Home | History | Annotate | Download | only in CodeView
      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   W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
    283   StringRef LinkageName;
    284   if (ObjDelegate) {
    285     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
    286                                      Data.Header.DataOffset, &LinkageName);
    287   }
    288   CVTD.printTypeIndex("Type", Data.Header.Type);
    289   W.printString("DisplayName", Data.Name);
    290   if (!LinkageName.empty())
    291     W.printString("LinkageName", LinkageName);
    292 }
    293 
    294 void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
    295     SymbolKind Kind,
    296     DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
    297   DictScope S(W, "DefRangeFramePointerRelFullScope");
    298   W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
    299 }
    300 
    301 void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
    302     SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
    303   DictScope S(W, "DefRangeFramePointerRel");
    304 
    305   W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
    306   printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
    307                               DefRangeFramePointerRel.getRelocationOffset());
    308   printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
    309 }
    310 
    311 void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
    312     SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
    313   DictScope S(W, "DefRangeRegisterRel");
    314 
    315   W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
    316   W.printBoolean("HasSpilledUDTMember",
    317                  DefRangeRegisterRel.hasSpilledUDTMember());
    318   W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
    319   W.printNumber("BasePointerOffset",
    320                 DefRangeRegisterRel.Header.BasePointerOffset);
    321   printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
    322                               DefRangeRegisterRel.getRelocationOffset());
    323   printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
    324 }
    325 
    326 void CVSymbolDumperImpl::visitDefRangeRegisterSym(
    327     SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
    328   DictScope S(W, "DefRangeRegister");
    329 
    330   W.printNumber("Register", DefRangeRegister.Header.Register);
    331   W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName);
    332   printLocalVariableAddrRange(DefRangeRegister.Header.Range,
    333                               DefRangeRegister.getRelocationOffset());
    334   printLocalVariableAddrGap(DefRangeRegister.Gaps);
    335 }
    336 
    337 void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
    338     SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
    339   DictScope S(W, "DefRangeSubfieldRegister");
    340 
    341   W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
    342   W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName);
    343   W.printNumber("OffsetInParent",
    344                 DefRangeSubfieldRegister.Header.OffsetInParent);
    345   printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
    346                               DefRangeSubfieldRegister.getRelocationOffset());
    347   printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
    348 }
    349 
    350 void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
    351     SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
    352   DictScope S(W, "DefRangeSubfield");
    353 
    354   if (ObjDelegate) {
    355     StringRef StringTable = ObjDelegate->getStringTable();
    356     auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
    357     if (ProgramStringTableOffset >= StringTable.size())
    358       return parseError();
    359     StringRef Program =
    360         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
    361     W.printString("Program", Program);
    362   }
    363   W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
    364   printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
    365                               DefRangeSubfield.getRelocationOffset());
    366   printLocalVariableAddrGap(DefRangeSubfield.Gaps);
    367 }
    368 
    369 void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
    370                                           DefRangeSym &DefRange) {
    371   DictScope S(W, "DefRange");
    372 
    373   if (ObjDelegate) {
    374     StringRef StringTable = ObjDelegate->getStringTable();
    375     auto ProgramStringTableOffset = DefRange.Header.Program;
    376     if (ProgramStringTableOffset >= StringTable.size())
    377       return parseError();
    378     StringRef Program =
    379         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
    380     W.printString("Program", Program);
    381   }
    382   printLocalVariableAddrRange(DefRange.Header.Range,
    383                               DefRange.getRelocationOffset());
    384   printLocalVariableAddrGap(DefRange.Gaps);
    385 }
    386 
    387 void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
    388                                              FrameCookieSym &FrameCookie) {
    389   DictScope S(W, "FrameCookie");
    390 
    391   StringRef LinkageName;
    392   if (ObjDelegate) {
    393     ObjDelegate->printRelocatedField(
    394         "CodeOffset", FrameCookie.getRelocationOffset(),
    395         FrameCookie.Header.CodeOffset, &LinkageName);
    396   }
    397   W.printHex("Register", FrameCookie.Header.Register);
    398   W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
    399               getFrameCookieKindNames());
    400   W.printHex("Flags", FrameCookie.Header.Flags);
    401 }
    402 
    403 void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
    404                                            FrameProcSym &FrameProc) {
    405   DictScope S(W, "FrameProc");
    406 
    407   W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
    408   W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
    409   W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
    410   W.printHex("BytesOfCalleeSavedRegisters",
    411              FrameProc.Header.BytesOfCalleeSavedRegisters);
    412   W.printHex("OffsetOfExceptionHandler",
    413              FrameProc.Header.OffsetOfExceptionHandler);
    414   W.printHex("SectionIdOfExceptionHandler",
    415              FrameProc.Header.SectionIdOfExceptionHandler);
    416   W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
    417 }
    418 
    419 void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
    420     SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
    421   DictScope S(W, "HeapAllocationSite");
    422 
    423   StringRef LinkageName;
    424   if (ObjDelegate) {
    425     ObjDelegate->printRelocatedField(
    426         "CodeOffset", HeapAllocSite.getRelocationOffset(),
    427         HeapAllocSite.Header.CodeOffset, &LinkageName);
    428   }
    429   W.printHex("Segment", HeapAllocSite.Header.Segment);
    430   W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize);
    431   CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
    432   if (!LinkageName.empty())
    433     W.printString("LinkageName", LinkageName);
    434 }
    435 
    436 void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
    437                                             InlineSiteSym &InlineSite) {
    438   DictScope S(W, "InlineSite");
    439 
    440   W.printHex("PtrParent", InlineSite.Header.PtrParent);
    441   W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
    442   CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
    443 
    444   ListScope BinaryAnnotations(W, "BinaryAnnotations");
    445   for (auto &Annotation : InlineSite.annotations()) {
    446     switch (Annotation.OpCode) {
    447     case BinaryAnnotationsOpCode::Invalid:
    448       return parseError();
    449     case BinaryAnnotationsOpCode::CodeOffset:
    450     case BinaryAnnotationsOpCode::ChangeCodeOffset:
    451     case BinaryAnnotationsOpCode::ChangeCodeLength:
    452       W.printHex(Annotation.Name, Annotation.U1);
    453       break;
    454     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
    455     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
    456     case BinaryAnnotationsOpCode::ChangeRangeKind:
    457     case BinaryAnnotationsOpCode::ChangeColumnStart:
    458     case BinaryAnnotationsOpCode::ChangeColumnEnd:
    459       W.printNumber(Annotation.Name, Annotation.U1);
    460       break;
    461     case BinaryAnnotationsOpCode::ChangeLineOffset:
    462     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
    463       W.printNumber(Annotation.Name, Annotation.S1);
    464       break;
    465     case BinaryAnnotationsOpCode::ChangeFile:
    466       if (ObjDelegate) {
    467         W.printHex("ChangeFile",
    468                    ObjDelegate->getFileNameForFileOffset(Annotation.U1),
    469                    Annotation.U1);
    470       } else {
    471         W.printHex("ChangeFile", Annotation.U1);
    472       }
    473 
    474       break;
    475     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
    476       W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
    477                     << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
    478                     << "}\n";
    479       break;
    480     }
    481     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
    482       W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
    483                     << W.hex(Annotation.U2)
    484                     << ", Length: " << W.hex(Annotation.U1) << "}\n";
    485       break;
    486     }
    487     }
    488   }
    489 }
    490 
    491 void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
    492                                           RegisterSym &Register) {
    493   DictScope S(W, "RegisterSym");
    494   W.printNumber("Type", Register.Header.Index);
    495   W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
    496   W.printString("Name", Register.Name);
    497 }
    498 
    499 void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
    500                                           PublicSym32 &Public) {
    501   DictScope S(W, "PublicSym");
    502   W.printNumber("Type", Public.Header.Index);
    503   W.printNumber("Seg", Public.Header.Seg);
    504   W.printNumber("Off", Public.Header.Off);
    505   W.printString("Name", Public.Name);
    506 }
    507 
    508 void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
    509   DictScope S(W, "ProcRef");
    510   W.printNumber("SumName", ProcRef.Header.SumName);
    511   W.printNumber("SymOffset", ProcRef.Header.SymOffset);
    512   W.printNumber("Mod", ProcRef.Header.Mod);
    513   W.printString("Name", ProcRef.Name);
    514 }
    515 
    516 void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
    517   DictScope S(W, "Label");
    518 
    519   StringRef LinkageName;
    520   if (ObjDelegate) {
    521     ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
    522                                      Label.Header.CodeOffset, &LinkageName);
    523   }
    524   W.printHex("Segment", Label.Header.Segment);
    525   W.printHex("Flags", Label.Header.Flags);
    526   W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames());
    527   W.printString("DisplayName", Label.Name);
    528   if (!LinkageName.empty())
    529     W.printString("LinkageName", LinkageName);
    530 }
    531 
    532 void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
    533   DictScope S(W, "Local");
    534 
    535   CVTD.printTypeIndex("Type", Local.Header.Type);
    536   W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
    537   W.printString("VarName", Local.Name);
    538 }
    539 
    540 void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
    541   DictScope S(W, "ObjectName");
    542 
    543   W.printHex("Signature", ObjName.Header.Signature);
    544   W.printString("ObjectName", ObjName.Name);
    545 }
    546 
    547 void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
    548   DictScope S(W, "ProcStart");
    549 
    550   if (InFunctionScope)
    551     return parseError();
    552 
    553   InFunctionScope = true;
    554 
    555   StringRef LinkageName;
    556   W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
    557   W.printHex("PtrParent", Proc.Header.PtrParent);
    558   W.printHex("PtrEnd", Proc.Header.PtrEnd);
    559   W.printHex("PtrNext", Proc.Header.PtrNext);
    560   W.printHex("CodeSize", Proc.Header.CodeSize);
    561   W.printHex("DbgStart", Proc.Header.DbgStart);
    562   W.printHex("DbgEnd", Proc.Header.DbgEnd);
    563   CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType);
    564   if (ObjDelegate) {
    565     ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
    566                                      Proc.Header.CodeOffset, &LinkageName);
    567   }
    568   W.printHex("Segment", Proc.Header.Segment);
    569   W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
    570                getProcSymFlagNames());
    571   W.printString("DisplayName", Proc.Name);
    572   if (!LinkageName.empty())
    573     W.printString("LinkageName", LinkageName);
    574 }
    575 
    576 void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
    577                                           ScopeEndSym &ScopeEnd) {
    578   if (Kind == SymbolKind::S_END)
    579     DictScope S(W, "BlockEnd");
    580   else if (Kind == SymbolKind::S_PROC_ID_END)
    581     DictScope S(W, "ProcEnd");
    582   else if (Kind == SymbolKind::S_INLINESITE_END)
    583     DictScope S(W, "InlineSiteEnd");
    584 
    585   InFunctionScope = false;
    586 }
    587 
    588 void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
    589   ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
    590   for (auto FuncID : Caller.Indices)
    591     CVTD.printTypeIndex("FuncID", FuncID);
    592 }
    593 
    594 void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
    595                                              RegRelativeSym &RegRel) {
    596   DictScope S(W, "RegRelativeSym");
    597 
    598   W.printHex("Offset", RegRel.Header.Offset);
    599   CVTD.printTypeIndex("Type", RegRel.Header.Type);
    600   W.printHex("Register", RegRel.Header.Register);
    601   W.printString("VarName", RegRel.Name);
    602 }
    603 
    604 void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
    605                                                  ThreadLocalDataSym &Data) {
    606   DictScope S(W, "ThreadLocalDataSym");
    607 
    608   StringRef LinkageName;
    609   if (ObjDelegate) {
    610     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
    611                                      Data.Header.DataOffset, &LinkageName);
    612   }
    613   CVTD.printTypeIndex("Type", Data.Header.Type);
    614   W.printString("DisplayName", Data.Name);
    615   if (!LinkageName.empty())
    616     W.printString("LinkageName", LinkageName);
    617 }
    618 
    619 void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
    620   DictScope S(W, "UDT");
    621   CVTD.printTypeIndex("Type", UDT.Header.Type);
    622   W.printString("UDTName", UDT.Name);
    623 }
    624 
    625 void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
    626                                             ArrayRef<uint8_t> Data) {
    627   DictScope S(W, "UnknownSym");
    628   W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
    629   W.printNumber("Length", uint32_t(Data.size()));
    630 }
    631 
    632 bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
    633   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
    634   Dumper.visitSymbolRecord(Record);
    635   return !Dumper.hadError();
    636 }
    637 
    638 bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
    639   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
    640   Dumper.visitSymbolStream(Symbols);
    641   return !Dumper.hadError();
    642 }
    643