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/EnumTables.h"
15 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
16 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
17 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
18 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
19 #include "llvm/Support/ScopedPrinter.h"
20 
21 #include <system_error>
22 
23 using namespace llvm;
24 using namespace llvm::codeview;
25 
26 namespace {
27 /// Use this private dumper implementation to keep implementation details about
28 /// the visitor out of SymbolDumper.h.
29 class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
30 public:
31   CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
32                      ScopedPrinter &W, bool PrintRecordBytes)
33       : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
34         W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
35 
36 /// CVSymbolVisitor overrides.
37 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
38   void visit##Name(SymbolKind Kind, Name &Record);
39 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
40 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
41 
42   void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
43   void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
44   void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
45 
46 private:
47   void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
48                                    uint32_t RelocationOffset);
49   void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
50 
51   CVTypeDumper &CVTD;
52   SymbolDumpDelegate *ObjDelegate;
53   ScopedPrinter &W;
54 
55   bool PrintRecordBytes;
56   bool InFunctionScope;
57 };
58 }
59 
60 void CVSymbolDumperImpl::printLocalVariableAddrRange(
61     const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
62   DictScope S(W, "LocalVariableAddrRange");
63   if (ObjDelegate)
64     ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
65                                      Range.OffsetStart);
66   W.printHex("ISectStart", Range.ISectStart);
67   W.printHex("Range", Range.Range);
68 }
69 
70 void CVSymbolDumperImpl::printLocalVariableAddrGap(
71     ArrayRef<LocalVariableAddrGap> Gaps) {
72   for (auto &Gap : Gaps) {
73     ListScope S(W, "LocalVariableAddrGap");
74     W.printHex("GapStartOffset", Gap.GapStartOffset);
75     W.printHex("Range", Gap.Range);
76   }
77 }
78 
79 void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
80                                           ArrayRef<uint8_t> Data) {}
81 
82 void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
83                                         ArrayRef<uint8_t> OriginalSymData) {
84   if (PrintRecordBytes && ObjDelegate)
85     ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
86 }
87 
88 void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
89   DictScope S(W, "BlockStart");
90 
91   StringRef LinkageName;
92   W.printHex("PtrParent", Block.Header.PtrParent);
93   W.printHex("PtrEnd", Block.Header.PtrEnd);
94   W.printHex("CodeSize", Block.Header.CodeSize);
95   if (ObjDelegate) {
96     ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
97                                      Block.Header.CodeOffset, &LinkageName);
98   }
99   W.printHex("Segment", Block.Header.Segment);
100   W.printString("BlockName", Block.Name);
101   W.printString("LinkageName", LinkageName);
102 }
103 
104 void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
105   DictScope S(W, "Thunk32");
106   W.printNumber("Parent", Thunk.Header.Parent);
107   W.printNumber("End", Thunk.Header.End);
108   W.printNumber("Next", Thunk.Header.Next);
109   W.printNumber("Off", Thunk.Header.Off);
110   W.printNumber("Seg", Thunk.Header.Seg);
111   W.printNumber("Len", Thunk.Header.Len);
112   W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames());
113 }
114 
115 void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
116                                             TrampolineSym &Tramp) {
117   DictScope S(W, "Trampoline");
118   W.printEnum("Type", Tramp.Header.Type, getTrampolineNames());
119   W.printNumber("Size", Tramp.Header.Size);
120   W.printNumber("ThunkOff", Tramp.Header.ThunkOff);
121   W.printNumber("TargetOff", Tramp.Header.TargetOff);
122   W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
123   W.printNumber("TargetSection", Tramp.Header.TargetSection);
124 }
125 
126 void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
127   DictScope S(W, "Section");
128   W.printNumber("SectionNumber", Section.Header.SectionNumber);
129   W.printNumber("Alignment", Section.Header.Alignment);
130   W.printNumber("Reserved", Section.Header.Reserved);
131   W.printNumber("Rva", Section.Header.Rva);
132   W.printNumber("Length", Section.Header.Length);
133   W.printFlags("Characteristics", Section.Header.Characteristics,
134                getImageSectionCharacteristicNames(),
135                COFF::SectionCharacteristics(0x00F00000));
136 
137   W.printString("Name", Section.Name);
138 }
139 
140 void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
141                                            CoffGroupSym &CoffGroup) {
142   DictScope S(W, "COFF Group");
143   W.printNumber("Size", CoffGroup.Header.Size);
144   W.printFlags("Characteristics", CoffGroup.Header.Characteristics,
145                getImageSectionCharacteristicNames(),
146                COFF::SectionCharacteristics(0x00F00000));
147   W.printNumber("Offset", CoffGroup.Header.Offset);
148   W.printNumber("Segment", CoffGroup.Header.Segment);
149   W.printString("Name", CoffGroup.Name);
150 }
151 
152 void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
153                                             BPRelativeSym &BPRel) {
154   DictScope S(W, "BPRelativeSym");
155 
156   W.printNumber("Offset", BPRel.Header.Offset);
157   CVTD.printTypeIndex("Type", BPRel.Header.Type);
158   W.printString("VarName", BPRel.Name);
159 }
160 
161 void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
162                                            BuildInfoSym &BuildInfo) {
163   DictScope S(W, "BuildInfo");
164 
165   W.printNumber("BuildId", BuildInfo.Header.BuildId);
166 }
167 
168 void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
169                                               CallSiteInfoSym &CallSiteInfo) {
170   DictScope S(W, "CallSiteInfo");
171 
172   StringRef LinkageName;
173   if (ObjDelegate) {
174     ObjDelegate->printRelocatedField(
175         "CodeOffset", CallSiteInfo.getRelocationOffset(),
176         CallSiteInfo.Header.CodeOffset, &LinkageName);
177   }
178   W.printHex("Segment", CallSiteInfo.Header.Segment);
179   W.printHex("Reserved", CallSiteInfo.Header.Reserved);
180   CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
181   if (!LinkageName.empty())
182     W.printString("LinkageName", LinkageName);
183 }
184 
185 void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
186                                           EnvBlockSym &EnvBlock) {
187   DictScope S(W, "EnvBlock");
188 
189   W.printNumber("Reserved", EnvBlock.Header.Reserved);
190   ListScope L(W, "Entries");
191   for (auto Entry : EnvBlock.Fields) {
192     W.printString(Entry);
193   }
194 }
195 
196 void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
197                                             FileStaticSym &FileStatic) {
198   DictScope S(W, "FileStatic");
199   W.printNumber("Index", FileStatic.Header.Index);
200   W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
201   W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames());
202   W.printString("Name", FileStatic.Name);
203 }
204 
205 void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
206   DictScope S(W, "Export");
207   W.printNumber("Ordinal", Export.Header.Ordinal);
208   W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames());
209   W.printString("Name", Export.Name);
210 }
211 
212 void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
213                                           Compile2Sym &Compile2) {
214   DictScope S(W, "CompilerFlags2");
215 
216   W.printEnum("Language", Compile2.Header.getLanguage(),
217               getSourceLanguageNames());
218   W.printFlags("Flags", Compile2.Header.flags & ~0xff,
219                getCompileSym2FlagNames());
220   W.printEnum("Machine", unsigned(Compile2.Header.Machine), getCPUTypeNames());
221   std::string FrontendVersion;
222   {
223     raw_string_ostream Out(FrontendVersion);
224     Out << Compile2.Header.VersionFrontendMajor << '.'
225         << Compile2.Header.VersionFrontendMinor << '.'
226         << Compile2.Header.VersionFrontendBuild;
227   }
228   std::string BackendVersion;
229   {
230     raw_string_ostream Out(BackendVersion);
231     Out << Compile2.Header.VersionBackendMajor << '.'
232         << Compile2.Header.VersionBackendMinor << '.'
233         << Compile2.Header.VersionBackendBuild;
234   }
235   W.printString("FrontendVersion", FrontendVersion);
236   W.printString("BackendVersion", BackendVersion);
237   W.printString("VersionName", Compile2.Version);
238 }
239 
240 void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
241                                           Compile3Sym &Compile3) {
242   DictScope S(W, "CompilerFlags3");
243 
244   W.printEnum("Language", Compile3.Header.getLanguage(),
245               getSourceLanguageNames());
246   W.printFlags("Flags", Compile3.Header.flags & ~0xff,
247                getCompileSym3FlagNames());
248   W.printEnum("Machine", unsigned(Compile3.Header.Machine), getCPUTypeNames());
249   std::string FrontendVersion;
250   {
251     raw_string_ostream Out(FrontendVersion);
252     Out << Compile3.Header.VersionFrontendMajor << '.'
253         << Compile3.Header.VersionFrontendMinor << '.'
254         << Compile3.Header.VersionFrontendBuild << '.'
255         << Compile3.Header.VersionFrontendQFE;
256   }
257   std::string BackendVersion;
258   {
259     raw_string_ostream Out(BackendVersion);
260     Out << Compile3.Header.VersionBackendMajor << '.'
261         << Compile3.Header.VersionBackendMinor << '.'
262         << Compile3.Header.VersionBackendBuild << '.'
263         << Compile3.Header.VersionBackendQFE;
264   }
265   W.printString("FrontendVersion", FrontendVersion);
266   W.printString("BackendVersion", BackendVersion);
267   W.printString("VersionName", Compile3.Version);
268 }
269 
270 void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
271                                           ConstantSym &Constant) {
272   DictScope S(W, "Constant");
273 
274   CVTD.printTypeIndex("Type", Constant.Header.Type);
275   W.printNumber("Value", Constant.Value);
276   W.printString("Name", Constant.Name);
277 }
278 
279 void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
280   DictScope S(W, "DataSym");
281 
282   StringRef LinkageName;
283   if (ObjDelegate) {
284     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
285                                      Data.Header.DataOffset, &LinkageName);
286   }
287   CVTD.printTypeIndex("Type", Data.Header.Type);
288   W.printString("DisplayName", Data.Name);
289   if (!LinkageName.empty())
290     W.printString("LinkageName", LinkageName);
291 }
292 
293 void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
294     SymbolKind Kind,
295     DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
296   DictScope S(W, "DefRangeFramePointerRelFullScope");
297   W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
298 }
299 
300 void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
301     SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
302   DictScope S(W, "DefRangeFramePointerRel");
303 
304   W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
305   printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
306                               DefRangeFramePointerRel.getRelocationOffset());
307   printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
308 }
309 
310 void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
311     SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
312   DictScope S(W, "DefRangeRegisterRel");
313 
314   W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
315   W.printBoolean("HasSpilledUDTMember",
316                  DefRangeRegisterRel.hasSpilledUDTMember());
317   W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
318   W.printNumber("BasePointerOffset",
319                 DefRangeRegisterRel.Header.BasePointerOffset);
320   printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
321                               DefRangeRegisterRel.getRelocationOffset());
322   printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
323 }
324 
325 void CVSymbolDumperImpl::visitDefRangeRegisterSym(
326     SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
327   DictScope S(W, "DefRangeRegister");
328 
329   W.printNumber("Register", DefRangeRegister.Header.Register);
330   W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName);
331   printLocalVariableAddrRange(DefRangeRegister.Header.Range,
332                               DefRangeRegister.getRelocationOffset());
333   printLocalVariableAddrGap(DefRangeRegister.Gaps);
334 }
335 
336 void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
337     SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
338   DictScope S(W, "DefRangeSubfieldRegister");
339 
340   W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
341   W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName);
342   W.printNumber("OffsetInParent",
343                 DefRangeSubfieldRegister.Header.OffsetInParent);
344   printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
345                               DefRangeSubfieldRegister.getRelocationOffset());
346   printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
347 }
348 
349 void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
350     SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
351   DictScope S(W, "DefRangeSubfield");
352 
353   if (ObjDelegate) {
354     StringRef StringTable = ObjDelegate->getStringTable();
355     auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
356     if (ProgramStringTableOffset >= StringTable.size())
357       return parseError();
358     StringRef Program =
359         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
360     W.printString("Program", Program);
361   }
362   W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
363   printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
364                               DefRangeSubfield.getRelocationOffset());
365   printLocalVariableAddrGap(DefRangeSubfield.Gaps);
366 }
367 
368 void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
369                                           DefRangeSym &DefRange) {
370   DictScope S(W, "DefRange");
371 
372   if (ObjDelegate) {
373     StringRef StringTable = ObjDelegate->getStringTable();
374     auto ProgramStringTableOffset = DefRange.Header.Program;
375     if (ProgramStringTableOffset >= StringTable.size())
376       return parseError();
377     StringRef Program =
378         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
379     W.printString("Program", Program);
380   }
381   printLocalVariableAddrRange(DefRange.Header.Range,
382                               DefRange.getRelocationOffset());
383   printLocalVariableAddrGap(DefRange.Gaps);
384 }
385 
386 void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
387                                              FrameCookieSym &FrameCookie) {
388   DictScope S(W, "FrameCookie");
389 
390   StringRef LinkageName;
391   if (ObjDelegate) {
392     ObjDelegate->printRelocatedField(
393         "CodeOffset", FrameCookie.getRelocationOffset(),
394         FrameCookie.Header.CodeOffset, &LinkageName);
395   }
396   W.printHex("Register", FrameCookie.Header.Register);
397   W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
398               getFrameCookieKindNames());
399   W.printHex("Flags", FrameCookie.Header.Flags);
400 }
401 
402 void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
403                                            FrameProcSym &FrameProc) {
404   DictScope S(W, "FrameProc");
405 
406   W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
407   W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
408   W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
409   W.printHex("BytesOfCalleeSavedRegisters",
410              FrameProc.Header.BytesOfCalleeSavedRegisters);
411   W.printHex("OffsetOfExceptionHandler",
412              FrameProc.Header.OffsetOfExceptionHandler);
413   W.printHex("SectionIdOfExceptionHandler",
414              FrameProc.Header.SectionIdOfExceptionHandler);
415   W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
416 }
417 
418 void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
419     SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
420   DictScope S(W, "HeapAllocationSite");
421 
422   StringRef LinkageName;
423   if (ObjDelegate) {
424     ObjDelegate->printRelocatedField(
425         "CodeOffset", HeapAllocSite.getRelocationOffset(),
426         HeapAllocSite.Header.CodeOffset, &LinkageName);
427   }
428   W.printHex("Segment", HeapAllocSite.Header.Segment);
429   W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize);
430   CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
431   if (!LinkageName.empty())
432     W.printString("LinkageName", LinkageName);
433 }
434 
435 void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
436                                             InlineSiteSym &InlineSite) {
437   DictScope S(W, "InlineSite");
438 
439   W.printHex("PtrParent", InlineSite.Header.PtrParent);
440   W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
441   CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
442 
443   ListScope BinaryAnnotations(W, "BinaryAnnotations");
444   for (auto &Annotation : InlineSite.annotations()) {
445     switch (Annotation.OpCode) {
446     case BinaryAnnotationsOpCode::Invalid:
447       return parseError();
448     case BinaryAnnotationsOpCode::CodeOffset:
449     case BinaryAnnotationsOpCode::ChangeCodeOffset:
450     case BinaryAnnotationsOpCode::ChangeCodeLength:
451       W.printHex(Annotation.Name, Annotation.U1);
452       break;
453     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
454     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
455     case BinaryAnnotationsOpCode::ChangeRangeKind:
456     case BinaryAnnotationsOpCode::ChangeColumnStart:
457     case BinaryAnnotationsOpCode::ChangeColumnEnd:
458       W.printNumber(Annotation.Name, Annotation.U1);
459       break;
460     case BinaryAnnotationsOpCode::ChangeLineOffset:
461     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
462       W.printNumber(Annotation.Name, Annotation.S1);
463       break;
464     case BinaryAnnotationsOpCode::ChangeFile:
465       if (ObjDelegate) {
466         W.printHex("ChangeFile",
467                    ObjDelegate->getFileNameForFileOffset(Annotation.U1),
468                    Annotation.U1);
469       } else {
470         W.printHex("ChangeFile", Annotation.U1);
471       }
472 
473       break;
474     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
475       W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
476                     << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
477                     << "}\n";
478       break;
479     }
480     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
481       W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
482                     << W.hex(Annotation.U2)
483                     << ", Length: " << W.hex(Annotation.U1) << "}\n";
484       break;
485     }
486     }
487   }
488 }
489 
490 void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
491                                           RegisterSym &Register) {
492   DictScope S(W, "RegisterSym");
493   W.printNumber("Type", Register.Header.Index);
494   W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
495   W.printString("Name", Register.Name);
496 }
497 
498 void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
499                                           PublicSym32 &Public) {
500   DictScope S(W, "PublicSym");
501   W.printNumber("Type", Public.Header.Index);
502   W.printNumber("Seg", Public.Header.Seg);
503   W.printNumber("Off", Public.Header.Off);
504   W.printString("Name", Public.Name);
505 }
506 
507 void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
508   DictScope S(W, "ProcRef");
509   W.printNumber("SumName", ProcRef.Header.SumName);
510   W.printNumber("SymOffset", ProcRef.Header.SymOffset);
511   W.printNumber("Mod", ProcRef.Header.Mod);
512   W.printString("Name", ProcRef.Name);
513 }
514 
515 void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
516   DictScope S(W, "Label");
517 
518   StringRef LinkageName;
519   if (ObjDelegate) {
520     ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
521                                      Label.Header.CodeOffset, &LinkageName);
522   }
523   W.printHex("Segment", Label.Header.Segment);
524   W.printHex("Flags", Label.Header.Flags);
525   W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames());
526   W.printString("DisplayName", Label.Name);
527   if (!LinkageName.empty())
528     W.printString("LinkageName", LinkageName);
529 }
530 
531 void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
532   DictScope S(W, "Local");
533 
534   CVTD.printTypeIndex("Type", Local.Header.Type);
535   W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
536   W.printString("VarName", Local.Name);
537 }
538 
539 void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
540   DictScope S(W, "ObjectName");
541 
542   W.printHex("Signature", ObjName.Header.Signature);
543   W.printString("ObjectName", ObjName.Name);
544 }
545 
546 void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
547   DictScope S(W, "ProcStart");
548 
549   if (InFunctionScope)
550     return parseError();
551 
552   InFunctionScope = true;
553 
554   StringRef LinkageName;
555   W.printHex("PtrParent", Proc.Header.PtrParent);
556   W.printHex("PtrEnd", Proc.Header.PtrEnd);
557   W.printHex("PtrNext", Proc.Header.PtrNext);
558   W.printHex("CodeSize", Proc.Header.CodeSize);
559   W.printHex("DbgStart", Proc.Header.DbgStart);
560   W.printHex("DbgEnd", Proc.Header.DbgEnd);
561   CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType);
562   if (ObjDelegate) {
563     ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
564                                      Proc.Header.CodeOffset, &LinkageName);
565   }
566   W.printHex("Segment", Proc.Header.Segment);
567   W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
568                getProcSymFlagNames());
569   W.printString("DisplayName", Proc.Name);
570   if (!LinkageName.empty())
571     W.printString("LinkageName", LinkageName);
572 }
573 
574 void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
575                                           ScopeEndSym &ScopeEnd) {
576   if (Kind == SymbolKind::S_END)
577     DictScope S(W, "BlockEnd");
578   else if (Kind == SymbolKind::S_PROC_ID_END)
579     DictScope S(W, "ProcEnd");
580   else if (Kind == SymbolKind::S_INLINESITE_END)
581     DictScope S(W, "InlineSiteEnd");
582 
583   InFunctionScope = false;
584 }
585 
586 void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
587   ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
588   for (auto FuncID : Caller.Indices)
589     CVTD.printTypeIndex("FuncID", FuncID);
590 }
591 
592 void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
593                                              RegRelativeSym &RegRel) {
594   DictScope S(W, "RegRelativeSym");
595 
596   W.printHex("Offset", RegRel.Header.Offset);
597   CVTD.printTypeIndex("Type", RegRel.Header.Type);
598   W.printHex("Register", RegRel.Header.Register);
599   W.printString("VarName", RegRel.Name);
600 }
601 
602 void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
603                                                  ThreadLocalDataSym &Data) {
604   DictScope S(W, "ThreadLocalDataSym");
605 
606   StringRef LinkageName;
607   if (ObjDelegate) {
608     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
609                                      Data.Header.DataOffset, &LinkageName);
610   }
611   CVTD.printTypeIndex("Type", Data.Header.Type);
612   W.printString("DisplayName", Data.Name);
613   if (!LinkageName.empty())
614     W.printString("LinkageName", LinkageName);
615 }
616 
617 void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
618   DictScope S(W, "UDT");
619   CVTD.printTypeIndex("Type", UDT.Header.Type);
620   W.printString("UDTName", UDT.Name);
621 }
622 
623 void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
624                                             ArrayRef<uint8_t> Data) {
625   DictScope S(W, "UnknownSym");
626   W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
627   W.printNumber("Length", uint32_t(Data.size()));
628 }
629 
630 bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
631   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
632   Dumper.visitSymbolRecord(Record);
633   return !Dumper.hadError();
634 }
635 
636 bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
637   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
638   Dumper.visitSymbolStream(Symbols);
639   return !Dumper.hadError();
640 }
641