MinimalSymbolDumper.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. //===- MinimalSymbolDumper.cpp -------------------------------- *- C++ --*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "MinimalSymbolDumper.h"
  9. #include "FormatUtil.h"
  10. #include "InputFile.h"
  11. #include "LinePrinter.h"
  12. #include "llvm/DebugInfo/CodeView/CVRecord.h"
  13. #include "llvm/DebugInfo/CodeView/CodeView.h"
  14. #include "llvm/DebugInfo/CodeView/Formatters.h"
  15. #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
  16. #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
  17. #include "llvm/DebugInfo/CodeView/TypeRecord.h"
  18. #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
  19. #include "llvm/Support/FormatVariadic.h"
  20. using namespace llvm;
  21. using namespace llvm::codeview;
  22. using namespace llvm::pdb;
  23. static std::string formatLocalSymFlags(uint32_t IndentLevel,
  24. LocalSymFlags Flags) {
  25. std::vector<std::string> Opts;
  26. if (Flags == LocalSymFlags::None)
  27. return "none";
  28. PUSH_FLAG(LocalSymFlags, IsParameter, Flags, "param");
  29. PUSH_FLAG(LocalSymFlags, IsAddressTaken, Flags, "address is taken");
  30. PUSH_FLAG(LocalSymFlags, IsCompilerGenerated, Flags, "compiler generated");
  31. PUSH_FLAG(LocalSymFlags, IsAggregate, Flags, "aggregate");
  32. PUSH_FLAG(LocalSymFlags, IsAggregated, Flags, "aggregated");
  33. PUSH_FLAG(LocalSymFlags, IsAliased, Flags, "aliased");
  34. PUSH_FLAG(LocalSymFlags, IsAlias, Flags, "alias");
  35. PUSH_FLAG(LocalSymFlags, IsReturnValue, Flags, "return val");
  36. PUSH_FLAG(LocalSymFlags, IsOptimizedOut, Flags, "optimized away");
  37. PUSH_FLAG(LocalSymFlags, IsEnregisteredGlobal, Flags, "enreg global");
  38. PUSH_FLAG(LocalSymFlags, IsEnregisteredStatic, Flags, "enreg static");
  39. return typesetItemList(Opts, 4, IndentLevel, " | ");
  40. }
  41. static std::string formatExportFlags(uint32_t IndentLevel, ExportFlags Flags) {
  42. std::vector<std::string> Opts;
  43. if (Flags == ExportFlags::None)
  44. return "none";
  45. PUSH_FLAG(ExportFlags, IsConstant, Flags, "constant");
  46. PUSH_FLAG(ExportFlags, IsData, Flags, "data");
  47. PUSH_FLAG(ExportFlags, IsPrivate, Flags, "private");
  48. PUSH_FLAG(ExportFlags, HasNoName, Flags, "no name");
  49. PUSH_FLAG(ExportFlags, HasExplicitOrdinal, Flags, "explicit ord");
  50. PUSH_FLAG(ExportFlags, IsForwarder, Flags, "forwarder");
  51. return typesetItemList(Opts, 4, IndentLevel, " | ");
  52. }
  53. static std::string formatCompileSym2Flags(uint32_t IndentLevel,
  54. CompileSym2Flags Flags) {
  55. std::vector<std::string> Opts;
  56. Flags &= ~CompileSym2Flags::SourceLanguageMask;
  57. if (Flags == CompileSym2Flags::None)
  58. return "none";
  59. PUSH_FLAG(CompileSym2Flags, EC, Flags, "edit and continue");
  60. PUSH_FLAG(CompileSym2Flags, NoDbgInfo, Flags, "no dbg info");
  61. PUSH_FLAG(CompileSym2Flags, LTCG, Flags, "ltcg");
  62. PUSH_FLAG(CompileSym2Flags, NoDataAlign, Flags, "no data align");
  63. PUSH_FLAG(CompileSym2Flags, ManagedPresent, Flags, "has managed code");
  64. PUSH_FLAG(CompileSym2Flags, SecurityChecks, Flags, "security checks");
  65. PUSH_FLAG(CompileSym2Flags, HotPatch, Flags, "hot patchable");
  66. PUSH_FLAG(CompileSym2Flags, CVTCIL, Flags, "cvtcil");
  67. PUSH_FLAG(CompileSym2Flags, MSILModule, Flags, "msil module");
  68. return typesetItemList(Opts, 4, IndentLevel, " | ");
  69. }
  70. static std::string formatCompileSym3Flags(uint32_t IndentLevel,
  71. CompileSym3Flags Flags) {
  72. std::vector<std::string> Opts;
  73. Flags &= ~CompileSym3Flags::SourceLanguageMask;
  74. if (Flags == CompileSym3Flags::None)
  75. return "none";
  76. PUSH_FLAG(CompileSym3Flags, EC, Flags, "edit and continue");
  77. PUSH_FLAG(CompileSym3Flags, NoDbgInfo, Flags, "no dbg info");
  78. PUSH_FLAG(CompileSym3Flags, LTCG, Flags, "ltcg");
  79. PUSH_FLAG(CompileSym3Flags, NoDataAlign, Flags, "no data align");
  80. PUSH_FLAG(CompileSym3Flags, ManagedPresent, Flags, "has managed code");
  81. PUSH_FLAG(CompileSym3Flags, SecurityChecks, Flags, "security checks");
  82. PUSH_FLAG(CompileSym3Flags, HotPatch, Flags, "hot patchable");
  83. PUSH_FLAG(CompileSym3Flags, CVTCIL, Flags, "cvtcil");
  84. PUSH_FLAG(CompileSym3Flags, MSILModule, Flags, "msil module");
  85. PUSH_FLAG(CompileSym3Flags, Sdl, Flags, "sdl");
  86. PUSH_FLAG(CompileSym3Flags, PGO, Flags, "pgo");
  87. PUSH_FLAG(CompileSym3Flags, Exp, Flags, "exp");
  88. return typesetItemList(Opts, 4, IndentLevel, " | ");
  89. }
  90. static std::string formatFrameProcedureOptions(uint32_t IndentLevel,
  91. FrameProcedureOptions FPO) {
  92. std::vector<std::string> Opts;
  93. if (FPO == FrameProcedureOptions::None)
  94. return "none";
  95. PUSH_FLAG(FrameProcedureOptions, HasAlloca, FPO, "has alloca");
  96. PUSH_FLAG(FrameProcedureOptions, HasSetJmp, FPO, "has setjmp");
  97. PUSH_FLAG(FrameProcedureOptions, HasLongJmp, FPO, "has longjmp");
  98. PUSH_FLAG(FrameProcedureOptions, HasInlineAssembly, FPO, "has inline asm");
  99. PUSH_FLAG(FrameProcedureOptions, HasExceptionHandling, FPO, "has eh");
  100. PUSH_FLAG(FrameProcedureOptions, MarkedInline, FPO, "marked inline");
  101. PUSH_FLAG(FrameProcedureOptions, HasStructuredExceptionHandling, FPO,
  102. "has seh");
  103. PUSH_FLAG(FrameProcedureOptions, Naked, FPO, "naked");
  104. PUSH_FLAG(FrameProcedureOptions, SecurityChecks, FPO, "secure checks");
  105. PUSH_FLAG(FrameProcedureOptions, AsynchronousExceptionHandling, FPO,
  106. "has async eh");
  107. PUSH_FLAG(FrameProcedureOptions, NoStackOrderingForSecurityChecks, FPO,
  108. "no stack order");
  109. PUSH_FLAG(FrameProcedureOptions, Inlined, FPO, "inlined");
  110. PUSH_FLAG(FrameProcedureOptions, StrictSecurityChecks, FPO,
  111. "strict secure checks");
  112. PUSH_FLAG(FrameProcedureOptions, SafeBuffers, FPO, "safe buffers");
  113. PUSH_FLAG(FrameProcedureOptions, ProfileGuidedOptimization, FPO, "pgo");
  114. PUSH_FLAG(FrameProcedureOptions, ValidProfileCounts, FPO,
  115. "has profile counts");
  116. PUSH_FLAG(FrameProcedureOptions, OptimizedForSpeed, FPO, "opt speed");
  117. PUSH_FLAG(FrameProcedureOptions, GuardCfg, FPO, "guard cfg");
  118. PUSH_FLAG(FrameProcedureOptions, GuardCfw, FPO, "guard cfw");
  119. return typesetItemList(Opts, 4, IndentLevel, " | ");
  120. }
  121. static std::string formatPublicSymFlags(uint32_t IndentLevel,
  122. PublicSymFlags Flags) {
  123. std::vector<std::string> Opts;
  124. if (Flags == PublicSymFlags::None)
  125. return "none";
  126. PUSH_FLAG(PublicSymFlags, Code, Flags, "code");
  127. PUSH_FLAG(PublicSymFlags, Function, Flags, "function");
  128. PUSH_FLAG(PublicSymFlags, Managed, Flags, "managed");
  129. PUSH_FLAG(PublicSymFlags, MSIL, Flags, "msil");
  130. return typesetItemList(Opts, 4, IndentLevel, " | ");
  131. }
  132. static std::string formatProcSymFlags(uint32_t IndentLevel,
  133. ProcSymFlags Flags) {
  134. std::vector<std::string> Opts;
  135. if (Flags == ProcSymFlags::None)
  136. return "none";
  137. PUSH_FLAG(ProcSymFlags, HasFP, Flags, "has fp");
  138. PUSH_FLAG(ProcSymFlags, HasIRET, Flags, "has iret");
  139. PUSH_FLAG(ProcSymFlags, HasFRET, Flags, "has fret");
  140. PUSH_FLAG(ProcSymFlags, IsNoReturn, Flags, "noreturn");
  141. PUSH_FLAG(ProcSymFlags, IsUnreachable, Flags, "unreachable");
  142. PUSH_FLAG(ProcSymFlags, HasCustomCallingConv, Flags, "custom calling conv");
  143. PUSH_FLAG(ProcSymFlags, IsNoInline, Flags, "noinline");
  144. PUSH_FLAG(ProcSymFlags, HasOptimizedDebugInfo, Flags, "opt debuginfo");
  145. return typesetItemList(Opts, 4, IndentLevel, " | ");
  146. }
  147. static std::string formatThunkOrdinal(ThunkOrdinal Ordinal) {
  148. switch (Ordinal) {
  149. RETURN_CASE(ThunkOrdinal, Standard, "thunk");
  150. RETURN_CASE(ThunkOrdinal, ThisAdjustor, "this adjustor");
  151. RETURN_CASE(ThunkOrdinal, Vcall, "vcall");
  152. RETURN_CASE(ThunkOrdinal, Pcode, "pcode");
  153. RETURN_CASE(ThunkOrdinal, UnknownLoad, "unknown load");
  154. RETURN_CASE(ThunkOrdinal, TrampIncremental, "tramp incremental");
  155. RETURN_CASE(ThunkOrdinal, BranchIsland, "branch island");
  156. }
  157. return formatUnknownEnum(Ordinal);
  158. }
  159. static std::string formatTrampolineType(TrampolineType Tramp) {
  160. switch (Tramp) {
  161. RETURN_CASE(TrampolineType, TrampIncremental, "tramp incremental");
  162. RETURN_CASE(TrampolineType, BranchIsland, "branch island");
  163. }
  164. return formatUnknownEnum(Tramp);
  165. }
  166. static std::string formatSourceLanguage(SourceLanguage Lang) {
  167. switch (Lang) {
  168. RETURN_CASE(SourceLanguage, C, "c");
  169. RETURN_CASE(SourceLanguage, Cpp, "c++");
  170. RETURN_CASE(SourceLanguage, Fortran, "fortran");
  171. RETURN_CASE(SourceLanguage, Masm, "masm");
  172. RETURN_CASE(SourceLanguage, Pascal, "pascal");
  173. RETURN_CASE(SourceLanguage, Basic, "basic");
  174. RETURN_CASE(SourceLanguage, Cobol, "cobol");
  175. RETURN_CASE(SourceLanguage, Link, "link");
  176. RETURN_CASE(SourceLanguage, VB, "vb");
  177. RETURN_CASE(SourceLanguage, Cvtres, "cvtres");
  178. RETURN_CASE(SourceLanguage, Cvtpgd, "cvtpgd");
  179. RETURN_CASE(SourceLanguage, CSharp, "c#");
  180. RETURN_CASE(SourceLanguage, ILAsm, "il asm");
  181. RETURN_CASE(SourceLanguage, Java, "java");
  182. RETURN_CASE(SourceLanguage, JScript, "javascript");
  183. RETURN_CASE(SourceLanguage, MSIL, "msil");
  184. RETURN_CASE(SourceLanguage, HLSL, "hlsl");
  185. RETURN_CASE(SourceLanguage, D, "d");
  186. RETURN_CASE(SourceLanguage, Swift, "swift");
  187. RETURN_CASE(SourceLanguage, Rust, "rust");
  188. }
  189. return formatUnknownEnum(Lang);
  190. }
  191. static std::string formatMachineType(CPUType Cpu) {
  192. switch (Cpu) {
  193. RETURN_CASE(CPUType, Intel8080, "intel 8080");
  194. RETURN_CASE(CPUType, Intel8086, "intel 8086");
  195. RETURN_CASE(CPUType, Intel80286, "intel 80286");
  196. RETURN_CASE(CPUType, Intel80386, "intel 80386");
  197. RETURN_CASE(CPUType, Intel80486, "intel 80486");
  198. RETURN_CASE(CPUType, Pentium, "intel pentium");
  199. RETURN_CASE(CPUType, PentiumPro, "intel pentium pro");
  200. RETURN_CASE(CPUType, Pentium3, "intel pentium 3");
  201. RETURN_CASE(CPUType, MIPS, "mips");
  202. RETURN_CASE(CPUType, MIPS16, "mips-16");
  203. RETURN_CASE(CPUType, MIPS32, "mips-32");
  204. RETURN_CASE(CPUType, MIPS64, "mips-64");
  205. RETURN_CASE(CPUType, MIPSI, "mips i");
  206. RETURN_CASE(CPUType, MIPSII, "mips ii");
  207. RETURN_CASE(CPUType, MIPSIII, "mips iii");
  208. RETURN_CASE(CPUType, MIPSIV, "mips iv");
  209. RETURN_CASE(CPUType, MIPSV, "mips v");
  210. RETURN_CASE(CPUType, M68000, "motorola 68000");
  211. RETURN_CASE(CPUType, M68010, "motorola 68010");
  212. RETURN_CASE(CPUType, M68020, "motorola 68020");
  213. RETURN_CASE(CPUType, M68030, "motorola 68030");
  214. RETURN_CASE(CPUType, M68040, "motorola 68040");
  215. RETURN_CASE(CPUType, Alpha, "alpha");
  216. RETURN_CASE(CPUType, Alpha21164, "alpha 21164");
  217. RETURN_CASE(CPUType, Alpha21164A, "alpha 21164a");
  218. RETURN_CASE(CPUType, Alpha21264, "alpha 21264");
  219. RETURN_CASE(CPUType, Alpha21364, "alpha 21364");
  220. RETURN_CASE(CPUType, PPC601, "powerpc 601");
  221. RETURN_CASE(CPUType, PPC603, "powerpc 603");
  222. RETURN_CASE(CPUType, PPC604, "powerpc 604");
  223. RETURN_CASE(CPUType, PPC620, "powerpc 620");
  224. RETURN_CASE(CPUType, PPCFP, "powerpc fp");
  225. RETURN_CASE(CPUType, PPCBE, "powerpc be");
  226. RETURN_CASE(CPUType, SH3, "sh3");
  227. RETURN_CASE(CPUType, SH3E, "sh3e");
  228. RETURN_CASE(CPUType, SH3DSP, "sh3 dsp");
  229. RETURN_CASE(CPUType, SH4, "sh4");
  230. RETURN_CASE(CPUType, SHMedia, "shmedia");
  231. RETURN_CASE(CPUType, ARM3, "arm 3");
  232. RETURN_CASE(CPUType, ARM4, "arm 4");
  233. RETURN_CASE(CPUType, ARM4T, "arm 4t");
  234. RETURN_CASE(CPUType, ARM5, "arm 5");
  235. RETURN_CASE(CPUType, ARM5T, "arm 5t");
  236. RETURN_CASE(CPUType, ARM6, "arm 6");
  237. RETURN_CASE(CPUType, ARM_XMAC, "arm xmac");
  238. RETURN_CASE(CPUType, ARM_WMMX, "arm wmmx");
  239. RETURN_CASE(CPUType, ARM7, "arm 7");
  240. RETURN_CASE(CPUType, ARM64, "arm64");
  241. RETURN_CASE(CPUType, ARM64EC, "arm64ec");
  242. RETURN_CASE(CPUType, ARM64X, "arm64x");
  243. RETURN_CASE(CPUType, HybridX86ARM64, "hybrid x86 arm64");
  244. RETURN_CASE(CPUType, Omni, "omni");
  245. RETURN_CASE(CPUType, Ia64, "intel itanium ia64");
  246. RETURN_CASE(CPUType, Ia64_2, "intel itanium ia64 2");
  247. RETURN_CASE(CPUType, CEE, "cee");
  248. RETURN_CASE(CPUType, AM33, "am33");
  249. RETURN_CASE(CPUType, M32R, "m32r");
  250. RETURN_CASE(CPUType, TriCore, "tri-core");
  251. RETURN_CASE(CPUType, X64, "intel x86-x64");
  252. RETURN_CASE(CPUType, EBC, "ebc");
  253. RETURN_CASE(CPUType, Thumb, "thumb");
  254. RETURN_CASE(CPUType, ARMNT, "arm nt");
  255. RETURN_CASE(CPUType, D3D11_Shader, "d3d11 shader");
  256. }
  257. return formatUnknownEnum(Cpu);
  258. }
  259. static std::string formatCookieKind(FrameCookieKind Kind) {
  260. switch (Kind) {
  261. RETURN_CASE(FrameCookieKind, Copy, "copy");
  262. RETURN_CASE(FrameCookieKind, XorStackPointer, "xor stack ptr");
  263. RETURN_CASE(FrameCookieKind, XorFramePointer, "xor frame ptr");
  264. RETURN_CASE(FrameCookieKind, XorR13, "xor rot13");
  265. }
  266. return formatUnknownEnum(Kind);
  267. }
  268. static std::string formatRegisterId(RegisterId Id, CPUType Cpu) {
  269. if (Cpu == CPUType::ARMNT) {
  270. switch (Id) {
  271. #define CV_REGISTERS_ARM
  272. #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
  273. #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
  274. #undef CV_REGISTER
  275. #undef CV_REGISTERS_ARM
  276. default:
  277. break;
  278. }
  279. } else if (Cpu == CPUType::ARM64) {
  280. switch (Id) {
  281. #define CV_REGISTERS_ARM64
  282. #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
  283. #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
  284. #undef CV_REGISTER
  285. #undef CV_REGISTERS_ARM64
  286. default:
  287. break;
  288. }
  289. } else {
  290. switch (Id) {
  291. #define CV_REGISTERS_X86
  292. #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
  293. #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
  294. #undef CV_REGISTER
  295. #undef CV_REGISTERS_X86
  296. default:
  297. break;
  298. }
  299. }
  300. return formatUnknownEnum(Id);
  301. }
  302. static std::string formatRegisterId(uint16_t Reg16, CPUType Cpu) {
  303. return formatRegisterId(RegisterId(Reg16), Cpu);
  304. }
  305. static std::string formatRegisterId(ulittle16_t &Reg16, CPUType Cpu) {
  306. return formatRegisterId(uint16_t(Reg16), Cpu);
  307. }
  308. static std::string formatRange(LocalVariableAddrRange Range) {
  309. return formatv("[{0},+{1})",
  310. formatSegmentOffset(Range.ISectStart, Range.OffsetStart),
  311. Range.Range)
  312. .str();
  313. }
  314. static std::string formatGaps(uint32_t IndentLevel,
  315. ArrayRef<LocalVariableAddrGap> Gaps) {
  316. std::vector<std::string> GapStrs;
  317. for (const auto &G : Gaps) {
  318. GapStrs.push_back(formatv("({0},{1})", G.GapStartOffset, G.Range).str());
  319. }
  320. return typesetItemList(GapStrs, 7, IndentLevel, ", ");
  321. }
  322. Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record) {
  323. return visitSymbolBegin(Record, 0);
  324. }
  325. Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record,
  326. uint32_t Offset) {
  327. // formatLine puts the newline at the beginning, so we use formatLine here
  328. // to start a new line, and then individual visit methods use format to
  329. // append to the existing line.
  330. P.formatLine("{0} | {1} [size = {2}]",
  331. fmt_align(Offset, AlignStyle::Right, 6),
  332. formatSymbolKind(Record.kind()), Record.length());
  333. P.Indent();
  334. return Error::success();
  335. }
  336. Error MinimalSymbolDumper::visitSymbolEnd(CVSymbol &Record) {
  337. if (RecordBytes) {
  338. AutoIndent Indent(P, 7);
  339. P.formatBinary("bytes", Record.content(), 0);
  340. }
  341. P.Unindent();
  342. return Error::success();
  343. }
  344. std::string MinimalSymbolDumper::typeOrIdIndex(codeview::TypeIndex TI,
  345. bool IsType) const {
  346. if (TI.isSimple() || TI.isDecoratedItemId())
  347. return formatv("{0}", TI).str();
  348. auto &Container = IsType ? Types : Ids;
  349. StringRef Name = Container.getTypeName(TI);
  350. if (Name.size() > 32) {
  351. Name = Name.take_front(32);
  352. return std::string(formatv("{0} ({1}...)", TI, Name));
  353. } else
  354. return std::string(formatv("{0} ({1})", TI, Name));
  355. }
  356. std::string MinimalSymbolDumper::idIndex(codeview::TypeIndex TI) const {
  357. return typeOrIdIndex(TI, false);
  358. }
  359. std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
  360. return typeOrIdIndex(TI, true);
  361. }
  362. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
  363. P.format(" `{0}`", Block.Name);
  364. AutoIndent Indent(P, 7);
  365. P.formatLine("parent = {0}, end = {1}", Block.Parent, Block.End);
  366. P.formatLine("code size = {0}, addr = {1}", Block.CodeSize,
  367. formatSegmentOffset(Block.Segment, Block.CodeOffset));
  368. return Error::success();
  369. }
  370. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
  371. P.format(" `{0}`", Thunk.Name);
  372. AutoIndent Indent(P, 7);
  373. P.formatLine("parent = {0}, end = {1}, next = {2}", Thunk.Parent, Thunk.End,
  374. Thunk.Next);
  375. P.formatLine("kind = {0}, size = {1}, addr = {2}",
  376. formatThunkOrdinal(Thunk.Thunk), Thunk.Length,
  377. formatSegmentOffset(Thunk.Segment, Thunk.Offset));
  378. return Error::success();
  379. }
  380. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  381. TrampolineSym &Tramp) {
  382. AutoIndent Indent(P, 7);
  383. P.formatLine("type = {0}, size = {1}, source = {2}, target = {3}",
  384. formatTrampolineType(Tramp.Type), Tramp.Size,
  385. formatSegmentOffset(Tramp.ThunkSection, Tramp.ThunkOffset),
  386. formatSegmentOffset(Tramp.TargetSection, Tramp.ThunkOffset));
  387. return Error::success();
  388. }
  389. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  390. SectionSym &Section) {
  391. P.format(" `{0}`", Section.Name);
  392. AutoIndent Indent(P, 7);
  393. P.formatLine("length = {0}, alignment = {1}, rva = {2}, section # = {3}",
  394. Section.Length, Section.Alignment, Section.Rva,
  395. Section.SectionNumber);
  396. P.printLine("characteristics =");
  397. AutoIndent Indent2(P, 2);
  398. P.printLine(formatSectionCharacteristics(P.getIndentLevel(),
  399. Section.Characteristics, 1, "",
  400. CharacteristicStyle::Descriptive));
  401. return Error::success();
  402. }
  403. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CoffGroupSym &CG) {
  404. P.format(" `{0}`", CG.Name);
  405. AutoIndent Indent(P, 7);
  406. P.formatLine("length = {0}, addr = {1}", CG.Size,
  407. formatSegmentOffset(CG.Segment, CG.Offset));
  408. P.printLine("characteristics =");
  409. AutoIndent Indent2(P, 2);
  410. P.printLine(formatSectionCharacteristics(P.getIndentLevel(),
  411. CG.Characteristics, 1, "",
  412. CharacteristicStyle::Descriptive));
  413. return Error::success();
  414. }
  415. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  416. BPRelativeSym &BPRel) {
  417. P.format(" `{0}`", BPRel.Name);
  418. AutoIndent Indent(P, 7);
  419. P.formatLine("type = {0}, offset = {1}", typeIndex(BPRel.Type), BPRel.Offset);
  420. return Error::success();
  421. }
  422. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  423. BuildInfoSym &BuildInfo) {
  424. P.format(" BuildId = `{0}`", BuildInfo.BuildId);
  425. return Error::success();
  426. }
  427. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  428. CallSiteInfoSym &CSI) {
  429. AutoIndent Indent(P, 7);
  430. P.formatLine("type = {0}, addr = {1}", typeIndex(CSI.Type),
  431. formatSegmentOffset(CSI.Segment, CSI.CodeOffset));
  432. return Error::success();
  433. }
  434. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  435. EnvBlockSym &EnvBlock) {
  436. AutoIndent Indent(P, 7);
  437. for (const auto &Entry : EnvBlock.Fields) {
  438. P.formatLine("- {0}", Entry);
  439. }
  440. return Error::success();
  441. }
  442. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FS) {
  443. P.format(" `{0}`", FS.Name);
  444. AutoIndent Indent(P, 7);
  445. if (SymGroup) {
  446. Expected<StringRef> FileName =
  447. SymGroup->getNameFromStringTable(FS.ModFilenameOffset);
  448. if (FileName) {
  449. P.formatLine("type = {0}, file name = {1} ({2}), flags = {3}",
  450. typeIndex(FS.Index), FS.ModFilenameOffset, *FileName,
  451. formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags));
  452. }
  453. return Error::success();
  454. }
  455. P.formatLine("type = {0}, file name offset = {1}, flags = {2}",
  456. typeIndex(FS.Index), FS.ModFilenameOffset,
  457. formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags));
  458. return Error::success();
  459. }
  460. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
  461. P.format(" `{0}`", Export.Name);
  462. AutoIndent Indent(P, 7);
  463. P.formatLine("ordinal = {0}, flags = {1}", Export.Ordinal,
  464. formatExportFlags(P.getIndentLevel() + 9, Export.Flags));
  465. return Error::success();
  466. }
  467. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  468. Compile2Sym &Compile2) {
  469. AutoIndent Indent(P, 7);
  470. SourceLanguage Lang = static_cast<SourceLanguage>(
  471. Compile2.Flags & CompileSym2Flags::SourceLanguageMask);
  472. CompilationCPU = Compile2.Machine;
  473. P.formatLine("machine = {0}, ver = {1}, language = {2}",
  474. formatMachineType(Compile2.Machine), Compile2.Version,
  475. formatSourceLanguage(Lang));
  476. P.formatLine("frontend = {0}.{1}.{2}, backend = {3}.{4}.{5}",
  477. Compile2.VersionFrontendMajor, Compile2.VersionFrontendMinor,
  478. Compile2.VersionFrontendBuild, Compile2.VersionBackendMajor,
  479. Compile2.VersionBackendMinor, Compile2.VersionBackendBuild);
  480. P.formatLine("flags = {0}",
  481. formatCompileSym2Flags(P.getIndentLevel() + 9, Compile2.Flags));
  482. P.formatLine(
  483. "extra strings = {0}",
  484. typesetStringList(P.getIndentLevel() + 9 + 2, Compile2.ExtraStrings));
  485. return Error::success();
  486. }
  487. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  488. Compile3Sym &Compile3) {
  489. AutoIndent Indent(P, 7);
  490. SourceLanguage Lang = static_cast<SourceLanguage>(
  491. Compile3.Flags & CompileSym3Flags::SourceLanguageMask);
  492. CompilationCPU = Compile3.Machine;
  493. P.formatLine("machine = {0}, Ver = {1}, language = {2}",
  494. formatMachineType(Compile3.Machine), Compile3.Version,
  495. formatSourceLanguage(Lang));
  496. P.formatLine("frontend = {0}.{1}.{2}.{3}, backend = {4}.{5}.{6}.{7}",
  497. Compile3.VersionFrontendMajor, Compile3.VersionFrontendMinor,
  498. Compile3.VersionFrontendBuild, Compile3.VersionFrontendQFE,
  499. Compile3.VersionBackendMajor, Compile3.VersionBackendMinor,
  500. Compile3.VersionBackendBuild, Compile3.VersionBackendQFE);
  501. P.formatLine("flags = {0}",
  502. formatCompileSym3Flags(P.getIndentLevel() + 9, Compile3.Flags));
  503. return Error::success();
  504. }
  505. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  506. ConstantSym &Constant) {
  507. P.format(" `{0}`", Constant.Name);
  508. AutoIndent Indent(P, 7);
  509. P.formatLine("type = {0}, value = {1}", typeIndex(Constant.Type),
  510. toString(Constant.Value, 10));
  511. return Error::success();
  512. }
  513. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
  514. P.format(" `{0}`", Data.Name);
  515. AutoIndent Indent(P, 7);
  516. P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type),
  517. formatSegmentOffset(Data.Segment, Data.DataOffset));
  518. return Error::success();
  519. }
  520. Error MinimalSymbolDumper::visitKnownRecord(
  521. CVSymbol &CVR, DefRangeFramePointerRelFullScopeSym &Def) {
  522. P.format(" offset = {0}", Def.Offset);
  523. return Error::success();
  524. }
  525. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  526. DefRangeFramePointerRelSym &Def) {
  527. AutoIndent Indent(P, 7);
  528. P.formatLine("offset = {0}, range = {1}", Def.Hdr.Offset,
  529. formatRange(Def.Range));
  530. P.formatLine("gaps = [{0}]", formatGaps(P.getIndentLevel() + 9, Def.Gaps));
  531. return Error::success();
  532. }
  533. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  534. DefRangeRegisterRelSym &Def) {
  535. AutoIndent Indent(P, 7);
  536. P.formatLine("register = {0}, offset = {1}, offset in parent = {2}, has "
  537. "spilled udt = {3}",
  538. formatRegisterId(Def.Hdr.Register, CompilationCPU),
  539. int32_t(Def.Hdr.BasePointerOffset), Def.offsetInParent(),
  540. Def.hasSpilledUDTMember());
  541. P.formatLine("range = {0}, gaps = [{1}]", formatRange(Def.Range),
  542. formatGaps(P.getIndentLevel() + 9, Def.Gaps));
  543. return Error::success();
  544. }
  545. Error MinimalSymbolDumper::visitKnownRecord(
  546. CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
  547. AutoIndent Indent(P, 7);
  548. P.formatLine("register = {0}, may have no name = {1}, range start = "
  549. "{2}, length = {3}",
  550. formatRegisterId(DefRangeRegister.Hdr.Register, CompilationCPU),
  551. bool(DefRangeRegister.Hdr.MayHaveNoName),
  552. formatSegmentOffset(DefRangeRegister.Range.ISectStart,
  553. DefRangeRegister.Range.OffsetStart),
  554. DefRangeRegister.Range.Range);
  555. P.formatLine("gaps = [{0}]",
  556. formatGaps(P.getIndentLevel() + 9, DefRangeRegister.Gaps));
  557. return Error::success();
  558. }
  559. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  560. DefRangeSubfieldRegisterSym &Def) {
  561. AutoIndent Indent(P, 7);
  562. bool NoName = !!(Def.Hdr.MayHaveNoName == 0);
  563. P.formatLine("register = {0}, may have no name = {1}, offset in parent = {2}",
  564. formatRegisterId(Def.Hdr.Register, CompilationCPU), NoName,
  565. uint32_t(Def.Hdr.OffsetInParent));
  566. P.formatLine("range = {0}, gaps = [{1}]", formatRange(Def.Range),
  567. formatGaps(P.getIndentLevel() + 9, Def.Gaps));
  568. return Error::success();
  569. }
  570. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  571. DefRangeSubfieldSym &Def) {
  572. AutoIndent Indent(P, 7);
  573. P.formatLine("program = {0}, offset in parent = {1}, range = {2}",
  574. Def.Program, Def.OffsetInParent, formatRange(Def.Range));
  575. P.formatLine("gaps = [{0}]", formatGaps(P.getIndentLevel() + 9, Def.Gaps));
  576. return Error::success();
  577. }
  578. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DefRangeSym &Def) {
  579. AutoIndent Indent(P, 7);
  580. P.formatLine("program = {0}, range = {1}", Def.Program,
  581. formatRange(Def.Range));
  582. P.formatLine("gaps = [{0}]", formatGaps(P.getIndentLevel() + 9, Def.Gaps));
  583. return Error::success();
  584. }
  585. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameCookieSym &FC) {
  586. AutoIndent Indent(P, 7);
  587. P.formatLine("code offset = {0}, Register = {1}, kind = {2}, flags = {3}",
  588. FC.CodeOffset, formatRegisterId(FC.Register, CompilationCPU),
  589. formatCookieKind(FC.CookieKind), FC.Flags);
  590. return Error::success();
  591. }
  592. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameProcSym &FP) {
  593. AutoIndent Indent(P, 7);
  594. P.formatLine("size = {0}, padding size = {1}, offset to padding = {2}",
  595. FP.TotalFrameBytes, FP.PaddingFrameBytes, FP.OffsetToPadding);
  596. P.formatLine("bytes of callee saved registers = {0}, exception handler addr "
  597. "= {1}",
  598. FP.BytesOfCalleeSavedRegisters,
  599. formatSegmentOffset(FP.SectionIdOfExceptionHandler,
  600. FP.OffsetOfExceptionHandler));
  601. P.formatLine(
  602. "local fp reg = {0}, param fp reg = {1}",
  603. formatRegisterId(FP.getLocalFramePtrReg(CompilationCPU), CompilationCPU),
  604. formatRegisterId(FP.getParamFramePtrReg(CompilationCPU), CompilationCPU));
  605. P.formatLine("flags = {0}",
  606. formatFrameProcedureOptions(P.getIndentLevel() + 9, FP.Flags));
  607. return Error::success();
  608. }
  609. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  610. HeapAllocationSiteSym &HAS) {
  611. AutoIndent Indent(P, 7);
  612. P.formatLine("type = {0}, addr = {1} call size = {2}", typeIndex(HAS.Type),
  613. formatSegmentOffset(HAS.Segment, HAS.CodeOffset),
  614. HAS.CallInstructionSize);
  615. return Error::success();
  616. }
  617. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, InlineSiteSym &IS) {
  618. AutoIndent Indent(P, 7);
  619. P.formatLine("inlinee = {0}, parent = {1}, end = {2}", idIndex(IS.Inlinee),
  620. IS.Parent, IS.End);
  621. // Break down the annotation byte code and calculate code and line offsets.
  622. // FIXME: It would be helpful if we could look up the initial file and inlinee
  623. // lines offset using the inlinee index above.
  624. uint32_t CodeOffset = 0;
  625. int32_t LineOffset = 0;
  626. for (auto &Annot : IS.annotations()) {
  627. P.formatLine(" {0}", fmt_align(toHex(Annot.Bytes), AlignStyle::Left, 9));
  628. auto formatCodeOffset = [&](uint32_t Delta) {
  629. CodeOffset += Delta;
  630. P.format(" code 0x{0} (+0x{1})", utohexstr(CodeOffset), utohexstr(Delta));
  631. };
  632. auto formatCodeLength = [&](uint32_t Length) {
  633. // Notably, changing the code length does not affect the code offset.
  634. P.format(" code end 0x{0} (+0x{1})", utohexstr(CodeOffset + Length),
  635. utohexstr(Length));
  636. };
  637. auto formatLineOffset = [&](int32_t Delta) {
  638. LineOffset += Delta;
  639. char Sign = Delta > 0 ? '+' : '-';
  640. P.format(" line {0} ({1}{2})", LineOffset, Sign, std::abs(Delta));
  641. };
  642. // Use the opcode to interpret the integer values.
  643. switch (Annot.OpCode) {
  644. case BinaryAnnotationsOpCode::Invalid:
  645. break;
  646. case BinaryAnnotationsOpCode::CodeOffset:
  647. case BinaryAnnotationsOpCode::ChangeCodeOffset:
  648. formatCodeOffset(Annot.U1);
  649. break;
  650. case BinaryAnnotationsOpCode::ChangeLineOffset:
  651. formatLineOffset(Annot.S1);
  652. break;
  653. case BinaryAnnotationsOpCode::ChangeCodeLength:
  654. formatCodeLength(Annot.U1);
  655. // Apparently this annotation updates the code offset. It's hard to make
  656. // MSVC produce this opcode, but clang uses it, and debuggers seem to use
  657. // this interpretation.
  658. CodeOffset += Annot.U1;
  659. break;
  660. case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
  661. formatCodeOffset(Annot.U1);
  662. formatLineOffset(Annot.S1);
  663. break;
  664. case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
  665. formatCodeOffset(Annot.U2);
  666. formatCodeLength(Annot.U1);
  667. break;
  668. case BinaryAnnotationsOpCode::ChangeFile: {
  669. uint32_t FileOffset = Annot.U1;
  670. StringRef Filename = "<unknown>";
  671. if (SymGroup) {
  672. if (Expected<StringRef> MaybeFile =
  673. SymGroup->getNameFromStringTable(FileOffset))
  674. Filename = *MaybeFile;
  675. else
  676. return MaybeFile.takeError();
  677. }
  678. P.format(" setfile {0} 0x{1}", utohexstr(FileOffset));
  679. break;
  680. }
  681. // The rest of these are hard to convince MSVC to emit, so they are not as
  682. // well understood.
  683. case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
  684. formatCodeOffset(Annot.U1);
  685. break;
  686. case BinaryAnnotationsOpCode::ChangeLineEndDelta:
  687. case BinaryAnnotationsOpCode::ChangeRangeKind:
  688. case BinaryAnnotationsOpCode::ChangeColumnStart:
  689. case BinaryAnnotationsOpCode::ChangeColumnEnd:
  690. P.format(" {0} {1}", Annot.Name, Annot.U1);
  691. break;
  692. case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
  693. P.format(" {0} {1}", Annot.Name, Annot.S1);
  694. break;
  695. }
  696. }
  697. return Error::success();
  698. }
  699. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  700. RegisterSym &Register) {
  701. P.format(" `{0}`", Register.Name);
  702. AutoIndent Indent(P, 7);
  703. P.formatLine("register = {0}, type = {1}",
  704. formatRegisterId(Register.Register, CompilationCPU),
  705. typeIndex(Register.Index));
  706. return Error::success();
  707. }
  708. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  709. PublicSym32 &Public) {
  710. P.format(" `{0}`", Public.Name);
  711. AutoIndent Indent(P, 7);
  712. P.formatLine("flags = {0}, addr = {1}",
  713. formatPublicSymFlags(P.getIndentLevel() + 9, Public.Flags),
  714. formatSegmentOffset(Public.Segment, Public.Offset));
  715. return Error::success();
  716. }
  717. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcRefSym &PR) {
  718. P.format(" `{0}`", PR.Name);
  719. AutoIndent Indent(P, 7);
  720. P.formatLine("module = {0}, sum name = {1}, offset = {2}", PR.Module,
  721. PR.SumName, PR.SymOffset);
  722. return Error::success();
  723. }
  724. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
  725. P.format(" `{0}` (addr = {1})", Label.Name,
  726. formatSegmentOffset(Label.Segment, Label.CodeOffset));
  727. AutoIndent Indent(P, 7);
  728. P.formatLine("flags = {0}",
  729. formatProcSymFlags(P.getIndentLevel() + 9, Label.Flags));
  730. return Error::success();
  731. }
  732. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
  733. P.format(" `{0}`", Local.Name);
  734. AutoIndent Indent(P, 7);
  735. std::string FlagStr =
  736. formatLocalSymFlags(P.getIndentLevel() + 9, Local.Flags);
  737. P.formatLine("type={0}, flags = {1}", typeIndex(Local.Type), FlagStr);
  738. return Error::success();
  739. }
  740. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  741. ObjNameSym &ObjName) {
  742. P.format(" sig={0}, `{1}`", ObjName.Signature, ObjName.Name);
  743. return Error::success();
  744. }
  745. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
  746. P.format(" `{0}`", Proc.Name);
  747. AutoIndent Indent(P, 7);
  748. P.formatLine("parent = {0}, end = {1}, addr = {2}, code size = {3}",
  749. Proc.Parent, Proc.End,
  750. formatSegmentOffset(Proc.Segment, Proc.CodeOffset),
  751. Proc.CodeSize);
  752. bool IsType = true;
  753. switch (Proc.getKind()) {
  754. case SymbolRecordKind::GlobalProcIdSym:
  755. case SymbolRecordKind::ProcIdSym:
  756. case SymbolRecordKind::DPCProcIdSym:
  757. IsType = false;
  758. break;
  759. default:
  760. break;
  761. }
  762. P.formatLine("type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}",
  763. typeOrIdIndex(Proc.FunctionType, IsType), Proc.DbgStart,
  764. Proc.DbgEnd,
  765. formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags));
  766. return Error::success();
  767. }
  768. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  769. ScopeEndSym &ScopeEnd) {
  770. return Error::success();
  771. }
  772. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
  773. AutoIndent Indent(P, 7);
  774. for (const auto &I : Caller.Indices) {
  775. P.formatLine("callee: {0}", idIndex(I));
  776. }
  777. return Error::success();
  778. }
  779. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  780. RegRelativeSym &RegRel) {
  781. P.format(" `{0}`", RegRel.Name);
  782. AutoIndent Indent(P, 7);
  783. P.formatLine(
  784. "type = {0}, register = {1}, offset = {2}", typeIndex(RegRel.Type),
  785. formatRegisterId(RegRel.Register, CompilationCPU), RegRel.Offset);
  786. return Error::success();
  787. }
  788. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  789. ThreadLocalDataSym &Data) {
  790. P.format(" `{0}`", Data.Name);
  791. AutoIndent Indent(P, 7);
  792. P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type),
  793. formatSegmentOffset(Data.Segment, Data.DataOffset));
  794. return Error::success();
  795. }
  796. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
  797. P.format(" `{0}`", UDT.Name);
  798. AutoIndent Indent(P, 7);
  799. P.formatLine("original type = {0}", UDT.Type);
  800. return Error::success();
  801. }
  802. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  803. UsingNamespaceSym &UN) {
  804. P.format(" `{0}`", UN.Name);
  805. return Error::success();
  806. }
  807. Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
  808. AnnotationSym &Annot) {
  809. AutoIndent Indent(P, 7);
  810. P.formatLine("addr = {0}", formatSegmentOffset(Annot.Segment, Annot.CodeOffset));
  811. P.formatLine("strings = {0}", typesetStringList(P.getIndentLevel() + 9 + 2,
  812. Annot.Strings));
  813. return Error::success();
  814. }