forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			643 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			643 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- 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();
 | |
| }
 |