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