//===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDumper.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/ScopedPrinter.h" #include <system_error> using namespace llvm; using namespace llvm::codeview; namespace { /// Use this private dumper implementation to keep implementation details about /// the visitor out of SymbolDumper.h. class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> { public: CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate, ScopedPrinter &W, bool PrintRecordBytes) : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate), W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} /// CVSymbolVisitor overrides. #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ void visit##Name(SymbolKind Kind, Name &Record); #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def" void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data); void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData); void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data); private: void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, uint32_t RelocationOffset); void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps); CVTypeDumper &CVTD; SymbolDumpDelegate *ObjDelegate; ScopedPrinter &W; bool PrintRecordBytes; bool InFunctionScope; }; } void CVSymbolDumperImpl::printLocalVariableAddrRange( const LocalVariableAddrRange &Range, uint32_t RelocationOffset) { DictScope S(W, "LocalVariableAddrRange"); if (ObjDelegate) ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset, Range.OffsetStart); W.printHex("ISectStart", Range.ISectStart); W.printHex("Range", Range.Range); } void CVSymbolDumperImpl::printLocalVariableAddrGap( ArrayRef<LocalVariableAddrGap> Gaps) { for (auto &Gap : Gaps) { ListScope S(W, "LocalVariableAddrGap"); W.printHex("GapStartOffset", Gap.GapStartOffset); W.printHex("Range", Gap.Range); } } void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data) {} void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData) { if (PrintRecordBytes && ObjDelegate) ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData); } void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) { DictScope S(W, "BlockStart"); StringRef LinkageName; W.printHex("PtrParent", Block.Header.PtrParent); W.printHex("PtrEnd", Block.Header.PtrEnd); W.printHex("CodeSize", Block.Header.CodeSize); if (ObjDelegate) { ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(), Block.Header.CodeOffset, &LinkageName); } W.printHex("Segment", Block.Header.Segment); W.printString("BlockName", Block.Name); W.printString("LinkageName", LinkageName); } void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) { DictScope S(W, "Thunk32"); W.printNumber("Parent", Thunk.Header.Parent); W.printNumber("End", Thunk.Header.End); W.printNumber("Next", Thunk.Header.Next); W.printNumber("Off", Thunk.Header.Off); W.printNumber("Seg", Thunk.Header.Seg); W.printNumber("Len", Thunk.Header.Len); W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames()); } void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind, TrampolineSym &Tramp) { DictScope S(W, "Trampoline"); W.printEnum("Type", Tramp.Header.Type, getTrampolineNames()); W.printNumber("Size", Tramp.Header.Size); W.printNumber("ThunkOff", Tramp.Header.ThunkOff); W.printNumber("TargetOff", Tramp.Header.TargetOff); W.printNumber("ThunkSection", Tramp.Header.ThunkSection); W.printNumber("TargetSection", Tramp.Header.TargetSection); } void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) { DictScope S(W, "Section"); W.printNumber("SectionNumber", Section.Header.SectionNumber); W.printNumber("Alignment", Section.Header.Alignment); W.printNumber("Reserved", Section.Header.Reserved); W.printNumber("Rva", Section.Header.Rva); W.printNumber("Length", Section.Header.Length); W.printFlags("Characteristics", Section.Header.Characteristics, getImageSectionCharacteristicNames(), COFF::SectionCharacteristics(0x00F00000)); W.printString("Name", Section.Name); } void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind, CoffGroupSym &CoffGroup) { DictScope S(W, "COFF Group"); W.printNumber("Size", CoffGroup.Header.Size); W.printFlags("Characteristics", CoffGroup.Header.Characteristics, getImageSectionCharacteristicNames(), COFF::SectionCharacteristics(0x00F00000)); W.printNumber("Offset", CoffGroup.Header.Offset); W.printNumber("Segment", CoffGroup.Header.Segment); W.printString("Name", CoffGroup.Name); } void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind, BPRelativeSym &BPRel) { DictScope S(W, "BPRelativeSym"); W.printNumber("Offset", BPRel.Header.Offset); CVTD.printTypeIndex("Type", BPRel.Header.Type); W.printString("VarName", BPRel.Name); } void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind, BuildInfoSym &BuildInfo) { DictScope S(W, "BuildInfo"); W.printNumber("BuildId", BuildInfo.Header.BuildId); } void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind, CallSiteInfoSym &CallSiteInfo) { DictScope S(W, "CallSiteInfo"); StringRef LinkageName; if (ObjDelegate) { ObjDelegate->printRelocatedField( "CodeOffset", CallSiteInfo.getRelocationOffset(), CallSiteInfo.Header.CodeOffset, &LinkageName); } W.printHex("Segment", CallSiteInfo.Header.Segment); W.printHex("Reserved", CallSiteInfo.Header.Reserved); CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); } void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind, EnvBlockSym &EnvBlock) { DictScope S(W, "EnvBlock"); W.printNumber("Reserved", EnvBlock.Header.Reserved); ListScope L(W, "Entries"); for (auto Entry : EnvBlock.Fields) { W.printString(Entry); } } void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind, FileStaticSym &FileStatic) { DictScope S(W, "FileStatic"); W.printNumber("Index", FileStatic.Header.Index); W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset); W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames()); W.printString("Name", FileStatic.Name); } void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) { DictScope S(W, "Export"); W.printNumber("Ordinal", Export.Header.Ordinal); W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames()); W.printString("Name", Export.Name); } void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind, Compile2Sym &Compile2) { DictScope S(W, "CompilerFlags2"); W.printEnum("Language", Compile2.Header.getLanguage(), getSourceLanguageNames()); W.printFlags("Flags", Compile2.Header.flags & ~0xff, getCompileSym2FlagNames()); W.printEnum("Machine", unsigned(Compile2.Header.Machine), getCPUTypeNames()); std::string FrontendVersion; { raw_string_ostream Out(FrontendVersion); Out << Compile2.Header.VersionFrontendMajor << '.' << Compile2.Header.VersionFrontendMinor << '.' << Compile2.Header.VersionFrontendBuild; } std::string BackendVersion; { raw_string_ostream Out(BackendVersion); Out << Compile2.Header.VersionBackendMajor << '.' << Compile2.Header.VersionBackendMinor << '.' << Compile2.Header.VersionBackendBuild; } W.printString("FrontendVersion", FrontendVersion); W.printString("BackendVersion", BackendVersion); W.printString("VersionName", Compile2.Version); } void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind, Compile3Sym &Compile3) { DictScope S(W, "CompilerFlags3"); W.printEnum("Language", Compile3.Header.getLanguage(), getSourceLanguageNames()); W.printFlags("Flags", Compile3.Header.flags & ~0xff, getCompileSym3FlagNames()); W.printEnum("Machine", unsigned(Compile3.Header.Machine), getCPUTypeNames()); std::string FrontendVersion; { raw_string_ostream Out(FrontendVersion); Out << Compile3.Header.VersionFrontendMajor << '.' << Compile3.Header.VersionFrontendMinor << '.' << Compile3.Header.VersionFrontendBuild << '.' << Compile3.Header.VersionFrontendQFE; } std::string BackendVersion; { raw_string_ostream Out(BackendVersion); Out << Compile3.Header.VersionBackendMajor << '.' << Compile3.Header.VersionBackendMinor << '.' << Compile3.Header.VersionBackendBuild << '.' << Compile3.Header.VersionBackendQFE; } W.printString("FrontendVersion", FrontendVersion); W.printString("BackendVersion", BackendVersion); W.printString("VersionName", Compile3.Version); } void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind, ConstantSym &Constant) { DictScope S(W, "Constant"); CVTD.printTypeIndex("Type", Constant.Header.Type); W.printNumber("Value", Constant.Value); W.printString("Name", Constant.Name); } void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) { DictScope S(W, "DataSym"); W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames()); StringRef LinkageName; if (ObjDelegate) { ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), Data.Header.DataOffset, &LinkageName); } CVTD.printTypeIndex("Type", Data.Header.Type); W.printString("DisplayName", Data.Name); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); } void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym( SymbolKind Kind, DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { DictScope S(W, "DefRangeFramePointerRelFullScope"); W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset); } void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym( SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { DictScope S(W, "DefRangeFramePointerRel"); W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset); printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range, DefRangeFramePointerRel.getRelocationOffset()); printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); } void CVSymbolDumperImpl::visitDefRangeRegisterRelSym( SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) { DictScope S(W, "DefRangeRegisterRel"); W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister); W.printBoolean("HasSpilledUDTMember", DefRangeRegisterRel.hasSpilledUDTMember()); W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent()); W.printNumber("BasePointerOffset", DefRangeRegisterRel.Header.BasePointerOffset); printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range, DefRangeRegisterRel.getRelocationOffset()); printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); } void CVSymbolDumperImpl::visitDefRangeRegisterSym( SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) { DictScope S(W, "DefRangeRegister"); W.printNumber("Register", DefRangeRegister.Header.Register); W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName); printLocalVariableAddrRange(DefRangeRegister.Header.Range, DefRangeRegister.getRelocationOffset()); printLocalVariableAddrGap(DefRangeRegister.Gaps); } void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym( SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { DictScope S(W, "DefRangeSubfieldRegister"); W.printNumber("Register", DefRangeSubfieldRegister.Header.Register); W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName); W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Header.OffsetInParent); printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range, DefRangeSubfieldRegister.getRelocationOffset()); printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); } void CVSymbolDumperImpl::visitDefRangeSubfieldSym( SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) { DictScope S(W, "DefRangeSubfield"); if (ObjDelegate) { StringRef StringTable = ObjDelegate->getStringTable(); auto ProgramStringTableOffset = DefRangeSubfield.Header.Program; if (ProgramStringTableOffset >= StringTable.size()) return parseError(); StringRef Program = StringTable.drop_front(ProgramStringTableOffset).split('\0').first; W.printString("Program", Program); } W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent); printLocalVariableAddrRange(DefRangeSubfield.Header.Range, DefRangeSubfield.getRelocationOffset()); printLocalVariableAddrGap(DefRangeSubfield.Gaps); } void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind, DefRangeSym &DefRange) { DictScope S(W, "DefRange"); if (ObjDelegate) { StringRef StringTable = ObjDelegate->getStringTable(); auto ProgramStringTableOffset = DefRange.Header.Program; if (ProgramStringTableOffset >= StringTable.size()) return parseError(); StringRef Program = StringTable.drop_front(ProgramStringTableOffset).split('\0').first; W.printString("Program", Program); } printLocalVariableAddrRange(DefRange.Header.Range, DefRange.getRelocationOffset()); printLocalVariableAddrGap(DefRange.Gaps); } void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind, FrameCookieSym &FrameCookie) { DictScope S(W, "FrameCookie"); StringRef LinkageName; if (ObjDelegate) { ObjDelegate->printRelocatedField( "CodeOffset", FrameCookie.getRelocationOffset(), FrameCookie.Header.CodeOffset, &LinkageName); } W.printHex("Register", FrameCookie.Header.Register); W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind), getFrameCookieKindNames()); W.printHex("Flags", FrameCookie.Header.Flags); } void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind, FrameProcSym &FrameProc) { DictScope S(W, "FrameProc"); W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes); W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes); W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding); W.printHex("BytesOfCalleeSavedRegisters", FrameProc.Header.BytesOfCalleeSavedRegisters); W.printHex("OffsetOfExceptionHandler", FrameProc.Header.OffsetOfExceptionHandler); W.printHex("SectionIdOfExceptionHandler", FrameProc.Header.SectionIdOfExceptionHandler); W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames()); } void CVSymbolDumperImpl::visitHeapAllocationSiteSym( SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) { DictScope S(W, "HeapAllocationSite"); StringRef LinkageName; if (ObjDelegate) { ObjDelegate->printRelocatedField( "CodeOffset", HeapAllocSite.getRelocationOffset(), HeapAllocSite.Header.CodeOffset, &LinkageName); } W.printHex("Segment", HeapAllocSite.Header.Segment); W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize); CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); } void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind, InlineSiteSym &InlineSite) { DictScope S(W, "InlineSite"); W.printHex("PtrParent", InlineSite.Header.PtrParent); W.printHex("PtrEnd", InlineSite.Header.PtrEnd); CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee); ListScope BinaryAnnotations(W, "BinaryAnnotations"); for (auto &Annotation : InlineSite.annotations()) { switch (Annotation.OpCode) { case BinaryAnnotationsOpCode::Invalid: return parseError(); case BinaryAnnotationsOpCode::CodeOffset: case BinaryAnnotationsOpCode::ChangeCodeOffset: case BinaryAnnotationsOpCode::ChangeCodeLength: W.printHex(Annotation.Name, Annotation.U1); break; case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: case BinaryAnnotationsOpCode::ChangeLineEndDelta: case BinaryAnnotationsOpCode::ChangeRangeKind: case BinaryAnnotationsOpCode::ChangeColumnStart: case BinaryAnnotationsOpCode::ChangeColumnEnd: W.printNumber(Annotation.Name, Annotation.U1); break; case BinaryAnnotationsOpCode::ChangeLineOffset: case BinaryAnnotationsOpCode::ChangeColumnEndDelta: W.printNumber(Annotation.Name, Annotation.S1); break; case BinaryAnnotationsOpCode::ChangeFile: if (ObjDelegate) { W.printHex("ChangeFile", ObjDelegate->getFileNameForFileOffset(Annotation.U1), Annotation.U1); } else { W.printHex("ChangeFile", Annotation.U1); } break; case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: { W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: " << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1 << "}\n"; break; } case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: { W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: " << W.hex(Annotation.U2) << ", Length: " << W.hex(Annotation.U1) << "}\n"; break; } } } } void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind, RegisterSym &Register) { DictScope S(W, "RegisterSym"); W.printNumber("Type", Register.Header.Index); W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames()); W.printString("Name", Register.Name); } void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind, PublicSym32 &Public) { DictScope S(W, "PublicSym"); W.printNumber("Type", Public.Header.Index); W.printNumber("Seg", Public.Header.Seg); W.printNumber("Off", Public.Header.Off); W.printString("Name", Public.Name); } void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) { DictScope S(W, "ProcRef"); W.printNumber("SumName", ProcRef.Header.SumName); W.printNumber("SymOffset", ProcRef.Header.SymOffset); W.printNumber("Mod", ProcRef.Header.Mod); W.printString("Name", ProcRef.Name); } void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) { DictScope S(W, "Label"); StringRef LinkageName; if (ObjDelegate) { ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(), Label.Header.CodeOffset, &LinkageName); } W.printHex("Segment", Label.Header.Segment); W.printHex("Flags", Label.Header.Flags); W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames()); W.printString("DisplayName", Label.Name); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); } void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) { DictScope S(W, "Local"); CVTD.printTypeIndex("Type", Local.Header.Type); W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames()); W.printString("VarName", Local.Name); } void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) { DictScope S(W, "ObjectName"); W.printHex("Signature", ObjName.Header.Signature); W.printString("ObjectName", ObjName.Name); } void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) { DictScope S(W, "ProcStart"); if (InFunctionScope) return parseError(); InFunctionScope = true; StringRef LinkageName; W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames()); W.printHex("PtrParent", Proc.Header.PtrParent); W.printHex("PtrEnd", Proc.Header.PtrEnd); W.printHex("PtrNext", Proc.Header.PtrNext); W.printHex("CodeSize", Proc.Header.CodeSize); W.printHex("DbgStart", Proc.Header.DbgStart); W.printHex("DbgEnd", Proc.Header.DbgEnd); CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType); if (ObjDelegate) { ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(), Proc.Header.CodeOffset, &LinkageName); } W.printHex("Segment", Proc.Header.Segment); W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags), getProcSymFlagNames()); W.printString("DisplayName", Proc.Name); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); } void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind, ScopeEndSym &ScopeEnd) { if (Kind == SymbolKind::S_END) DictScope S(W, "BlockEnd"); else if (Kind == SymbolKind::S_PROC_ID_END) DictScope S(W, "ProcEnd"); else if (Kind == SymbolKind::S_INLINESITE_END) DictScope S(W, "InlineSiteEnd"); InFunctionScope = false; } void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) { ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers"); for (auto FuncID : Caller.Indices) CVTD.printTypeIndex("FuncID", FuncID); } void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind, RegRelativeSym &RegRel) { DictScope S(W, "RegRelativeSym"); W.printHex("Offset", RegRel.Header.Offset); CVTD.printTypeIndex("Type", RegRel.Header.Type); W.printHex("Register", RegRel.Header.Register); W.printString("VarName", RegRel.Name); } void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind, ThreadLocalDataSym &Data) { DictScope S(W, "ThreadLocalDataSym"); StringRef LinkageName; if (ObjDelegate) { ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(), Data.Header.DataOffset, &LinkageName); } CVTD.printTypeIndex("Type", Data.Header.Type); W.printString("DisplayName", Data.Name); if (!LinkageName.empty()) W.printString("LinkageName", LinkageName); } void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) { DictScope S(W, "UDT"); CVTD.printTypeIndex("Type", UDT.Header.Type); W.printString("UDTName", UDT.Name); } void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data) { DictScope S(W, "UnknownSym"); W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames()); W.printNumber("Length", uint32_t(Data.size())); } bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) { CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); Dumper.visitSymbolRecord(Record); return !Dumper.hadError(); } bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) { CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); Dumper.visitSymbolStream(Symbols); return !Dumper.hadError(); }