diff --git a/tools/llvm-readobj/CVLeafTypes.def b/include/llvm/DebugInfo/CodeView/CVLeafTypes.def similarity index 100% rename from tools/llvm-readobj/CVLeafTypes.def rename to include/llvm/DebugInfo/CodeView/CVLeafTypes.def diff --git a/tools/llvm-readobj/CVSymbolTypes.def b/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def similarity index 100% rename from tools/llvm-readobj/CVSymbolTypes.def rename to include/llvm/DebugInfo/CodeView/CVSymbolTypes.def diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h index f97465acbf7..620bfbc288b 100644 --- a/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/include/llvm/DebugInfo/CodeView/CodeView.h @@ -381,6 +381,13 @@ enum class PointerToMemberRepresentation : uint16_t { GeneralFunction = 0x08 // member function, most general }; +/// Distinguishes individual records in .debug$T section or PDB type stream. The +/// documentation and headers talk about this as the "leaf" type. +enum TypeLeafKind : uint16_t { +#define LEAF_TYPE(name, val) name = val, +#include "CVLeafTypes.def" +}; + enum class TypeRecordKind : uint16_t { None = 0, diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index a3d9d7d0408..bbd851ecfb5 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -668,15 +668,6 @@ namespace COFF { enum CodeViewIdentifiers { DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS = 0x1, DEBUG_SECTION_MAGIC = 0x4, - DEBUG_SYMBOL_SUBSECTION = 0xF1, - DEBUG_LINE_TABLE_SUBSECTION = 0xF2, - DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4, - - // Symbol subsections are split into records of different types. - DEBUG_SYMBOL_TYPE_LOCAL_PROC_START = 0x1146, - DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, - DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; inline bool isReservedSectionNumber(int32_t SectionNumber) { diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp index a0292027d0d..7a5c4f3136a 100644 --- a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp +++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp @@ -12,10 +12,14 @@ //===----------------------------------------------------------------------===// #include "WinCodeViewLineTables.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/COFF.h" +using namespace llvm::codeview; + namespace llvm { StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) { @@ -129,6 +133,9 @@ void WinCodeViewLineTables::endModule() { if (FnDebugInfo.empty()) return; + // FIXME: For functions that are comdat, we should emit separate .debug$S + // sections that are comdat associative with the main function instead of + // having one big .debug$S section. assert(Asm != nullptr); Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getCOFFDebugSymbolsSection()); @@ -146,7 +153,7 @@ void WinCodeViewLineTables::endModule() { // This subsection holds a file index to offset in string table table. Asm->OutStreamer->AddComment("File index to string table offset subsection"); - Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION); + Asm->EmitInt32(unsigned(ModuleSubstreamKind::FileChecksums)); size_t NumFilenames = FileNameRegistry.Infos.size(); Asm->EmitInt32(8 * NumFilenames); for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { @@ -159,7 +166,7 @@ void WinCodeViewLineTables::endModule() { // This subsection holds the string table. Asm->OutStreamer->AddComment("String table"); - Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION); + Asm->EmitInt32(unsigned(ModuleSubstreamKind::StringTable)); Asm->EmitInt32(FileNameRegistry.LastOffset); // The payload starts with a null character. Asm->EmitInt8(0); @@ -213,7 +220,7 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { MCSymbol *SymbolsBegin = Asm->MMI->getContext().createTempSymbol(), *SymbolsEnd = Asm->MMI->getContext().createTempSymbol(); Asm->OutStreamer->AddComment("Symbol subsection for " + Twine(FuncName)); - Asm->EmitInt32(COFF::DEBUG_SYMBOL_SUBSECTION); + Asm->EmitInt32(unsigned(ModuleSubstreamKind::Symbols)); EmitLabelDiff(*Asm->OutStreamer, SymbolsBegin, SymbolsEnd); Asm->OutStreamer->EmitLabel(SymbolsBegin); { @@ -222,7 +229,8 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { EmitLabelDiff(*Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2); Asm->OutStreamer->EmitLabel(ProcSegmentBegin); - Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_START); + Asm->EmitInt16(unsigned(SymbolRecordKind::S_GPROC32_ID)); + // Some bytes of this segment don't seem to be required for basic debugging, // so just fill them with zeroes. Asm->OutStreamer->EmitFill(12, 0); @@ -240,7 +248,7 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { // We're done with this function. Asm->EmitInt16(0x0002); - Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_END); + Asm->EmitInt16(unsigned(SymbolRecordKind::S_PROC_ID_END)); } Asm->OutStreamer->EmitLabel(SymbolsEnd); // Every subsection must be aligned to a 4-byte boundary. @@ -264,7 +272,7 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { // Emit a line table subsection, required to do PC-to-file:line lookup. Asm->OutStreamer->AddComment("Line table subsection for " + Twine(FuncName)); - Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION); + Asm->EmitInt32(unsigned(ModuleSubstreamKind::Lines)); MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(), *LineTableEnd = Asm->MMI->getContext().createTempSymbol(); EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd); diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index 13e03bf78dd..94dc9042338 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -24,6 +24,10 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/COFF.h" @@ -42,6 +46,7 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::codeview; +using namespace llvm::support; using namespace llvm::Win64EH; namespace { @@ -608,9 +613,9 @@ static const EnumEntry SimpleTypeNames[] = { {"__bool64*", SimpleTypeKind::Boolean64}, }; -static const EnumEntry LeafTypeNames[] = { -#define LEAF_TYPE(name, val) LLVM_READOBJ_ENUM_ENT(LeafType, name), -#include "CVLeafTypes.def" +static const EnumEntry LeafTypeNames[] = { +#define LEAF_TYPE(name, val) LLVM_READOBJ_ENUM_ENT(TypeLeafKind, name), +#include "llvm/DebugInfo/CodeView/CVLeafTypes.def" }; static const EnumEntry PtrKindNames[] = { @@ -1205,8 +1210,8 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, Data = Data.drop_front(Rec->RecordLength - 2); - SymType Type = static_cast(uint16_t(Rec->RecordType)); - switch (Type) { + SymbolRecordKind Kind = Rec->getKind(); + switch (Kind) { case S_LPROC32: case S_GPROC32: case S_GPROC32_ID: @@ -1555,7 +1560,7 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, default: { DictScope S(W, "UnknownSym"); - W.printHex("Type", unsigned(Type)); + W.printHex("Kind", unsigned(Kind)); W.printHex("Size", Rec->RecordLength); W.printBinaryBlock("SymData", SymData); break; @@ -1564,7 +1569,7 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, } } -StringRef getRemainingTypeBytes(const TypeRecord *Rec, const char *Start) { +StringRef getRemainingTypeBytes(const TypeRecordPrefix *Rec, const char *Start) { ptrdiff_t StartOffset = Start - reinterpret_cast(Rec); size_t RecSize = Rec->Len + 2; assert(StartOffset >= 0 && "negative start-offset!"); @@ -1573,7 +1578,7 @@ StringRef getRemainingTypeBytes(const TypeRecord *Rec, const char *Start) { return StringRef(Start, RecSize - StartOffset); } -StringRef getRemainingBytesAsString(const TypeRecord *Rec, const char *Start) { +StringRef getRemainingBytesAsString(const TypeRecordPrefix *Rec, const char *Start) { StringRef Remaining = getRemainingTypeBytes(Rec, Start); StringRef Leading, Trailing; std::tie(Leading, Trailing) = Remaining.split('\0'); @@ -1617,7 +1622,7 @@ void COFFDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) { W.printHex(FieldName, TI.getIndex()); } -static StringRef getLeafTypeName(LeafType LT) { +static StringRef getLeafTypeName(TypeLeafKind LT) { switch (LT) { case LF_STRING_ID: return "StringId"; case LF_FIELDLIST: return "FieldList"; @@ -1660,9 +1665,9 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName, Data = Data.drop_front(4); while (!Data.empty()) { - const TypeRecord *Rec; + const TypeRecordPrefix *Rec; error(consumeObject(Data, Rec)); - auto Leaf = static_cast(uint16_t(Rec->Leaf)); + auto Leaf = static_cast(uint16_t(Rec->Leaf)); // This record is 'Len - 2' bytes, and the next one starts immediately // afterwards. @@ -1673,7 +1678,7 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName, StringRef LeafName = getLeafTypeName(Leaf); DictScope S(W, LeafName); unsigned NextTypeIndex = 0x1000 + CVUDTNames.size(); - W.printEnum("LeafType", unsigned(Leaf), makeArrayRef(LeafTypeNames)); + W.printEnum("TypeLeafKind", unsigned(Leaf), makeArrayRef(LeafTypeNames)); W.printHex("TypeIndex", NextTypeIndex); // Fill this in inside the switch to get something in CVUDTNames. diff --git a/tools/llvm-readobj/CodeView.h b/tools/llvm-readobj/CodeView.h index 444b2645166..35c91bb4462 100644 --- a/tools/llvm-readobj/CodeView.h +++ b/tools/llvm-readobj/CodeView.h @@ -26,220 +26,9 @@ namespace llvm { namespace codeview { -/// A Symbols subsection is a sequence of SymRecords. Advancing by 'len' -/// bytes will find the next SymRecord. These are the possible types of a -/// record. Equivalent to SYM_ENUM_e in cvinfo.h. -enum SymType : uint16_t { -#define SYMBOL_TYPE(ename, value) ename = value, -#include "CVSymbolTypes.def" -}; - -/// Generic record compatible with all symbol records. -struct SymRecord { - ulittle16_t RecordLength; // Record length, starting from the next field - ulittle16_t RecordType; // Record type (SymType) - // Symbol data follows. -}; - -/// Corresponds to the CV_PROCFLAGS bitfield. -enum ProcFlags : uint8_t { - HasFP = 1 << 0, - HasIRET = 1 << 1, - HasFRET = 1 << 2, - IsNoReturn = 1 << 3, - IsUnreachable = 1 << 4, - HasCustomCallingConv = 1 << 5, - IsNoInline = 1 << 6, - HasOptimizedDebugInfo = 1 << 7, -}; - -// S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or -// S_LPROC32_DPC_ID -struct ProcSym { - ulittle32_t PtrParent; - ulittle32_t PtrEnd; - ulittle32_t PtrNext; - ulittle32_t CodeSize; - ulittle32_t DbgStart; - ulittle32_t DbgEnd; - TypeIndex FunctionType; - ulittle32_t CodeOffset; - ulittle16_t Segment; - uint8_t Flags; // CV_PROCFLAGS - // Name: The null-terminated name follows. -}; - -// S_INLINESITE -struct InlineSiteSym { - ulittle32_t PtrParent; - ulittle32_t PtrEnd; - TypeIndex Inlinee; - // BinaryAnnotations -}; - -// S_LOCAL -struct LocalSym { - TypeIndex Type; - ulittle16_t Flags; - enum : uint16_t { - IsParameter = 1 << 0, - IsAddressTaken = 1 << 1, - IsCompilerGenerated = 1 << 2, - IsAggregate = 1 << 3, - IsAggregated = 1 << 4, - IsAliased = 1 << 5, - IsAlias = 1 << 6, - IsReturnValue = 1 << 7, - IsOptimizedOut = 1 << 8, - IsEnregisteredGlobal = 1 << 9, - IsEnregisteredStatic = 1 << 10, - }; - // Name: The null-terminated name follows. -}; - -// S_BLOCK32 -struct BlockSym { - ulittle32_t PtrParent; - ulittle32_t PtrEnd; - ulittle32_t CodeSize; - ulittle32_t CodeOffset; - ulittle16_t Segment; - // Name: The null-terminated name follows. -}; - -// S_LABEL32 -struct LabelSym { - ulittle32_t CodeOffset; - ulittle16_t Segment; - uint8_t Flags; // CV_PROCFLAGS - // Name: The null-terminated name follows. -}; - -// S_OBJNAME -struct ObjNameSym { - ulittle32_t Signature; - // Name: The null-terminated name follows. -}; - -// S_COMPILE3 -struct CompileSym3 { - ulittle32_t flags; - uint8_t getLanguage() const { return flags & 0xff; } - enum Flags : uint32_t { - EC = 1 << 8, - NoDbgInfo = 1 << 9, - LTCG = 1 << 10, - NoDataAlign = 1 << 11, - ManagedPresent = 1 << 12, - SecurityChecks = 1 << 13, - HotPatch = 1 << 14, - CVTCIL = 1 << 15, - MSILModule = 1 << 16, - Sdl = 1 << 17, - PGO = 1 << 18, - Exp = 1 << 19, - }; - ulittle16_t Machine; // CPUType - ulittle16_t VersionFrontendMajor; - ulittle16_t VersionFrontendMinor; - ulittle16_t VersionFrontendBuild; - ulittle16_t VersionFrontendQFE; - ulittle16_t VersionBackendMajor; - ulittle16_t VersionBackendMinor; - ulittle16_t VersionBackendBuild; - ulittle16_t VersionBackendQFE; - // VersionString: The null-terminated version string follows. -}; - -// S_FRAMEPROC -struct FrameProcSym { - ulittle32_t TotalFrameBytes; - ulittle32_t PaddingFrameBytes; - ulittle32_t OffsetToPadding; - ulittle32_t BytesOfCalleeSavedRegisters; - ulittle32_t OffsetOfExceptionHandler; - ulittle16_t SectionIdOfExceptionHandler; - ulittle32_t Flags; -}; - -// S_CALLSITEINFO -struct CallSiteInfoSym { - ulittle32_t CodeOffset; - ulittle16_t Segment; - ulittle16_t Reserved; - TypeIndex Type; -}; - -// S_HEAPALLOCSITE -struct HeapAllocationSiteSym { - ulittle32_t CodeOffset; - ulittle16_t Segment; - ulittle16_t CallInstructionSize; - TypeIndex Type; -}; - -// S_FRAMECOOKIE -struct FrameCookieSym { - ulittle32_t CodeOffset; - ulittle16_t Register; - ulittle16_t CookieKind; - - enum : uint16_t { - Copy, - XorStackPointer, - XorFramePointer, - XorR13, - }; -}; - -// S_UDT, S_COBOLUDT -struct UDTSym { - TypeIndex Type; // Type of the UDT - // Name: The null-terminated name follows. -}; - -// S_BUILDINFO -struct BuildInfoSym { - ulittle32_t BuildId; -}; - -// S_BPREL32 -struct BPRelativeSym { - ulittle32_t Offset; // Offset from the base pointer register - TypeIndex Type; // Type of the variable - // Name: The null-terminated name follows. -}; - -// S_REGREL32 -struct RegRelativeSym { - ulittle32_t Offset; // Offset from the register - TypeIndex Type; // Type of the variable - ulittle16_t Register; // Register to which the variable is relative - // Name: The null-terminated name follows. -}; - -// S_CONSTANT, S_MANCONSTANT -struct ConstantSym { - TypeIndex Type; - // Value: The value of the constant. - // Name: The null-terminated name follows. -}; - -// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA -struct DataSym { - TypeIndex Type; - ulittle32_t DataOffset; - ulittle16_t Segment; - // Name: The null-terminated name follows. -}; - -// S_LTHREAD32, S_GTHREAD32 -struct ThreadLocalDataSym { - TypeIndex Type; - ulittle32_t DataOffset; - ulittle16_t Segment; - // Name: The null-terminated name follows. -}; +using llvm::support::little32_t; +using llvm::support::ulittle16_t; +using llvm::support::ulittle32_t; /// Data in the the SUBSEC_FRAMEDATA subection. struct FrameData { @@ -262,19 +51,12 @@ struct FrameData { //===----------------------------------------------------------------------===// // On-disk representation of type information -/// Indicates the kind of TypeRecord we're dealing with here. The documentation -/// and headers talk about this as the "leaf" type. -enum LeafType : uint16_t { -#define LEAF_TYPE(name, val) name = val, -#include "CVLeafTypes.def" -}; - // A CodeView type stream is a sequence of TypeRecords. Records larger than // 65536 must chain on to a second record. Each TypeRecord is followed by one of // the leaf types described below. -struct TypeRecord { +struct TypeRecordPrefix { ulittle16_t Len; // Type record length, starting from &Leaf. - ulittle16_t Leaf; // Type record kind (LeafType) + ulittle16_t Leaf; // Type record kind (TypeLeafKind) }; // LF_TYPESERVER2 diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h index 08aa519e8ef..a255fe5fa19 100644 --- a/tools/llvm-readobj/StreamWriter.h +++ b/tools/llvm-readobj/StreamWriter.h @@ -20,7 +20,6 @@ #include using namespace llvm; -using namespace llvm::support; namespace llvm { @@ -293,8 +292,9 @@ private: }; template <> -inline void StreamWriter::printHex(StringRef Label, - ulittle16_t Value) { +inline void +StreamWriter::printHex(StringRef Label, + support::ulittle16_t Value) { startLine() << Label << ": " << hex(Value) << "\n"; }