1 //===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
11 #include "llvm/ADT/DenseMap.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
14 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
15 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
16 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
17 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
18 #include "llvm/Support/ScopedPrinter.h"
19 
20 #include <system_error>
21 
22 using namespace llvm;
23 using namespace llvm::codeview;
24 
25 static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
26 #define CV_SYMBOL(enum, val) {#enum, enum},
27 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
28 };
29 
30 namespace {
31 #define CV_ENUM_CLASS_ENT(enum_class, enum)                                    \
32   { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
33 
34 #define CV_ENUM_ENT(ns, enum)                                                  \
35   { #enum, ns::enum }
36 
37 static const EnumEntry<uint16_t> RegisterNames[] = {
38     CV_ENUM_CLASS_ENT(RegisterId, Unknown),
39     CV_ENUM_CLASS_ENT(RegisterId, VFrame),
40     CV_ENUM_CLASS_ENT(RegisterId, AL),
41     CV_ENUM_CLASS_ENT(RegisterId, CL),
42     CV_ENUM_CLASS_ENT(RegisterId, DL),
43     CV_ENUM_CLASS_ENT(RegisterId, BL),
44     CV_ENUM_CLASS_ENT(RegisterId, AH),
45     CV_ENUM_CLASS_ENT(RegisterId, CH),
46     CV_ENUM_CLASS_ENT(RegisterId, DH),
47     CV_ENUM_CLASS_ENT(RegisterId, BH),
48     CV_ENUM_CLASS_ENT(RegisterId, AX),
49     CV_ENUM_CLASS_ENT(RegisterId, CX),
50     CV_ENUM_CLASS_ENT(RegisterId, DX),
51     CV_ENUM_CLASS_ENT(RegisterId, BX),
52     CV_ENUM_CLASS_ENT(RegisterId, SP),
53     CV_ENUM_CLASS_ENT(RegisterId, BP),
54     CV_ENUM_CLASS_ENT(RegisterId, SI),
55     CV_ENUM_CLASS_ENT(RegisterId, DI),
56     CV_ENUM_CLASS_ENT(RegisterId, EAX),
57     CV_ENUM_CLASS_ENT(RegisterId, ECX),
58     CV_ENUM_CLASS_ENT(RegisterId, EDX),
59     CV_ENUM_CLASS_ENT(RegisterId, EBX),
60     CV_ENUM_CLASS_ENT(RegisterId, ESP),
61     CV_ENUM_CLASS_ENT(RegisterId, EBP),
62     CV_ENUM_CLASS_ENT(RegisterId, ESI),
63     CV_ENUM_CLASS_ENT(RegisterId, EDI),
64     CV_ENUM_CLASS_ENT(RegisterId, ES),
65     CV_ENUM_CLASS_ENT(RegisterId, CS),
66     CV_ENUM_CLASS_ENT(RegisterId, SS),
67     CV_ENUM_CLASS_ENT(RegisterId, DS),
68     CV_ENUM_CLASS_ENT(RegisterId, FS),
69     CV_ENUM_CLASS_ENT(RegisterId, GS),
70     CV_ENUM_CLASS_ENT(RegisterId, IP),
71     CV_ENUM_CLASS_ENT(RegisterId, RAX),
72     CV_ENUM_CLASS_ENT(RegisterId, RBX),
73     CV_ENUM_CLASS_ENT(RegisterId, RCX),
74     CV_ENUM_CLASS_ENT(RegisterId, RDX),
75     CV_ENUM_CLASS_ENT(RegisterId, RSI),
76     CV_ENUM_CLASS_ENT(RegisterId, RDI),
77     CV_ENUM_CLASS_ENT(RegisterId, RBP),
78     CV_ENUM_CLASS_ENT(RegisterId, RSP),
79     CV_ENUM_CLASS_ENT(RegisterId, R8),
80     CV_ENUM_CLASS_ENT(RegisterId, R9),
81     CV_ENUM_CLASS_ENT(RegisterId, R10),
82     CV_ENUM_CLASS_ENT(RegisterId, R11),
83     CV_ENUM_CLASS_ENT(RegisterId, R12),
84     CV_ENUM_CLASS_ENT(RegisterId, R13),
85     CV_ENUM_CLASS_ENT(RegisterId, R14),
86     CV_ENUM_CLASS_ENT(RegisterId, R15),
87 };
88 
89 static const EnumEntry<uint8_t> ProcSymFlagNames[] = {
90     CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP),
91     CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET),
92     CV_ENUM_CLASS_ENT(ProcSymFlags, HasFRET),
93     CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoReturn),
94     CV_ENUM_CLASS_ENT(ProcSymFlags, IsUnreachable),
95     CV_ENUM_CLASS_ENT(ProcSymFlags, HasCustomCallingConv),
96     CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoInline),
97     CV_ENUM_CLASS_ENT(ProcSymFlags, HasOptimizedDebugInfo),
98 };
99 
100 static const EnumEntry<uint16_t> LocalFlags[] = {
101     CV_ENUM_CLASS_ENT(LocalSymFlags, IsParameter),
102     CV_ENUM_CLASS_ENT(LocalSymFlags, IsAddressTaken),
103     CV_ENUM_CLASS_ENT(LocalSymFlags, IsCompilerGenerated),
104     CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregate),
105     CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregated),
106     CV_ENUM_CLASS_ENT(LocalSymFlags, IsAliased),
107     CV_ENUM_CLASS_ENT(LocalSymFlags, IsAlias),
108     CV_ENUM_CLASS_ENT(LocalSymFlags, IsReturnValue),
109     CV_ENUM_CLASS_ENT(LocalSymFlags, IsOptimizedOut),
110     CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredGlobal),
111     CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredStatic),
112 };
113 
114 static const EnumEntry<uint32_t> FrameCookieKinds[] = {
115     CV_ENUM_CLASS_ENT(FrameCookieKind, Copy),
116     CV_ENUM_CLASS_ENT(FrameCookieKind, XorStackPointer),
117     CV_ENUM_CLASS_ENT(FrameCookieKind, XorFramePointer),
118     CV_ENUM_CLASS_ENT(FrameCookieKind, XorR13),
119 };
120 
121 static const EnumEntry<codeview::SourceLanguage> SourceLanguages[] = {
122     CV_ENUM_ENT(SourceLanguage, C),       CV_ENUM_ENT(SourceLanguage, Cpp),
123     CV_ENUM_ENT(SourceLanguage, Fortran), CV_ENUM_ENT(SourceLanguage, Masm),
124     CV_ENUM_ENT(SourceLanguage, Pascal),  CV_ENUM_ENT(SourceLanguage, Basic),
125     CV_ENUM_ENT(SourceLanguage, Cobol),   CV_ENUM_ENT(SourceLanguage, Link),
126     CV_ENUM_ENT(SourceLanguage, Cvtres),  CV_ENUM_ENT(SourceLanguage, Cvtpgd),
127     CV_ENUM_ENT(SourceLanguage, CSharp),  CV_ENUM_ENT(SourceLanguage, VB),
128     CV_ENUM_ENT(SourceLanguage, ILAsm),   CV_ENUM_ENT(SourceLanguage, Java),
129     CV_ENUM_ENT(SourceLanguage, JScript), CV_ENUM_ENT(SourceLanguage, MSIL),
130     CV_ENUM_ENT(SourceLanguage, HLSL),
131 };
132 
133 static const EnumEntry<uint32_t> CompileSym2FlagNames[] = {
134     CV_ENUM_CLASS_ENT(CompileSym2Flags, EC),
135     CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDbgInfo),
136     CV_ENUM_CLASS_ENT(CompileSym2Flags, LTCG),
137     CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDataAlign),
138     CV_ENUM_CLASS_ENT(CompileSym2Flags, ManagedPresent),
139     CV_ENUM_CLASS_ENT(CompileSym2Flags, SecurityChecks),
140     CV_ENUM_CLASS_ENT(CompileSym2Flags, HotPatch),
141     CV_ENUM_CLASS_ENT(CompileSym2Flags, CVTCIL),
142     CV_ENUM_CLASS_ENT(CompileSym2Flags, MSILModule),
143 };
144 
145 static const EnumEntry<uint32_t> CompileSym3FlagNames[] = {
146     CV_ENUM_CLASS_ENT(CompileSym3Flags, EC),
147     CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDbgInfo),
148     CV_ENUM_CLASS_ENT(CompileSym3Flags, LTCG),
149     CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDataAlign),
150     CV_ENUM_CLASS_ENT(CompileSym3Flags, ManagedPresent),
151     CV_ENUM_CLASS_ENT(CompileSym3Flags, SecurityChecks),
152     CV_ENUM_CLASS_ENT(CompileSym3Flags, HotPatch),
153     CV_ENUM_CLASS_ENT(CompileSym3Flags, CVTCIL),
154     CV_ENUM_CLASS_ENT(CompileSym3Flags, MSILModule),
155     CV_ENUM_CLASS_ENT(CompileSym3Flags, Sdl),
156     CV_ENUM_CLASS_ENT(CompileSym3Flags, PGO),
157     CV_ENUM_CLASS_ENT(CompileSym3Flags, Exp),
158 };
159 
160 static const EnumEntry<unsigned> CPUTypeNames[] = {
161     CV_ENUM_CLASS_ENT(CPUType, Intel8080),
162     CV_ENUM_CLASS_ENT(CPUType, Intel8086),
163     CV_ENUM_CLASS_ENT(CPUType, Intel80286),
164     CV_ENUM_CLASS_ENT(CPUType, Intel80386),
165     CV_ENUM_CLASS_ENT(CPUType, Intel80486),
166     CV_ENUM_CLASS_ENT(CPUType, Pentium),
167     CV_ENUM_CLASS_ENT(CPUType, PentiumPro),
168     CV_ENUM_CLASS_ENT(CPUType, Pentium3),
169     CV_ENUM_CLASS_ENT(CPUType, MIPS),
170     CV_ENUM_CLASS_ENT(CPUType, MIPS16),
171     CV_ENUM_CLASS_ENT(CPUType, MIPS32),
172     CV_ENUM_CLASS_ENT(CPUType, MIPS64),
173     CV_ENUM_CLASS_ENT(CPUType, MIPSI),
174     CV_ENUM_CLASS_ENT(CPUType, MIPSII),
175     CV_ENUM_CLASS_ENT(CPUType, MIPSIII),
176     CV_ENUM_CLASS_ENT(CPUType, MIPSIV),
177     CV_ENUM_CLASS_ENT(CPUType, MIPSV),
178     CV_ENUM_CLASS_ENT(CPUType, M68000),
179     CV_ENUM_CLASS_ENT(CPUType, M68010),
180     CV_ENUM_CLASS_ENT(CPUType, M68020),
181     CV_ENUM_CLASS_ENT(CPUType, M68030),
182     CV_ENUM_CLASS_ENT(CPUType, M68040),
183     CV_ENUM_CLASS_ENT(CPUType, Alpha),
184     CV_ENUM_CLASS_ENT(CPUType, Alpha21164),
185     CV_ENUM_CLASS_ENT(CPUType, Alpha21164A),
186     CV_ENUM_CLASS_ENT(CPUType, Alpha21264),
187     CV_ENUM_CLASS_ENT(CPUType, Alpha21364),
188     CV_ENUM_CLASS_ENT(CPUType, PPC601),
189     CV_ENUM_CLASS_ENT(CPUType, PPC603),
190     CV_ENUM_CLASS_ENT(CPUType, PPC604),
191     CV_ENUM_CLASS_ENT(CPUType, PPC620),
192     CV_ENUM_CLASS_ENT(CPUType, PPCFP),
193     CV_ENUM_CLASS_ENT(CPUType, PPCBE),
194     CV_ENUM_CLASS_ENT(CPUType, SH3),
195     CV_ENUM_CLASS_ENT(CPUType, SH3E),
196     CV_ENUM_CLASS_ENT(CPUType, SH3DSP),
197     CV_ENUM_CLASS_ENT(CPUType, SH4),
198     CV_ENUM_CLASS_ENT(CPUType, SHMedia),
199     CV_ENUM_CLASS_ENT(CPUType, ARM3),
200     CV_ENUM_CLASS_ENT(CPUType, ARM4),
201     CV_ENUM_CLASS_ENT(CPUType, ARM4T),
202     CV_ENUM_CLASS_ENT(CPUType, ARM5),
203     CV_ENUM_CLASS_ENT(CPUType, ARM5T),
204     CV_ENUM_CLASS_ENT(CPUType, ARM6),
205     CV_ENUM_CLASS_ENT(CPUType, ARM_XMAC),
206     CV_ENUM_CLASS_ENT(CPUType, ARM_WMMX),
207     CV_ENUM_CLASS_ENT(CPUType, ARM7),
208     CV_ENUM_CLASS_ENT(CPUType, Omni),
209     CV_ENUM_CLASS_ENT(CPUType, Ia64),
210     CV_ENUM_CLASS_ENT(CPUType, Ia64_2),
211     CV_ENUM_CLASS_ENT(CPUType, CEE),
212     CV_ENUM_CLASS_ENT(CPUType, AM33),
213     CV_ENUM_CLASS_ENT(CPUType, M32R),
214     CV_ENUM_CLASS_ENT(CPUType, TriCore),
215     CV_ENUM_CLASS_ENT(CPUType, X64),
216     CV_ENUM_CLASS_ENT(CPUType, EBC),
217     CV_ENUM_CLASS_ENT(CPUType, Thumb),
218     CV_ENUM_CLASS_ENT(CPUType, ARMNT),
219     CV_ENUM_CLASS_ENT(CPUType, D3D11_Shader),
220 };
221 
222 static const EnumEntry<uint32_t> FrameProcSymFlags[] = {
223     CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca),
224     CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp),
225     CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp),
226     CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly),
227     CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling),
228     CV_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline),
229     CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasStructuredExceptionHandling),
230     CV_ENUM_CLASS_ENT(FrameProcedureOptions, Naked),
231     CV_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks),
232     CV_ENUM_CLASS_ENT(FrameProcedureOptions, AsynchronousExceptionHandling),
233     CV_ENUM_CLASS_ENT(FrameProcedureOptions, NoStackOrderingForSecurityChecks),
234     CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined),
235     CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks),
236     CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers),
237     CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization),
238     CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts),
239     CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed),
240     CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg),
241     CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw),
242 };
243 
244 static const EnumEntry<uint16_t> ExportSymFlags[] = {
245     CV_ENUM_CLASS_ENT(ExportFlags, IsConstant),
246     CV_ENUM_CLASS_ENT(ExportFlags, IsData),
247     CV_ENUM_CLASS_ENT(ExportFlags, IsPrivate),
248     CV_ENUM_CLASS_ENT(ExportFlags, HasNoName),
249     CV_ENUM_CLASS_ENT(ExportFlags, HasExplicitOrdinal),
250     CV_ENUM_CLASS_ENT(ExportFlags, IsForwarder),
251 };
252 
253 static const EnumEntry<uint8_t> ThunkOrdinalNames[] = {
254     CV_ENUM_CLASS_ENT(ThunkOrdinal, Standard),
255     CV_ENUM_CLASS_ENT(ThunkOrdinal, ThisAdjustor),
256     CV_ENUM_CLASS_ENT(ThunkOrdinal, Vcall),
257     CV_ENUM_CLASS_ENT(ThunkOrdinal, Pcode),
258     CV_ENUM_CLASS_ENT(ThunkOrdinal, UnknownLoad),
259     CV_ENUM_CLASS_ENT(ThunkOrdinal, TrampIncremental),
260     CV_ENUM_CLASS_ENT(ThunkOrdinal, BranchIsland),
261 };
262 
263 static const EnumEntry<uint16_t> TrampolineNames[] = {
264     CV_ENUM_CLASS_ENT(TrampolineType, TrampIncremental),
265     CV_ENUM_CLASS_ENT(TrampolineType, BranchIsland),
266 };
267 
268 /// Use this private dumper implementation to keep implementation details about
269 /// the visitor out of SymbolDumper.h.
270 class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
271 public:
272   CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
273                      ScopedPrinter &W, bool PrintRecordBytes)
274       : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
275         W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
276 
277 /// CVSymbolVisitor overrides.
278 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
279   void visit##Name(SymbolKind Kind, Name &Record);
280 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
281 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
282 
283   void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
284   void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
285   void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
286 
287 private:
288   void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
289                                    uint32_t RelocationOffset);
290   void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
291 
292   CVTypeDumper &CVTD;
293   SymbolDumpDelegate *ObjDelegate;
294   ScopedPrinter &W;
295 
296   bool PrintRecordBytes;
297   bool InFunctionScope;
298 };
299 }
300 
301 void CVSymbolDumperImpl::printLocalVariableAddrRange(
302     const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
303   DictScope S(W, "LocalVariableAddrRange");
304   if (ObjDelegate)
305     ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
306                                      Range.OffsetStart);
307   W.printHex("ISectStart", Range.ISectStart);
308   W.printHex("Range", Range.Range);
309 }
310 
311 void CVSymbolDumperImpl::printLocalVariableAddrGap(
312     ArrayRef<LocalVariableAddrGap> Gaps) {
313   for (auto &Gap : Gaps) {
314     ListScope S(W, "LocalVariableAddrGap");
315     W.printHex("GapStartOffset", Gap.GapStartOffset);
316     W.printHex("Range", Gap.Range);
317   }
318 }
319 
320 void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
321                                           ArrayRef<uint8_t> Data) {}
322 
323 void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
324                                         ArrayRef<uint8_t> OriginalSymData) {
325   if (PrintRecordBytes && ObjDelegate)
326     ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
327 }
328 
329 void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
330   DictScope S(W, "BlockStart");
331 
332   StringRef LinkageName;
333   W.printHex("PtrParent", Block.Header.PtrParent);
334   W.printHex("PtrEnd", Block.Header.PtrEnd);
335   W.printHex("CodeSize", Block.Header.CodeSize);
336   if (ObjDelegate) {
337     ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
338                                      Block.Header.CodeOffset, &LinkageName);
339   }
340   W.printHex("Segment", Block.Header.Segment);
341   W.printString("BlockName", Block.Name);
342   W.printString("LinkageName", LinkageName);
343 }
344 
345 void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
346   DictScope S(W, "Thunk32");
347   W.printNumber("Parent", Thunk.Header.Parent);
348   W.printNumber("End", Thunk.Header.End);
349   W.printNumber("Next", Thunk.Header.Next);
350   W.printNumber("Off", Thunk.Header.Off);
351   W.printNumber("Seg", Thunk.Header.Seg);
352   W.printNumber("Len", Thunk.Header.Len);
353   W.printEnum("Ordinal", Thunk.Header.Ord, makeArrayRef(ThunkOrdinalNames));
354 }
355 
356 void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
357                                             TrampolineSym &Tramp) {
358   DictScope S(W, "Trampoline");
359   W.printEnum("Type", Tramp.Header.Type, makeArrayRef(TrampolineNames));
360   W.printNumber("Size", Tramp.Header.Size);
361   W.printNumber("ThunkOff", Tramp.Header.ThunkOff);
362   W.printNumber("TargetOff", Tramp.Header.TargetOff);
363   W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
364   W.printNumber("TargetSection", Tramp.Header.TargetSection);
365 }
366 
367 void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
368   DictScope S(W, "Section");
369   W.printNumber("SectionNumber", Section.Header.SectionNumber);
370   W.printNumber("Alignment", Section.Header.Alignment);
371   W.printNumber("Reserved", Section.Header.Reserved);
372   W.printNumber("Rva", Section.Header.Rva);
373   W.printNumber("Length", Section.Header.Length);
374   W.printHex("Characteristics", Section.Header.Characteristics);
375   W.printString("Name", Section.Name);
376 }
377 
378 void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
379                                            CoffGroupSym &CoffGroup) {
380   DictScope S(W, "COFF Group");
381   W.printNumber("Size", CoffGroup.Header.Size);
382   W.printHex("Characteristics", CoffGroup.Header.Characteristics);
383   W.printNumber("Offset", CoffGroup.Header.Offset);
384   W.printNumber("Segment", CoffGroup.Header.Segment);
385   W.printString("Name", CoffGroup.Name);
386 }
387 
388 void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
389                                             BPRelativeSym &BPRel) {
390   DictScope S(W, "BPRelativeSym");
391 
392   W.printNumber("Offset", BPRel.Header.Offset);
393   CVTD.printTypeIndex("Type", BPRel.Header.Type);
394   W.printString("VarName", BPRel.Name);
395 }
396 
397 void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
398                                            BuildInfoSym &BuildInfo) {
399   DictScope S(W, "BuildInfo");
400 
401   W.printNumber("BuildId", BuildInfo.Header.BuildId);
402 }
403 
404 void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
405                                               CallSiteInfoSym &CallSiteInfo) {
406   DictScope S(W, "CallSiteInfo");
407 
408   StringRef LinkageName;
409   if (ObjDelegate) {
410     ObjDelegate->printRelocatedField(
411         "CodeOffset", CallSiteInfo.getRelocationOffset(),
412         CallSiteInfo.Header.CodeOffset, &LinkageName);
413   }
414   W.printHex("Segment", CallSiteInfo.Header.Segment);
415   W.printHex("Reserved", CallSiteInfo.Header.Reserved);
416   CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
417   if (!LinkageName.empty())
418     W.printString("LinkageName", LinkageName);
419 }
420 
421 void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
422                                           EnvBlockSym &EnvBlock) {
423   DictScope S(W, "EnvBlock");
424 
425   W.printNumber("Reserved", EnvBlock.Header.Reserved);
426   ListScope L(W, "Entries");
427   for (auto Entry : EnvBlock.Fields) {
428     W.printString(Entry);
429   }
430 }
431 
432 void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
433                                             FileStaticSym &FileStatic) {
434   DictScope S(W, "FileStatic");
435   W.printNumber("Index", FileStatic.Header.Index);
436   W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
437   W.printFlags("Flags", uint16_t(FileStatic.Header.Flags),
438                makeArrayRef(LocalFlags));
439   W.printString("Name", FileStatic.Name);
440 }
441 
442 void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
443   DictScope S(W, "Export");
444   W.printNumber("Ordinal", Export.Header.Ordinal);
445   W.printFlags("Flags", Export.Header.Flags, makeArrayRef(ExportSymFlags));
446   W.printString("Name", Export.Name);
447 }
448 
449 void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
450                                           Compile2Sym &Compile2) {
451   DictScope S(W, "CompilerFlags2");
452 
453   W.printEnum("Language", Compile2.Header.getLanguage(),
454               makeArrayRef(SourceLanguages));
455   W.printFlags("Flags", Compile2.Header.flags & ~0xff,
456                makeArrayRef(CompileSym2FlagNames));
457   W.printEnum("Machine", unsigned(Compile2.Header.Machine),
458               makeArrayRef(CPUTypeNames));
459   std::string FrontendVersion;
460   {
461     raw_string_ostream Out(FrontendVersion);
462     Out << Compile2.Header.VersionFrontendMajor << '.'
463         << Compile2.Header.VersionFrontendMinor << '.'
464         << Compile2.Header.VersionFrontendBuild;
465   }
466   std::string BackendVersion;
467   {
468     raw_string_ostream Out(BackendVersion);
469     Out << Compile2.Header.VersionBackendMajor << '.'
470         << Compile2.Header.VersionBackendMinor << '.'
471         << Compile2.Header.VersionBackendBuild;
472   }
473   W.printString("FrontendVersion", FrontendVersion);
474   W.printString("BackendVersion", BackendVersion);
475   W.printString("VersionName", Compile2.Version);
476 }
477 
478 void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
479                                           Compile3Sym &Compile3) {
480   DictScope S(W, "CompilerFlags3");
481 
482   W.printEnum("Language", Compile3.Header.getLanguage(),
483               makeArrayRef(SourceLanguages));
484   W.printFlags("Flags", Compile3.Header.flags & ~0xff,
485                makeArrayRef(CompileSym3FlagNames));
486   W.printEnum("Machine", unsigned(Compile3.Header.Machine),
487               makeArrayRef(CPUTypeNames));
488   std::string FrontendVersion;
489   {
490     raw_string_ostream Out(FrontendVersion);
491     Out << Compile3.Header.VersionFrontendMajor << '.'
492         << Compile3.Header.VersionFrontendMinor << '.'
493         << Compile3.Header.VersionFrontendBuild << '.'
494         << Compile3.Header.VersionFrontendQFE;
495   }
496   std::string BackendVersion;
497   {
498     raw_string_ostream Out(BackendVersion);
499     Out << Compile3.Header.VersionBackendMajor << '.'
500         << Compile3.Header.VersionBackendMinor << '.'
501         << Compile3.Header.VersionBackendBuild << '.'
502         << Compile3.Header.VersionBackendQFE;
503   }
504   W.printString("FrontendVersion", FrontendVersion);
505   W.printString("BackendVersion", BackendVersion);
506   W.printString("VersionName", Compile3.Version);
507 }
508 
509 void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
510                                           ConstantSym &Constant) {
511   DictScope S(W, "Constant");
512 
513   CVTD.printTypeIndex("Type", Constant.Header.Type);
514   W.printNumber("Value", Constant.Value);
515   W.printString("Name", Constant.Name);
516 }
517 
518 void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
519   DictScope S(W, "DataSym");
520 
521   StringRef LinkageName;
522   if (ObjDelegate) {
523     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
524                                      Data.Header.DataOffset, &LinkageName);
525   }
526   CVTD.printTypeIndex("Type", Data.Header.Type);
527   W.printString("DisplayName", Data.Name);
528   if (!LinkageName.empty())
529     W.printString("LinkageName", LinkageName);
530 }
531 
532 void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
533     SymbolKind Kind,
534     DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
535   DictScope S(W, "DefRangeFramePointerRelFullScope");
536   W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
537 }
538 
539 void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
540     SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
541   DictScope S(W, "DefRangeFramePointerRel");
542 
543   W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
544   printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
545                               DefRangeFramePointerRel.getRelocationOffset());
546   printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
547 }
548 
549 void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
550     SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
551   DictScope S(W, "DefRangeRegisterRel");
552 
553   W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
554   W.printBoolean("HasSpilledUDTMember",
555                  DefRangeRegisterRel.hasSpilledUDTMember());
556   W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
557   W.printNumber("BasePointerOffset",
558                 DefRangeRegisterRel.Header.BasePointerOffset);
559   printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
560                               DefRangeRegisterRel.getRelocationOffset());
561   printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
562 }
563 
564 void CVSymbolDumperImpl::visitDefRangeRegisterSym(
565     SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
566   DictScope S(W, "DefRangeRegister");
567 
568   W.printNumber("Register", DefRangeRegister.Header.Register);
569   W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName);
570   printLocalVariableAddrRange(DefRangeRegister.Header.Range,
571                               DefRangeRegister.getRelocationOffset());
572   printLocalVariableAddrGap(DefRangeRegister.Gaps);
573 }
574 
575 void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
576     SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
577   DictScope S(W, "DefRangeSubfieldRegister");
578 
579   W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
580   W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName);
581   W.printNumber("OffsetInParent",
582                 DefRangeSubfieldRegister.Header.OffsetInParent);
583   printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
584                               DefRangeSubfieldRegister.getRelocationOffset());
585   printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
586 }
587 
588 void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
589     SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
590   DictScope S(W, "DefRangeSubfield");
591 
592   if (ObjDelegate) {
593     StringRef StringTable = ObjDelegate->getStringTable();
594     auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
595     if (ProgramStringTableOffset >= StringTable.size())
596       return parseError();
597     StringRef Program =
598         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
599     W.printString("Program", Program);
600   }
601   W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
602   printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
603                               DefRangeSubfield.getRelocationOffset());
604   printLocalVariableAddrGap(DefRangeSubfield.Gaps);
605 }
606 
607 void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
608                                           DefRangeSym &DefRange) {
609   DictScope S(W, "DefRange");
610 
611   if (ObjDelegate) {
612     StringRef StringTable = ObjDelegate->getStringTable();
613     auto ProgramStringTableOffset = DefRange.Header.Program;
614     if (ProgramStringTableOffset >= StringTable.size())
615       return parseError();
616     StringRef Program =
617         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
618     W.printString("Program", Program);
619   }
620   printLocalVariableAddrRange(DefRange.Header.Range,
621                               DefRange.getRelocationOffset());
622   printLocalVariableAddrGap(DefRange.Gaps);
623 }
624 
625 void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
626                                              FrameCookieSym &FrameCookie) {
627   DictScope S(W, "FrameCookie");
628 
629   StringRef LinkageName;
630   if (ObjDelegate) {
631     ObjDelegate->printRelocatedField(
632         "CodeOffset", FrameCookie.getRelocationOffset(),
633         FrameCookie.Header.CodeOffset, &LinkageName);
634   }
635   W.printHex("Register", FrameCookie.Header.Register);
636   W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
637               makeArrayRef(FrameCookieKinds));
638 }
639 
640 void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
641                                            FrameProcSym &FrameProc) {
642   DictScope S(W, "FrameProc");
643 
644   W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
645   W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
646   W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
647   W.printHex("BytesOfCalleeSavedRegisters",
648              FrameProc.Header.BytesOfCalleeSavedRegisters);
649   W.printHex("OffsetOfExceptionHandler",
650              FrameProc.Header.OffsetOfExceptionHandler);
651   W.printHex("SectionIdOfExceptionHandler",
652              FrameProc.Header.SectionIdOfExceptionHandler);
653   W.printFlags("Flags", FrameProc.Header.Flags,
654                makeArrayRef(FrameProcSymFlags));
655 }
656 
657 void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
658     SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
659   DictScope S(W, "HeapAllocationSite");
660 
661   StringRef LinkageName;
662   if (ObjDelegate) {
663     ObjDelegate->printRelocatedField(
664         "CodeOffset", HeapAllocSite.getRelocationOffset(),
665         HeapAllocSite.Header.CodeOffset, &LinkageName);
666   }
667   W.printHex("Segment", HeapAllocSite.Header.Segment);
668   W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize);
669   CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
670   if (!LinkageName.empty())
671     W.printString("LinkageName", LinkageName);
672 }
673 
674 void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
675                                             InlineSiteSym &InlineSite) {
676   DictScope S(W, "InlineSite");
677 
678   W.printHex("PtrParent", InlineSite.Header.PtrParent);
679   W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
680   CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
681 
682   ListScope BinaryAnnotations(W, "BinaryAnnotations");
683   for (auto &Annotation : InlineSite.annotations()) {
684     switch (Annotation.OpCode) {
685     case BinaryAnnotationsOpCode::Invalid:
686       return parseError();
687     case BinaryAnnotationsOpCode::CodeOffset:
688     case BinaryAnnotationsOpCode::ChangeCodeOffset:
689     case BinaryAnnotationsOpCode::ChangeCodeLength:
690       W.printHex(Annotation.Name, Annotation.U1);
691       break;
692     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
693     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
694     case BinaryAnnotationsOpCode::ChangeRangeKind:
695     case BinaryAnnotationsOpCode::ChangeColumnStart:
696     case BinaryAnnotationsOpCode::ChangeColumnEnd:
697       W.printNumber(Annotation.Name, Annotation.U1);
698       break;
699     case BinaryAnnotationsOpCode::ChangeLineOffset:
700     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
701       W.printNumber(Annotation.Name, Annotation.S1);
702       break;
703     case BinaryAnnotationsOpCode::ChangeFile:
704       if (ObjDelegate) {
705         W.printHex("ChangeFile",
706                    ObjDelegate->getFileNameForFileOffset(Annotation.U1),
707                    Annotation.U1);
708       } else {
709         W.printHex("ChangeFile", Annotation.U1);
710       }
711 
712       break;
713     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
714       W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
715                     << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
716                     << "}\n";
717       break;
718     }
719     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
720       W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
721                     << W.hex(Annotation.U2)
722                     << ", Length: " << W.hex(Annotation.U1) << "}\n";
723       break;
724     }
725     }
726   }
727 }
728 
729 void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
730                                           RegisterSym &Register) {
731   DictScope S(W, "RegisterSym");
732   W.printNumber("Type", Register.Header.Index);
733   W.printEnum("Seg", uint16_t(Register.Header.Register),
734               makeArrayRef(RegisterNames));
735   W.printString("Name", Register.Name);
736 }
737 
738 void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
739                                           PublicSym32 &Public) {
740   DictScope S(W, "PublicSym");
741   W.printNumber("Type", Public.Header.Index);
742   W.printNumber("Seg", Public.Header.Seg);
743   W.printNumber("Off", Public.Header.Off);
744   W.printString("Name", Public.Name);
745 }
746 
747 void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
748   DictScope S(W, "ProcRef");
749   W.printNumber("SumName", ProcRef.Header.SumName);
750   W.printNumber("SymOffset", ProcRef.Header.SymOffset);
751   W.printNumber("Mod", ProcRef.Header.Mod);
752   W.printString("Name", ProcRef.Name);
753 }
754 
755 void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
756   DictScope S(W, "Label");
757 
758   StringRef LinkageName;
759   if (ObjDelegate) {
760     ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
761                                      Label.Header.CodeOffset, &LinkageName);
762   }
763   W.printHex("Segment", Label.Header.Segment);
764   W.printHex("Flags", Label.Header.Flags);
765   W.printFlags("Flags", Label.Header.Flags, makeArrayRef(ProcSymFlagNames));
766   W.printString("DisplayName", Label.Name);
767   if (!LinkageName.empty())
768     W.printString("LinkageName", LinkageName);
769 }
770 
771 void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
772   DictScope S(W, "Local");
773 
774   CVTD.printTypeIndex("Type", Local.Header.Type);
775   W.printFlags("Flags", uint16_t(Local.Header.Flags), makeArrayRef(LocalFlags));
776   W.printString("VarName", Local.Name);
777 }
778 
779 void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
780   DictScope S(W, "ObjectName");
781 
782   W.printHex("Signature", ObjName.Header.Signature);
783   W.printString("ObjectName", ObjName.Name);
784 }
785 
786 void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
787   DictScope S(W, "ProcStart");
788 
789   if (InFunctionScope)
790     return parseError();
791 
792   InFunctionScope = true;
793 
794   StringRef LinkageName;
795   W.printHex("PtrParent", Proc.Header.PtrParent);
796   W.printHex("PtrEnd", Proc.Header.PtrEnd);
797   W.printHex("PtrNext", Proc.Header.PtrNext);
798   W.printHex("CodeSize", Proc.Header.CodeSize);
799   W.printHex("DbgStart", Proc.Header.DbgStart);
800   W.printHex("DbgEnd", Proc.Header.DbgEnd);
801   CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType);
802   if (ObjDelegate) {
803     ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
804                                      Proc.Header.CodeOffset, &LinkageName);
805   }
806   W.printHex("Segment", Proc.Header.Segment);
807   W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
808                makeArrayRef(ProcSymFlagNames));
809   W.printString("DisplayName", Proc.Name);
810   if (!LinkageName.empty())
811     W.printString("LinkageName", LinkageName);
812 }
813 
814 void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
815                                           ScopeEndSym &ScopeEnd) {
816   if (Kind == SymbolKind::S_END)
817     DictScope S(W, "BlockEnd");
818   else if (Kind == SymbolKind::S_PROC_ID_END)
819     DictScope S(W, "ProcEnd");
820   else if (Kind == SymbolKind::S_INLINESITE_END)
821     DictScope S(W, "InlineSiteEnd");
822 
823   InFunctionScope = false;
824 }
825 
826 void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
827   ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
828   for (auto FuncID : Caller.Indices)
829     CVTD.printTypeIndex("FuncID", FuncID);
830 }
831 
832 void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
833                                              RegRelativeSym &RegRel) {
834   DictScope S(W, "RegRelativeSym");
835 
836   W.printHex("Offset", RegRel.Header.Offset);
837   CVTD.printTypeIndex("Type", RegRel.Header.Type);
838   W.printHex("Register", RegRel.Header.Register);
839   W.printString("VarName", RegRel.Name);
840 }
841 
842 void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
843                                                  ThreadLocalDataSym &Data) {
844   DictScope S(W, "ThreadLocalDataSym");
845 
846   StringRef LinkageName;
847   if (ObjDelegate) {
848     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
849                                      Data.Header.DataOffset, &LinkageName);
850   }
851   CVTD.printTypeIndex("Type", Data.Header.Type);
852   W.printString("DisplayName", Data.Name);
853   if (!LinkageName.empty())
854     W.printString("LinkageName", LinkageName);
855 }
856 
857 void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
858   DictScope S(W, "UDT");
859   CVTD.printTypeIndex("Type", UDT.Header.Type);
860   W.printString("UDTName", UDT.Name);
861 }
862 
863 void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
864                                             ArrayRef<uint8_t> Data) {
865   DictScope S(W, "UnknownSym");
866   W.printEnum("Kind", uint16_t(Kind), makeArrayRef(SymbolTypeNames));
867   W.printNumber("Length", uint32_t(Data.size()));
868 }
869 
870 bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
871   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
872   Dumper.visitSymbolRecord(Record);
873   return !Dumper.hadError();
874 }
875 
876 bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
877   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
878   Dumper.visitSymbolStream(Symbols);
879   return !Dumper.hadError();
880 }
881