Index: include/llvm/DebugInfo/CodeView/CVSymbolTypes.def =================================================================== --- include/llvm/DebugInfo/CodeView/CVSymbolTypes.def +++ include/llvm/DebugInfo/CodeView/CVSymbolTypes.def @@ -30,7 +30,6 @@ CV_SYMBOL(S_CONSTANT_16t , 0x0003) CV_SYMBOL(S_UDT_16t , 0x0004) CV_SYMBOL(S_SSEARCH , 0x0005) -CV_SYMBOL(S_END , 0x0006) CV_SYMBOL(S_SKIP , 0x0007) CV_SYMBOL(S_CVRESERVE , 0x0008) CV_SYMBOL(S_OBJNAME_ST , 0x0009) @@ -179,12 +178,6 @@ CV_SYMBOL(S_LPROCIA64_ID , 0x114a) CV_SYMBOL(S_GPROCIA64_ID , 0x114b) -// Inlined call site delimiters. -CV_SYMBOL(S_INLINESITE_END , 0x114e) - -// Procedure info end delimiter. -CV_SYMBOL(S_PROC_ID_END , 0x114f) - CV_SYMBOL(S_DEFRANGE_HLSL , 0x1150) CV_SYMBOL(S_GDATA_HLSL , 0x1151) CV_SYMBOL(S_LDATA_HLSL , 0x1152) @@ -193,8 +186,6 @@ CV_SYMBOL(S_DEFRANGE_DPC_PTR_TAG, 0x1157) CV_SYMBOL(S_DPC_SYM_TAG_MAP, 0x1158) CV_SYMBOL(S_ARMSWITCHTABLE , 0x1159) -CV_SYMBOL(S_CALLEES , 0x115a) -CV_SYMBOL(S_CALLERS , 0x115b) CV_SYMBOL(S_POGODATA , 0x115c) CV_SYMBOL(S_INLINESITE2 , 0x115d) CV_SYMBOL(S_MOD_TYPEREF , 0x115f) @@ -206,19 +197,24 @@ CV_SYMBOL(S_LDATA_HLSL32_EX, 0x1165) // Known symbol types +SYMBOL_RECORD(S_END , 0x0006, ScopeEndSym) +SYMBOL_RECORD_ALIAS(S_INLINESITE_END , 0x114e, InlineSiteEnd, ScopeEndSym) +SYMBOL_RECORD_ALIAS(S_PROC_ID_END , 0x114f, ProcEnd, ScopeEndSym) + SYMBOL_RECORD(S_LPROC32 , 0x110f, ProcSym) SYMBOL_RECORD_ALIAS(S_GPROC32 , 0x1110, GlobalProcSym, ProcSym) SYMBOL_RECORD_ALIAS(S_LPROC32_ID , 0x1146, ProcIdSym, ProcSym) SYMBOL_RECORD_ALIAS(S_GPROC32_ID , 0x1147, GlobalProcIdSym, ProcSym) SYMBOL_RECORD_ALIAS(S_LPROC32_DPC , 0x1155, DPCProcSym, ProcSym) SYMBOL_RECORD_ALIAS(S_LPROC32_DPC_ID , 0x1156, DPCProcIdSym, ProcSym) + SYMBOL_RECORD(S_INLINESITE , 0x114d, InlineSiteSym) SYMBOL_RECORD(S_LOCAL , 0x113e, LocalSym) SYMBOL_RECORD(S_DEFRANGE , 0x113f, DefRangeSym) SYMBOL_RECORD(S_DEFRANGE_SUBFIELD, 0x1140, DefRangeSubfieldSym) SYMBOL_RECORD(S_DEFRANGE_REGISTER, 0x1141, DefRangeRegisterSym) -SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL, 0x1142, DefRangeSubfieldRegisterSym) -SYMBOL_RECORD(S_DEFRANGE_SUBFIELD_REGISTER, 0x1143, DefRangeFramePointerRelSym) +SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL, 0x1142, DefRangeFramePointerRelSym) +SYMBOL_RECORD(S_DEFRANGE_SUBFIELD_REGISTER, 0x1143, DefRangeSubfieldRegisterSym) SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE, 0x1144, DefRangeFramePointerRelFullScopeSym) SYMBOL_RECORD(S_DEFRANGE_REGISTER_REL, 0x1145, DefRangeRegisterRelSym) SYMBOL_RECORD(S_BLOCK32 , 0x1103, BlockSym) @@ -229,17 +225,25 @@ SYMBOL_RECORD(S_CALLSITEINFO , 0x1139, CallSiteInfoSym) SYMBOL_RECORD(S_HEAPALLOCSITE , 0x115e, HeapAllocationSiteSym) SYMBOL_RECORD(S_FRAMECOOKIE , 0x113a, FrameCookieSym) + +SYMBOL_RECORD(S_CALLEES , 0x115a, CallerSym) +SYMBOL_RECORD_ALIAS(S_CALLERS , 0x115b, CalleeSym, CallerSym) + SYMBOL_RECORD(S_UDT , 0x1108, UDTSym) SYMBOL_RECORD_ALIAS(S_COBOLUDT , 0x1109, CobolUDT, UDTSym) + SYMBOL_RECORD(S_BUILDINFO , 0x114c, BuildInfoSym) SYMBOL_RECORD(S_BPREL32 , 0x110b, BPRelativeSym) SYMBOL_RECORD(S_REGREL32 , 0x1111, RegRelativeSym) + SYMBOL_RECORD(S_CONSTANT , 0x1107, ConstantSym) SYMBOL_RECORD_ALIAS(S_MANCONSTANT , 0x112d, ManagedConstant, ConstantSym) + SYMBOL_RECORD(S_LDATA32 , 0x110c, DataSym) SYMBOL_RECORD_ALIAS(S_GDATA32 , 0x110d, GlobalData, DataSym) SYMBOL_RECORD_ALIAS(S_LMANDATA , 0x111c, ManagedLocalData, DataSym) SYMBOL_RECORD_ALIAS(S_GMANDATA , 0x111d, ManagedGlobalData, DataSym) + SYMBOL_RECORD(S_LTHREAD32 , 0x1112, ThreadLocalDataSym) SYMBOL_RECORD_ALIAS(S_GTHREAD32 , 0x1113, GlobalTLS, ThreadLocalDataSym) Index: include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -0,0 +1,104 @@ +//===- CVSymbolVisitor.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/RecordIterator.h" +#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/Support/ErrorOr.h" + +namespace llvm { +namespace codeview { + +template class CVSymbolVisitor { +public: + CVSymbolVisitor(SymbolDumpDelegate *ObjDelegate) : ObjDelegate(ObjDelegate) {} + + bool hadError() const { return HadError; } + + template + bool consumeObject(ArrayRef &Data, const T *&Res) { + if (Data.size() < sizeof(*Res)) { + HadError = true; + return false; + } + Res = reinterpret_cast(Data.data()); + Data = Data.drop_front(sizeof(*Res)); + return true; + } + +/// Actions to take on known symbols. By default, they do nothing. Visit methods +/// for member records take the FieldData by non-const reference and are +/// expected to consume the trailing bytes used by the field. +/// FIXME: Make the visitor interpret the trailing bytes so that clients don't +/// need to. +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + void visit##Name(SymbolRecordKind Kind, Name &Record) {} +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "CVSymbolTypes.def" + + void visitSymbolRecord(const SymbolIterator::Record &Record) { + ArrayRef Data = Record.Data; + auto *DerivedThis = static_cast(this); + DerivedThis->visitSymbolBegin(Record.Type, Data); + uint32_t RecordOffset = + ObjDelegate ? ObjDelegate->getRecordOffset(Data) : 0; + switch (Record.Type) { + default: + DerivedThis->visitUnknownSymbol(Record.Type, Data); + break; +#define SYMBOL_RECORD(EnumName, EnumVal, Name) \ + case EnumName: { \ + SymbolRecordKind RK = static_cast(EnumName); \ + auto Result = Name::deserialize(RK, RecordOffset, Data); \ + if (Result.getError()) \ + return parseError(); \ + DerivedThis->visit##Name(Record.Type, *Result); \ + break; \ + } +#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ + SYMBOL_RECORD(EnumVal, EnumVal, AliasName) +#include "CVSymbolTypes.def" + } + DerivedThis->visitSymbolEnd(Record.Type, Record.Data); + } + + /// Visits the symbol records in Data. Sets the error flag on parse failures. + void visitSymbolStream(ArrayRef Data) { + for (const auto &I : makeSymbolRange(Data, &HadError)) { + visitSymbolRecord(I); + if (hadError()) + break; + } + } + + /// Action to take on unknown symbols. By default, they are ignored. + void visitUnknownSymbol(SymbolKind Kind, ArrayRef Data) {} + + /// Paired begin/end actions for all symbols. Receives all record data, + /// including the fixed-length record prefix. + void visitSymbolBegin(SymbolKind Leaf, ArrayRef RecordData) {} + void visitSymbolEnd(SymbolKind Leaf, ArrayRef OriginalSymData) {} + + /// Helper for returning from a void function when the stream is corrupted. + void parseError() { HadError = true; } + +private: + SymbolDumpDelegate *ObjDelegate; + /// Whether a symbol stream parsing error was encountered. + bool HadError = false; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H Index: include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h @@ -0,0 +1,38 @@ +//===-- SymbolDumpDelegate.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" + +#include + +namespace llvm { + +namespace codeview { + +class SymbolDumpDelegate { +public: + virtual ~SymbolDumpDelegate() {} + + virtual uint32_t getRecordOffset(ArrayRef Record) = 0; + virtual void printRelocatedField(StringRef Label, uint32_t RelocOffset, + uint32_t Offset, + StringRef *RelocSym = nullptr) = 0; + virtual void printBinaryBlockWithRelocs(StringRef Label, + ArrayRef Block) = 0; + virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0; + virtual StringRef getStringTable() = 0; +}; +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H Index: include/llvm/DebugInfo/CodeView/SymbolDumper.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -0,0 +1,54 @@ +//===-- SymbolDumper.h - 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" + +namespace llvm { +class ScopedPrinter; + +namespace codeview { +class CVTypeDumper; + +/// Dumper for CodeView symbol streams found in COFF object files and PDB files. +class CVSymbolDumper { +public: + CVSymbolDumper(ScopedPrinter &W, CVTypeDumper &CVTD, + std::unique_ptr ObjDelegate, + bool PrintRecordBytes) + : W(W), CVTD(CVTD), ObjDelegate(std::move(ObjDelegate)), + PrintRecordBytes(PrintRecordBytes) {} + + /// Dumps one type record. Returns false if there was a type parsing error, + /// and true otherwise. This should be called in order, since the dumper + /// maintains state about previous records which are necessary for cross + /// type references. + bool dump(const SymbolIterator::Record &Record); + + /// Dumps the type records in Data. Returns false if there was a type stream + /// parse error, and true otherwise. + bool dump(ArrayRef Data); + +private: + ScopedPrinter &W; + CVTypeDumper &CVTD; + std::unique_ptr ObjDelegate; + + bool PrintRecordBytes; +}; +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H Index: include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -79,6 +79,46 @@ StringRef Name; }; +class ScopeEndSym : public SymbolRecord { +public: + ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset) + : SymbolRecord(Kind), RecordOffset(RecordOffset) {} + + static ErrorOr deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + return ScopeEndSym(Kind, RecordOffset); + } + uint32_t RecordOffset; +}; + +class CallerSym : public SymbolRecord { +public: + struct Hdr { + uint32_t Count; + }; + + CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header, + ArrayRef Indices) + : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header), + Indices(Indices) {} + + static ErrorOr deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *Header; + ArrayRef Indices; + + CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count)); + + return CallerSym(Kind, RecordOffset, Header, Indices); + } + + Hdr Header; + uint32_t RecordOffset; + ArrayRef Indices; +}; + struct BinaryAnnotationIterator { struct AnnotationData { BinaryAnnotationsOpCode OpCode; @@ -697,7 +737,7 @@ }; // S_COMPILE3 -class CompileSym3 : public SymbolRecord { +class Compile3Sym : public SymbolRecord { public: struct Hdr { ulittle32_t flags; // CompileSym3Flags enum @@ -714,18 +754,18 @@ // VersionString: The null-terminated version string follows. }; - CompileSym3(uint32_t RecordOffset, const Hdr *H, StringRef Version) + Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version) : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset), Header(*H), Version(Version) {} - static ErrorOr deserialize(SymbolRecordKind Kind, + static ErrorOr deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, ArrayRef &Data) { const Hdr *H = nullptr; StringRef Version; CV_DESERIALIZE(Data, H, Version); - return CompileSym3(RecordOffset, H, Version); + return Compile3Sym(RecordOffset, H, Version); } uint32_t RecordOffset; @@ -1060,10 +1100,11 @@ StringRef Name; }; -typedef RecordIterator SymbolIterator; +typedef RecordIterator SymbolIterator; -inline iterator_range makeSymbolRange(ArrayRef Data) { - return make_range(SymbolIterator(Data, nullptr), SymbolIterator()); +inline iterator_range makeSymbolRange(ArrayRef Data, + bool *HadError) { + return make_range(SymbolIterator(Data, HadError), SymbolIterator()); } } // namespace codeview Index: lib/DebugInfo/CodeView/CMakeLists.txt =================================================================== --- lib/DebugInfo/CodeView/CMakeLists.txt +++ lib/DebugInfo/CodeView/CMakeLists.txt @@ -5,6 +5,7 @@ MemoryTypeTableBuilder.cpp MethodListRecordBuilder.cpp RecordSerialization.cpp + SymbolDumper.cpp TypeDumper.cpp TypeRecord.cpp TypeRecordBuilder.cpp Index: lib/DebugInfo/CodeView/SymbolDumper.cpp =================================================================== --- /dev/null +++ lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -0,0 +1,670 @@ +//===-- 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/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 + +using namespace llvm; +using namespace llvm::codeview; + +static const EnumEntry SymbolTypeNames[] = { +#define CV_SYMBOL(enum, val) {#enum, enum}, +#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def" +}; + +namespace { +#define CV_ENUM_CLASS_ENT(enum_class, enum) \ + { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) } + +#define CV_ENUM_ENT(ns, enum) \ + { #enum, ns::enum } + +static const EnumEntry ProcSymFlagNames[] = { + CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP), + CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET), + CV_ENUM_CLASS_ENT(ProcSymFlags, HasFRET), + CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoReturn), + CV_ENUM_CLASS_ENT(ProcSymFlags, IsUnreachable), + CV_ENUM_CLASS_ENT(ProcSymFlags, HasCustomCallingConv), + CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoInline), + CV_ENUM_CLASS_ENT(ProcSymFlags, HasOptimizedDebugInfo), +}; + +static const EnumEntry LocalFlags[] = { + CV_ENUM_CLASS_ENT(LocalSymFlags, IsParameter), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsAddressTaken), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsCompilerGenerated), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregate), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregated), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsAliased), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsAlias), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsReturnValue), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsOptimizedOut), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredGlobal), + CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredStatic), +}; + +static const EnumEntry FrameCookieKinds[] = { + CV_ENUM_CLASS_ENT(FrameCookieKind, Copy), + CV_ENUM_CLASS_ENT(FrameCookieKind, XorStackPointer), + CV_ENUM_CLASS_ENT(FrameCookieKind, XorFramePointer), + CV_ENUM_CLASS_ENT(FrameCookieKind, XorR13), +}; + +static const EnumEntry SourceLanguages[] = { + CV_ENUM_ENT(SourceLanguage, C), CV_ENUM_ENT(SourceLanguage, Cpp), + CV_ENUM_ENT(SourceLanguage, Fortran), CV_ENUM_ENT(SourceLanguage, Masm), + CV_ENUM_ENT(SourceLanguage, Pascal), CV_ENUM_ENT(SourceLanguage, Basic), + CV_ENUM_ENT(SourceLanguage, Cobol), CV_ENUM_ENT(SourceLanguage, Link), + CV_ENUM_ENT(SourceLanguage, Cvtres), CV_ENUM_ENT(SourceLanguage, Cvtpgd), + CV_ENUM_ENT(SourceLanguage, CSharp), CV_ENUM_ENT(SourceLanguage, VB), + CV_ENUM_ENT(SourceLanguage, ILAsm), CV_ENUM_ENT(SourceLanguage, Java), + CV_ENUM_ENT(SourceLanguage, JScript), CV_ENUM_ENT(SourceLanguage, MSIL), + CV_ENUM_ENT(SourceLanguage, HLSL), +}; + +static const EnumEntry CompileSym3FlagNames[] = { + CV_ENUM_CLASS_ENT(CompileSym3Flags, EC), + CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDbgInfo), + CV_ENUM_CLASS_ENT(CompileSym3Flags, LTCG), + CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDataAlign), + CV_ENUM_CLASS_ENT(CompileSym3Flags, ManagedPresent), + CV_ENUM_CLASS_ENT(CompileSym3Flags, SecurityChecks), + CV_ENUM_CLASS_ENT(CompileSym3Flags, HotPatch), + CV_ENUM_CLASS_ENT(CompileSym3Flags, CVTCIL), + CV_ENUM_CLASS_ENT(CompileSym3Flags, MSILModule), + CV_ENUM_CLASS_ENT(CompileSym3Flags, Sdl), + CV_ENUM_CLASS_ENT(CompileSym3Flags, PGO), + CV_ENUM_CLASS_ENT(CompileSym3Flags, Exp), +}; + +static const EnumEntry CPUTypeNames[] = { + CV_ENUM_CLASS_ENT(CPUType, Intel8080), + CV_ENUM_CLASS_ENT(CPUType, Intel8086), + CV_ENUM_CLASS_ENT(CPUType, Intel80286), + CV_ENUM_CLASS_ENT(CPUType, Intel80386), + CV_ENUM_CLASS_ENT(CPUType, Intel80486), + CV_ENUM_CLASS_ENT(CPUType, Pentium), + CV_ENUM_CLASS_ENT(CPUType, PentiumPro), + CV_ENUM_CLASS_ENT(CPUType, Pentium3), + CV_ENUM_CLASS_ENT(CPUType, MIPS), + CV_ENUM_CLASS_ENT(CPUType, MIPS16), + CV_ENUM_CLASS_ENT(CPUType, MIPS32), + CV_ENUM_CLASS_ENT(CPUType, MIPS64), + CV_ENUM_CLASS_ENT(CPUType, MIPSI), + CV_ENUM_CLASS_ENT(CPUType, MIPSII), + CV_ENUM_CLASS_ENT(CPUType, MIPSIII), + CV_ENUM_CLASS_ENT(CPUType, MIPSIV), + CV_ENUM_CLASS_ENT(CPUType, MIPSV), + CV_ENUM_CLASS_ENT(CPUType, M68000), + CV_ENUM_CLASS_ENT(CPUType, M68010), + CV_ENUM_CLASS_ENT(CPUType, M68020), + CV_ENUM_CLASS_ENT(CPUType, M68030), + CV_ENUM_CLASS_ENT(CPUType, M68040), + CV_ENUM_CLASS_ENT(CPUType, Alpha), + CV_ENUM_CLASS_ENT(CPUType, Alpha21164), + CV_ENUM_CLASS_ENT(CPUType, Alpha21164A), + CV_ENUM_CLASS_ENT(CPUType, Alpha21264), + CV_ENUM_CLASS_ENT(CPUType, Alpha21364), + CV_ENUM_CLASS_ENT(CPUType, PPC601), + CV_ENUM_CLASS_ENT(CPUType, PPC603), + CV_ENUM_CLASS_ENT(CPUType, PPC604), + CV_ENUM_CLASS_ENT(CPUType, PPC620), + CV_ENUM_CLASS_ENT(CPUType, PPCFP), + CV_ENUM_CLASS_ENT(CPUType, PPCBE), + CV_ENUM_CLASS_ENT(CPUType, SH3), + CV_ENUM_CLASS_ENT(CPUType, SH3E), + CV_ENUM_CLASS_ENT(CPUType, SH3DSP), + CV_ENUM_CLASS_ENT(CPUType, SH4), + CV_ENUM_CLASS_ENT(CPUType, SHMedia), + CV_ENUM_CLASS_ENT(CPUType, ARM3), + CV_ENUM_CLASS_ENT(CPUType, ARM4), + CV_ENUM_CLASS_ENT(CPUType, ARM4T), + CV_ENUM_CLASS_ENT(CPUType, ARM5), + CV_ENUM_CLASS_ENT(CPUType, ARM5T), + CV_ENUM_CLASS_ENT(CPUType, ARM6), + CV_ENUM_CLASS_ENT(CPUType, ARM_XMAC), + CV_ENUM_CLASS_ENT(CPUType, ARM_WMMX), + CV_ENUM_CLASS_ENT(CPUType, ARM7), + CV_ENUM_CLASS_ENT(CPUType, Omni), + CV_ENUM_CLASS_ENT(CPUType, Ia64), + CV_ENUM_CLASS_ENT(CPUType, Ia64_2), + CV_ENUM_CLASS_ENT(CPUType, CEE), + CV_ENUM_CLASS_ENT(CPUType, AM33), + CV_ENUM_CLASS_ENT(CPUType, M32R), + CV_ENUM_CLASS_ENT(CPUType, TriCore), + CV_ENUM_CLASS_ENT(CPUType, X64), + CV_ENUM_CLASS_ENT(CPUType, EBC), + CV_ENUM_CLASS_ENT(CPUType, Thumb), + CV_ENUM_CLASS_ENT(CPUType, ARMNT), + CV_ENUM_CLASS_ENT(CPUType, D3D11_Shader), +}; + +static const EnumEntry FrameProcSymFlags[] = { + CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasStructuredExceptionHandling), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, Naked), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, AsynchronousExceptionHandling), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, NoStackOrderingForSecurityChecks), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw), +}; + +/// Use this private dumper implementation to keep implementation details about +/// the visitor out of SymbolDumper.h. +class CVSymbolDumperImpl : public CVSymbolVisitor { +public: + CVSymbolDumperImpl(CVSymbolDumper &CVSD, CVTypeDumper &CVTD, + SymbolDumpDelegate *ObjDelegate, ScopedPrinter &W, + bool PrintRecordBytes) + : CVSymbolVisitor(ObjDelegate), CVSD(CVSD), 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 Data); + void visitSymbolEnd(SymbolKind Kind, ArrayRef OriginalSymData); + void visitUnknownSymbol(SymbolKind Kind, ArrayRef Data); + +private: + void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, + uint32_t RelocationOffset); + void printLocalVariableAddrGap(ArrayRef Gaps); + + CVSymbolDumper &CVSD; + 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 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 Data) {} + +void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind, + ArrayRef 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::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::visitCompile3Sym(SymbolKind Kind, + Compile3Sym &Compile3) { + DictScope S(W, "CompilerFlags"); + + W.printEnum("Language", Compile3.Header.getLanguage(), + makeArrayRef(SourceLanguages)); + W.printFlags("Flags", Compile3.Header.flags & ~0xff, + makeArrayRef(CompileSym3FlagNames)); + W.printEnum("Machine", unsigned(Compile3.Header.Machine), + makeArrayRef(CPUTypeNames)); + 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"); + + 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(); + if (!StringTable.empty()) { + W.printString("Program", + StringTable.drop_front(DefRangeSubfield.Header.Program) + .split('\0') + .first); + } + } + 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(); + if (!StringTable.empty()) { + W.printString( + "Program", + StringTable.drop_front(DefRange.Header.Program).split('\0').first); + } + } + 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), + makeArrayRef(FrameCookieKinds)); +} + +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, + makeArrayRef(FrameProcSymFlags)); +} + +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::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, makeArrayRef(ProcSymFlagNames)); + 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), makeArrayRef(LocalFlags)); + 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.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(Proc.Header.Flags), + makeArrayRef(ProcSymFlagNames)); + W.printString("DisplayName", Proc.Name); + if (!LinkageName.empty()) + W.printString("LinkageName", LinkageName); +} + +void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind, + ScopeEndSym &ScopeEnd) { + if (Kind == SymbolKind::S_END) + W.startLine() << "BlockEnd\n"; + else if (Kind == SymbolKind::S_PROC_ID_END) + W.startLine() << "ProcEnd\n"; + 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 Data) { + DictScope S(W, "UnknownSym"); + W.printHex("Kind", unsigned(Kind)); + W.printHex("Size", Data.size()); +} + +bool CVSymbolDumper::dump(const SymbolIterator::Record &Record) { + CVSymbolDumperImpl Dumper(*this, CVTD, ObjDelegate.get(), W, + PrintRecordBytes); + Dumper.visitSymbolRecord(Record); + return !Dumper.hadError(); +} + +bool CVSymbolDumper::dump(ArrayRef Data) { + CVSymbolDumperImpl Dumper(*this, CVTD, ObjDelegate.get(), W, + PrintRecordBytes); + Dumper.visitSymbolStream(Data); + return !Dumper.hadError(); +} Index: lib/DebugInfo/PDB/Raw/ModStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/ModStream.cpp +++ lib/DebugInfo/PDB/Raw/ModStream.cpp @@ -51,5 +51,5 @@ } iterator_range ModStream::symbols() const { - return codeview::makeSymbolRange(SymbolsSubstream.data().slice(4)); + return codeview::makeSymbolRange(SymbolsSubstream.data().slice(4), nullptr); } Index: tools/llvm-readobj/COFFDumper.cpp =================================================================== --- tools/llvm-readobj/COFFDumper.cpp +++ tools/llvm-readobj/COFFDumper.cpp @@ -24,8 +24,10 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" +#include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDumper.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" @@ -58,6 +60,7 @@ class COFFDumper : public ObjDumper { public: + friend class COFFObjectDumpDelegate; COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer) : ObjDumper(Writer), Obj(Obj), CVTD(Writer, opts::CodeViewSubsectionBytes) {} @@ -96,10 +99,6 @@ // Forward to CVTypeDumper for simplicity. CVTD.printTypeIndex(FieldName, TI); } - void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, - const coff_section *Sec, - uint32_t RelocationOffset); - void printLocalVariableAddrGap(ArrayRef Gaps); void printCodeViewSymbolsSubsection(StringRef Subsection, const SectionRef &Section, @@ -148,6 +147,45 @@ CVTypeDumper CVTD; }; +class COFFObjectDumpDelegate : public SymbolDumpDelegate { +public: + COFFObjectDumpDelegate(COFFDumper &CD, const SectionRef &SR, + const COFFObjectFile *Obj, StringRef SectionContents) + : CD(CD), SR(SR), Obj(Obj), SectionContents(SectionContents) { + Sec = Obj->getCOFFSection(SR); + } + + uint32_t getRecordOffset(ArrayRef Record) override { + return Record.data() - SectionContents.bytes_begin(); + } + + void printRelocatedField(StringRef Label, uint32_t RelocOffset, + uint32_t Offset, StringRef *RelocSym) override { + CD.printRelocatedField(Label, Sec, RelocOffset, Offset, RelocSym); + } + + void printBinaryBlockWithRelocs(StringRef Label, + ArrayRef Block) override { + StringRef SBlock(reinterpret_cast(Block.data()), + Block.size()); + if (opts::CodeViewSubsectionBytes) + CD.printBinaryBlockWithRelocs(Label, SR, SectionContents, SBlock); + } + + StringRef getFileNameForFileOffset(uint32_t FileOffset) override { + return CD.getFileNameForFileOffset(FileOffset); + } + + StringRef getStringTable() override { return CD.CVStringTable; } + +private: + COFFDumper &CD; + const SectionRef &SR; + const COFFObjectFile *Obj; + const coff_section *Sec; + StringRef SectionContents; +}; + } // end namespace namespace llvm { @@ -246,6 +284,7 @@ uint64_t OffsetStart = Block.data() - SectionContents.data(); uint64_t OffsetEnd = OffsetStart + Block.size(); + W.flush(); cacheRelocations(); ListScope D(W, "BlockRelocations"); const coff_section *Section = Obj->getCOFFSection(Sec); @@ -440,41 +479,6 @@ { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS } }; -static const EnumEntry CompileSym3FlagNames[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, EC), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, NoDbgInfo), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, LTCG), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, NoDataAlign), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, ManagedPresent), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, SecurityChecks), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, HotPatch), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, CVTCIL), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, MSILModule), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, Sdl), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, PGO), - LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, Exp), -}; - -static const EnumEntry SourceLanguages[] = { - LLVM_READOBJ_ENUM_ENT(SourceLanguage, C), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cpp), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Fortran), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Masm), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Pascal), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Basic), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cobol), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Link), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cvtres), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cvtpgd), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, CSharp), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, VB), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, ILAsm), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, Java), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, JScript), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, MSIL), - LLVM_READOBJ_ENUM_ENT(SourceLanguage, HLSL), -}; - static const EnumEntry SubSectionTypes[] = { LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols), LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines), @@ -491,68 +495,6 @@ LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA), }; -static const EnumEntry CPUTypeNames[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel8080), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel8086), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80286), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80386), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80486), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Pentium), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PentiumPro), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Pentium3), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS16), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS32), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS64), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSI), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSII), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSIII), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSIV), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSV), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68000), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68010), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68020), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68030), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68040), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21164), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21164A), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21264), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21364), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC601), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC603), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC604), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC620), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPCFP), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPCBE), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3E), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3DSP), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH4), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SHMedia), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM3), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM4), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM4T), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM5), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM5T), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM6), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM_XMAC), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM_WMMX), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM7), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Omni), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Ia64), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Ia64_2), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, CEE), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, AM33), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M32R), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, TriCore), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, X64), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, EBC), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Thumb), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARMNT), - LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, D3D11_Shader), -}; - static const EnumEntry ProcSymFlagNames[] = { LLVM_READOBJ_ENUM_CLASS_ENT(ProcSymFlags, HasFP), LLVM_READOBJ_ENUM_CLASS_ENT(ProcSymFlags, HasIRET), @@ -564,59 +506,12 @@ LLVM_READOBJ_ENUM_CLASS_ENT(ProcSymFlags, HasOptimizedDebugInfo), }; -static const EnumEntry FrameProcSymFlags[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, - HasStructuredExceptionHandling), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, Naked), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, - AsynchronousExceptionHandling), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, - NoStackOrderingForSecurityChecks), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, - ProfileGuidedOptimization), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw), -}; - static const EnumEntry FrameDataFlags[] = { LLVM_READOBJ_ENUM_ENT(FrameData, HasSEH), LLVM_READOBJ_ENUM_ENT(FrameData, HasEH), LLVM_READOBJ_ENUM_ENT(FrameData, IsFunctionStart), }; -static const EnumEntry LocalFlags[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsParameter), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAddressTaken), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsCompilerGenerated), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAggregate), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAggregated), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAliased), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAlias), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsReturnValue), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsOptimizedOut), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredGlobal), - LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredStatic), -}; - -static const EnumEntry FrameCookieKinds[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, Copy), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, XorStackPointer), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, XorFramePointer), - LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, XorR13), -}; - static const EnumEntry FileChecksumKindNames[] = { LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, None), LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, MD5), @@ -1009,574 +904,16 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, const SectionRef &Section, StringRef SectionContents) { - if (Subsection.size() < sizeof(RecordPrefix)) - return error(object_error::parse_failed); - - const coff_section *Sec = Obj->getCOFFSection(Section); - - // This holds the remaining data to parse. - StringRef Data = Subsection; - - bool InFunctionScope = false; - while (!Data.empty()) { - const RecordPrefix *Rec; - error(consumeObject(Data, Rec)); - - StringRef SymData = Data.substr(0, Rec->RecordLen - 2); - StringRef OrigSymData = SymData; - - Data = Data.drop_front(Rec->RecordLen - 2); - uint32_t RecordOffset = SymData.data() - SectionContents.data(); - - SymbolKind Kind = static_cast(uint16_t(Rec->RecordKind)); - switch (Kind) { - case S_LPROC32: - case S_GPROC32: - case S_GPROC32_ID: - case S_LPROC32_ID: - case S_LPROC32_DPC: - case S_LPROC32_DPC_ID: { - DictScope S(W, "ProcStart"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto ProcOrError = ProcSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!ProcOrError) - error(ProcOrError.getError()); - auto &Proc = ProcOrError.get(); - - if (InFunctionScope) - return error(object_error::parse_failed); - InFunctionScope = true; - - StringRef LinkageName; - 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); - printTypeIndex("FunctionType", Proc.Header.FunctionType); - printRelocatedField("CodeOffset", Sec, Proc.getRelocationOffset(), - Proc.Header.CodeOffset, &LinkageName); - W.printHex("Segment", Proc.Header.Segment); - W.printFlags("Flags", static_cast(Proc.Header.Flags), - makeArrayRef(ProcSymFlagNames)); - W.printString("DisplayName", Proc.Name); - W.printString("LinkageName", LinkageName); - break; - } - - case S_PROC_ID_END: { - W.startLine() << "ProcEnd\n"; - InFunctionScope = false; - break; - } - - case S_BLOCK32: { - DictScope S(W, "BlockStart"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto BlockOrError = BlockSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!BlockOrError) - error(BlockOrError.getError()); - auto &Block = BlockOrError.get(); - - StringRef LinkageName; - W.printHex("PtrParent", Block.Header.PtrParent); - W.printHex("PtrEnd", Block.Header.PtrEnd); - W.printHex("CodeSize", Block.Header.CodeSize); - printRelocatedField("CodeOffset", Sec, Block.getRelocationOffset(), - Block.Header.CodeOffset, &LinkageName); - W.printHex("Segment", Block.Header.Segment); - W.printString("BlockName", Block.Name); - W.printString("LinkageName", LinkageName); - break; - } - - case S_END: { - W.startLine() << "BlockEnd\n"; - InFunctionScope = false; - break; - } - - case S_LABEL32: { - DictScope S(W, "Label"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto LabelOrError = LabelSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!LabelOrError) - error(LabelOrError.getError()); - auto &Label = LabelOrError.get(); - - StringRef LinkageName; - printRelocatedField("CodeOffset", Sec, Label.getRelocationOffset(), - Label.Header.CodeOffset, &LinkageName); - W.printHex("Segment", Label.Header.Segment); - W.printHex("Flags", Label.Header.Flags); - W.printFlags("Flags", Label.Header.Flags, makeArrayRef(ProcSymFlagNames)); - W.printString("DisplayName", Label.Name); - W.printString("LinkageName", LinkageName); - break; - } - - case S_INLINESITE: { - DictScope S(W, "InlineSite"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto InlineSiteOrError = InlineSiteSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!InlineSiteOrError) - error(InlineSiteOrError.getError()); - auto &InlineSite = InlineSiteOrError.get(); - - W.printHex("PtrParent", InlineSite.Header.PtrParent); - W.printHex("PtrEnd", InlineSite.Header.PtrEnd); - printTypeIndex("Inlinee", InlineSite.Header.Inlinee); - - ListScope BinaryAnnotations(W, "BinaryAnnotations"); - for (auto &Annotation : InlineSite.annotations()) { - switch (Annotation.OpCode) { - case BinaryAnnotationsOpCode::Invalid: - return error(object_error::parse_failed); - 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: - printFileNameForOffset("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; - } - } - } - break; - } - - case S_INLINESITE_END: { - DictScope S(W, "InlineSiteEnd"); - break; - } - - case S_CALLERS: - case S_CALLEES: { - ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers"); - uint32_t Count; - error(consume(SymData, Count)); - for (uint32_t I = 0; I < Count; ++I) { - const TypeIndex *FuncID; - error(consumeObject(SymData, FuncID)); - printTypeIndex("FuncID", *FuncID); - } - break; - } + ArrayRef BinaryData(Subsection.bytes_begin(), + Subsection.bytes_end()); + auto CODD = llvm::make_unique(*this, Section, Obj, + SectionContents); - case S_LOCAL: { - DictScope S(W, "Local"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto LocalOrError = LocalSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!LocalOrError) - error(LocalOrError.getError()); - auto &Local = LocalOrError.get(); - - printTypeIndex("Type", Local.Header.Type); - W.printFlags("Flags", uint16_t(Local.Header.Flags), - makeArrayRef(LocalFlags)); - W.printString("VarName", Local.Name); - break; - } + CVSymbolDumper CVSD(W, CVTD, std::move(CODD), opts::CodeViewSubsectionBytes); - case S_DEFRANGE: { - DictScope S(W, "DefRange"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto DefRangeOrError = DefRangeSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!DefRangeOrError) - error(DefRangeOrError.getError()); - auto &DefRange = DefRangeOrError.get(); - - W.printString( - "Program", - CVStringTable.drop_front(DefRange.Header.Program).split('\0').first); - printLocalVariableAddrRange(DefRange.Header.Range, Sec, - DefRange.getRelocationOffset()); - printLocalVariableAddrGap(DefRange.Gaps); - break; - } - case S_DEFRANGE_SUBFIELD: { - DictScope S(W, "DefRangeSubfield"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto DefRangeOrError = DefRangeSubfieldSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!DefRangeOrError) - error(DefRangeOrError.getError()); - auto &DefRangeSubfield = DefRangeOrError.get(); - - W.printString("Program", - CVStringTable.drop_front(DefRangeSubfield.Header.Program) - .split('\0') - .first); - W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent); - printLocalVariableAddrRange(DefRangeSubfield.Header.Range, Sec, - DefRangeSubfield.getRelocationOffset()); - printLocalVariableAddrGap(DefRangeSubfield.Gaps); - break; - } - case S_DEFRANGE_REGISTER: { - DictScope S(W, "DefRangeRegister"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto DefRangeOrError = DefRangeRegisterSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!DefRangeOrError) - error(DefRangeOrError.getError()); - auto &DefRangeRegisterSym = DefRangeOrError.get(); - - W.printNumber("Register", DefRangeRegisterSym.Header.Register); - W.printNumber("MayHaveNoName", DefRangeRegisterSym.Header.MayHaveNoName); - printLocalVariableAddrRange(DefRangeRegisterSym.Header.Range, Sec, - DefRangeRegisterSym.getRelocationOffset()); - printLocalVariableAddrGap(DefRangeRegisterSym.Gaps); - break; - } - case S_DEFRANGE_SUBFIELD_REGISTER: { - DictScope S(W, "DefRangeSubfieldRegister"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto DefRangeOrError = DefRangeSubfieldRegisterSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!DefRangeOrError) - error(DefRangeOrError.getError()); - auto &DefRangeSubfieldRegister = DefRangeOrError.get(); - W.printNumber("Register", DefRangeSubfieldRegister.Header.Register); - W.printNumber("MayHaveNoName", - DefRangeSubfieldRegister.Header.MayHaveNoName); - W.printNumber("OffsetInParent", - DefRangeSubfieldRegister.Header.OffsetInParent); - printLocalVariableAddrRange( - DefRangeSubfieldRegister.Header.Range, Sec, - DefRangeSubfieldRegister.getRelocationOffset()); - printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); - break; - } - case S_DEFRANGE_FRAMEPOINTER_REL: { - DictScope S(W, "DefRangeFramePointerRel"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto DefRangeOrError = DefRangeFramePointerRelSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!DefRangeOrError) - error(DefRangeOrError.getError()); - auto &DefRangeFramePointerRel = DefRangeOrError.get(); - W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset); - printLocalVariableAddrRange( - DefRangeFramePointerRel.Header.Range, Sec, - DefRangeFramePointerRel.getRelocationOffset()); - printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); - break; - } - case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: { - DictScope S(W, "DefRangeFramePointerRelFullScope"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto DefRangeOrError = DefRangeFramePointerRelFullScopeSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!DefRangeOrError) - error(DefRangeOrError.getError()); - auto &DefRangeFramePointerRelFullScope = DefRangeOrError.get(); - W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset); - break; - } - case S_DEFRANGE_REGISTER_REL: { - DictScope S(W, "DefRangeRegisterRel"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto DefRangeOrError = DefRangeRegisterRelSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!DefRangeOrError) - error(DefRangeOrError.getError()); - auto &DefRangeRegisterRel = DefRangeOrError.get(); - - 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, Sec, - DefRangeRegisterRel.getRelocationOffset()); - printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); - break; - } - - case S_CALLSITEINFO: { - DictScope S(W, "CallSiteInfo"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto CallSiteOrError = CallSiteInfoSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!CallSiteOrError) - error(CallSiteOrError.getError()); - auto &CallSiteInfo = CallSiteOrError.get(); - - StringRef LinkageName; - printRelocatedField("CodeOffset", Sec, CallSiteInfo.getRelocationOffset(), - CallSiteInfo.Header.CodeOffset, &LinkageName); - W.printHex("Segment", CallSiteInfo.Header.Segment); - W.printHex("Reserved", CallSiteInfo.Header.Reserved); - printTypeIndex("Type", CallSiteInfo.Header.Type); - W.printString("LinkageName", LinkageName); - break; - } - - case S_HEAPALLOCSITE: { - DictScope S(W, "HeapAllocationSite"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto HeapAllocSiteOrError = HeapAllocationSiteSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!HeapAllocSiteOrError) - error(HeapAllocSiteOrError.getError()); - auto &HeapAllocSite = HeapAllocSiteOrError.get(); - - StringRef LinkageName; - printRelocatedField("CodeOffset", Sec, - HeapAllocSite.getRelocationOffset(), - HeapAllocSite.Header.CodeOffset, &LinkageName); - W.printHex("Segment", HeapAllocSite.Header.Segment); - W.printHex("CallInstructionSize", - HeapAllocSite.Header.CallInstructionSize); - printTypeIndex("Type", HeapAllocSite.Header.Type); - W.printString("LinkageName", LinkageName); - break; - } - - case S_FRAMECOOKIE: { - DictScope S(W, "FrameCookie"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto FrameCookieOrError = FrameCookieSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!FrameCookieOrError) - error(FrameCookieOrError.getError()); - auto &FrameCookie = FrameCookieOrError.get(); - - StringRef LinkageName; - printRelocatedField("CodeOffset", Sec, FrameCookie.getRelocationOffset(), - FrameCookie.Header.CodeOffset, &LinkageName); - W.printHex("Register", FrameCookie.Header.Register); - W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind), - makeArrayRef(FrameCookieKinds)); - break; - } - - case S_LDATA32: - case S_GDATA32: - case S_LMANDATA: - case S_GMANDATA: { - DictScope S(W, "DataSym"); - ArrayRef SymBytes(SymData.bytes_begin(), SymData.bytes_end()); - auto DataOrError = DataSym::deserialize( - static_cast(Kind), RecordOffset, SymBytes); - if (!DataOrError) - error(DataOrError.getError()); - auto &Data = DataOrError.get(); - - StringRef LinkageName; - printRelocatedField("DataOffset", Sec, Data.getRelocationOffset(), - Data.Header.DataOffset, &LinkageName); - printTypeIndex("Type", Data.Header.Type); - W.printString("DisplayName", Data.Name); - W.printString("LinkageName", LinkageName); - break; - } - - case S_LTHREAD32: - case S_GTHREAD32: { - DictScope S(W, "ThreadLocalDataSym"); - ArrayRef SymBytes(SymData.bytes_begin(), SymData.bytes_end()); - auto ThreadLocalDataOrError = ThreadLocalDataSym::deserialize( - static_cast(Kind), RecordOffset, SymBytes); - if (!ThreadLocalDataOrError) - error(ThreadLocalDataOrError.getError()); - auto &Data = ThreadLocalDataOrError.get(); - - StringRef LinkageName; - printRelocatedField("DataOffset", Sec, Data.getRelocationOffset(), - Data.Header.DataOffset, &LinkageName); - printTypeIndex("Type", Data.Header.Type); - W.printString("DisplayName", Data.Name); - W.printString("LinkageName", LinkageName); - break; - } - - case S_OBJNAME: { - DictScope S(W, "ObjectName"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto ObjNameOrError = ObjNameSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!ObjNameOrError) - error(ObjNameOrError.getError()); - auto &ObjName = ObjNameOrError.get(); - W.printHex("Signature", ObjName.Header.Signature); - W.printString("ObjectName", ObjName.Name); - break; - } - - case S_COMPILE3: { - DictScope S(W, "CompilerFlags"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto Compile3OrError = CompileSym3::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!Compile3OrError) - error(Compile3OrError.getError()); - auto &Compile3 = Compile3OrError.get(); - - W.printEnum("Language", Compile3.Header.getLanguage(), - makeArrayRef(SourceLanguages)); - W.printFlags("Flags", Compile3.Header.flags & ~0xff, - makeArrayRef(CompileSym3FlagNames)); - W.printEnum("Machine", unsigned(Compile3.Header.Machine), - makeArrayRef(CPUTypeNames)); - 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); - break; - } - - case S_FRAMEPROC: { - DictScope S(W, "FrameProc"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto FrameProcOrError = FrameProcSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!FrameProcOrError) - error(FrameProcOrError.getError()); - auto &FrameProc = FrameProcOrError.get(); - 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, - makeArrayRef(FrameProcSymFlags)); - break; - } - - case S_UDT: - case S_COBOLUDT: { - DictScope S(W, "UDT"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto UdtOrError = UDTSym::deserialize(static_cast(Kind), - RecordOffset, Data); - if (!UdtOrError) - error(UdtOrError.getError()); - auto &UDT = UdtOrError.get(); - printTypeIndex("Type", UDT.Header.Type); - W.printString("UDTName", UDT.Name); - break; - } - - case S_BPREL32: { - DictScope S(W, "BPRelativeSym"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto BPRelOrError = BPRelativeSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!BPRelOrError) - error(BPRelOrError.getError()); - auto &BPRel = BPRelOrError.get(); - W.printNumber("Offset", BPRel.Header.Offset); - printTypeIndex("Type", BPRel.Header.Type); - W.printString("VarName", BPRel.Name); - break; - } - - case S_REGREL32: { - DictScope S(W, "RegRelativeSym"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto RegRelOrError = RegRelativeSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!RegRelOrError) - error(RegRelOrError.getError()); - auto &RegRel = RegRelOrError.get(); - W.printHex("Offset", RegRel.Header.Offset); - printTypeIndex("Type", RegRel.Header.Type); - W.printHex("Register", RegRel.Header.Register); - W.printString("VarName", RegRel.Name); - break; - } - - case S_BUILDINFO: { - DictScope S(W, "BuildInfo"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto BuildInfoOrError = BuildInfoSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!BuildInfoOrError) - error(BuildInfoOrError.getError()); - auto &BuildInfo = BuildInfoOrError.get(); - W.printNumber("BuildId", BuildInfo.Header.BuildId); - break; - } - - case S_CONSTANT: - case S_MANCONSTANT: { - DictScope S(W, "Constant"); - ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); - auto ConstantOrError = ConstantSym::deserialize( - static_cast(Kind), RecordOffset, Data); - if (!ConstantOrError) - error(ConstantOrError.getError()); - auto &Constant = ConstantOrError.get(); - printTypeIndex("Type", Constant.Header.Type); - W.printNumber("Value", Constant.Value); - W.printString("Name", Constant.Name); - break; - } - - default: { - DictScope S(W, "UnknownSym"); - W.printHex("Kind", unsigned(Kind)); - W.printHex("Size", Rec->RecordLen); - break; - } - } - - if (opts::CodeViewSubsectionBytes) - printBinaryBlockWithRelocs("SymData", Section, SectionContents, - OrigSymData); + if (!CVSD.dump(BinaryData)) { W.flush(); + error(object_error::parse_failed); } W.flush(); } @@ -1633,24 +970,6 @@ } } -void COFFDumper::printLocalVariableAddrRange( - const LocalVariableAddrRange &Range, const coff_section *Sec, - uint32_t RelocationOffset) { - DictScope S(W, "LocalVariableAddrRange"); - printRelocatedField("OffsetStart", Sec, RelocationOffset, Range.OffsetStart); - W.printHex("ISectStart", Range.ISectStart); - W.printHex("Range", Range.Range); -} - -void COFFDumper::printLocalVariableAddrGap( - ArrayRef Gaps) { - for (auto &Gap : Gaps) { - ListScope S(W, "LocalVariableAddrGap"); - W.printHex("GapStartOffset", Gap.GapStartOffset); - W.printHex("Range", Gap.Range); - } -} - StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) { // The file checksum subsection should precede all references to it. if (!CVFileChecksumTable.data() || !CVStringTable.data())