Index: include/llvm/DebugInfo/CodeView/RecordIterator.h =================================================================== --- include/llvm/DebugInfo/CodeView/RecordIterator.h +++ include/llvm/DebugInfo/CodeView/RecordIterator.h @@ -18,17 +18,22 @@ namespace codeview { // A const input iterator interface to the CodeView record stream. template class RecordIterator { -private: struct RecordPrefix { support::ulittle16_t Len; // Record length, starting from &Leaf support::ulittle16_t Kind; // Record kind (a value from the `Kind` enum). }; public: + static const size_t PrefixSize = sizeof(RecordPrefix); + struct Record { std::size_t Length; Kind Type; ArrayRef Data; + + template const T *getData() const { + return reinterpret_cast(Data.data()); + } }; explicit RecordIterator(const ArrayRef &RecordBytes) Index: include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -29,17 +29,6 @@ #include "CVSymbolTypes.def" }; -/// Data preceding all symbol records. -struct SymRecord { - ulittle16_t RecordLength; // Record length, starting from the next field - ulittle16_t RecordKind; // Record kind (SymbolRecordKind) - // Symbol data follows. - - SymbolRecordKind getKind() const { - return SymbolRecordKind(uint16_t(RecordKind)); - } -}; - /// Corresponds to the CV_PROCFLAGS bitfield. enum ProcFlags : uint8_t { HasFP = 1 << 0, @@ -65,7 +54,7 @@ ulittle32_t CodeOffset; ulittle16_t Segment; uint8_t Flags; // CV_PROCFLAGS - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string }; enum BinaryAnnotationsOpCode : uint32_t { @@ -110,7 +99,7 @@ IsEnregisteredGlobal = 1 << 9, IsEnregisteredStatic = 1 << 10, }; - // Name: The null-terminated name follows. + char Name[1]; // Null terminated string. }; struct LocalVariableAddrRange { @@ -189,7 +178,7 @@ ulittle32_t CodeSize; ulittle32_t CodeOffset; ulittle16_t Segment; - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string. }; // S_LABEL32 @@ -197,13 +186,13 @@ ulittle32_t CodeOffset; ulittle16_t Segment; uint8_t Flags; // CV_PROCFLAGS - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string. }; // S_OBJNAME struct ObjNameSym { ulittle32_t Signature; - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string. }; // S_COMPILE3 @@ -233,7 +222,7 @@ ulittle16_t VersionBackendMinor; ulittle16_t VersionBackendBuild; ulittle16_t VersionBackendQFE; - // VersionString: The null-terminated version string follows. + char Version[1]; // null-terminated string. }; // S_FRAMEPROC @@ -280,7 +269,7 @@ // S_UDT, S_COBOLUDT struct UDTSym { TypeIndex Type; // Type of the UDT - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string. }; // S_BUILDINFO @@ -292,7 +281,7 @@ struct BPRelativeSym { little32_t Offset; // Offset from the base pointer register TypeIndex Type; // Type of the variable - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string. }; // S_REGREL32 @@ -300,7 +289,7 @@ 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. + char Name[1]; // null-terminated string. }; // S_CONSTANT, S_MANCONSTANT @@ -315,7 +304,7 @@ TypeIndex Type; ulittle32_t DataOffset; ulittle16_t Segment; - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string. }; // S_LTHREAD32, S_GTHREAD32 @@ -323,7 +312,7 @@ TypeIndex Type; ulittle32_t DataOffset; ulittle16_t Segment; - // Name: The null-terminated name follows. + char Name[1]; // null-terminated string. }; typedef RecordIterator SymbolIterator; Index: include/llvm/DebugInfo/CodeView/TypeStream.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeStream.h +++ include/llvm/DebugInfo/CodeView/TypeStream.h @@ -26,8 +26,8 @@ /// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if /// there are not enough bytes remaining. Reinterprets the consumed bytes as a /// T object and points 'Res' at them. -template -inline std::error_code consumeObject(StringRef &Data, const T *&Res) { +template +inline std::error_code consumeObject(S &Data, const T *&Res) { if (Data.size() < sizeof(*Res)) return object::object_error::parse_failed; Res = reinterpret_cast(Data.data()); @@ -35,7 +35,8 @@ return std::error_code(); } -inline std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) { +template +inline std::error_code consumeUInt32(S &Data, uint32_t &Res) { const support::ulittle32_t *IntPtr; if (auto EC = consumeObject(Data, IntPtr)) return EC; Index: tools/llvm-readobj/COFFDumper.cpp =================================================================== --- tools/llvm-readobj/COFFDumper.cpp +++ tools/llvm-readobj/COFFDumper.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/RecordIterator.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDumper.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" @@ -94,7 +95,7 @@ void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, const coff_section *Sec, StringRef SectionContents); - void printLocalVariableAddrGap(StringRef &SymData); + void printLocalVariableAddrGap(ArrayRef &SymData); void printCodeViewSymbolsSubsection(StringRef Subsection, const SectionRef &Section, @@ -218,7 +219,9 @@ const SectionRef &Sec, StringRef SectionContents, StringRef Block) { + outs().flush(); W.printBinaryBlock(Label, Block); + outs().flush(); assert(SectionContents.begin() < Block.begin() && SectionContents.end() >= Block.end() && @@ -235,6 +238,7 @@ if (OffsetStart <= RelocationOffset && RelocationOffset < OffsetEnd) printRelocation(Sec, Relocation, OffsetStart); } + outs().flush(); } static const EnumEntry ImageFileMachineType[] = { @@ -989,26 +993,16 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, const SectionRef &Section, StringRef SectionContents) { - if (Subsection.size() < sizeof(SymRecord)) + if (Subsection.size() < sizeof(SymbolIterator::PrefixSize)) 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 SymRecord *Rec; - error(consumeObject(Data, Rec)); + ArrayRef Data((uint8_t *)(Subsection.data()), Subsection.size()); + for (const auto &Record : makeSymbolRange(Data)) { - StringRef SymData = Data.substr(0, Rec->RecordLength - 2); - StringRef OrigSymData = SymData; - - Data = Data.drop_front(Rec->RecordLength - 2); - - SymbolRecordKind Kind = Rec->getKind(); - switch (Kind) { + switch (Record.Type) { case S_LPROC32: case S_GPROC32: case S_GPROC32_ID: @@ -1016,14 +1010,13 @@ case S_LPROC32_DPC: case S_LPROC32_DPC_ID: { DictScope S(W, "ProcStart"); - const ProcSym *Proc; - error(consumeObject(SymData, Proc)); + auto Proc = Record.getData(); if (InFunctionScope) return error(object_error::parse_failed); InFunctionScope = true; StringRef LinkageName; - StringRef DisplayName = SymData.split('\0').first; + StringRef DisplayName = Proc->Name; W.printHex("PtrParent", Proc->PtrParent); W.printHex("PtrEnd", Proc->PtrEnd); W.printHex("PtrNext", Proc->PtrNext); @@ -1048,10 +1041,9 @@ case S_BLOCK32: { DictScope S(W, "BlockStart"); - const BlockSym *Block; - error(consumeObject(SymData, Block)); + const BlockSym *Block = Record.getData(); - StringRef BlockName = SymData.split('\0').first; + StringRef BlockName = Block->Name; StringRef LinkageName; W.printHex("PtrParent", Block->PtrParent); W.printHex("PtrEnd", Block->PtrEnd); @@ -1072,10 +1064,9 @@ case S_LABEL32: { DictScope S(W, "Label"); - const LabelSym *Label; - error(consumeObject(SymData, Label)); + const LabelSym *Label = Record.getData(); - StringRef DisplayName = SymData.split('\0').first; + StringRef DisplayName = Label->Name; StringRef LinkageName; printRelocatedField("CodeOffset", Sec, SectionContents, &Label->CodeOffset, &LinkageName); @@ -1089,12 +1080,12 @@ case S_INLINESITE: { DictScope S(W, "InlineSite"); - const InlineSiteSym *InlineSite; - error(consumeObject(SymData, InlineSite)); + const InlineSiteSym *InlineSite = Record.getData(); W.printHex("PtrParent", InlineSite->PtrParent); W.printHex("PtrEnd", InlineSite->PtrEnd); printTypeIndex("Inlinee", InlineSite->Inlinee); + auto SymData = Record.Data.slice(sizeof(InlineSiteSym)); auto GetCompressedAnnotation = [&]() -> uint32_t { if (SymData.empty()) return -1; @@ -1209,8 +1200,9 @@ case S_CALLERS: case S_CALLEES: { - ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers"); + ListScope S(W, Record.Type == S_CALLEES ? "Callees" : "Callers"); uint32_t Count; + auto SymData = Record.Data; error(consumeUInt32(SymData, Count)); for (uint32_t I = 0; I < Count; ++I) { const TypeIndex *FuncID; @@ -1222,30 +1214,29 @@ case S_LOCAL: { DictScope S(W, "Local"); - const LocalSym *Local; - error(consumeObject(SymData, Local)); + const LocalSym *Local = Record.getData(); printTypeIndex("Type", Local->Type); W.printFlags("Flags", uint16_t(Local->Flags), makeArrayRef(LocalFlags)); - StringRef VarName = SymData.split('\0').first; + StringRef VarName = Local->Name; W.printString("VarName", VarName); break; } case S_DEFRANGE: { DictScope S(W, "DefRange"); - const DefRangeSym *DefRange; - error(consumeObject(SymData, DefRange)); + const DefRangeSym *DefRange = Record.getData(); W.printString( "Program", CVStringTable.drop_front(DefRange->Program).split('\0').first); printLocalVariableAddrRange(DefRange->Range, Sec, SectionContents); - printLocalVariableAddrGap(SymData); + auto Data = Record.Data.slice(sizeof(DefRangeSym)); + printLocalVariableAddrGap(Data); break; } case S_DEFRANGE_SUBFIELD: { DictScope S(W, "DefRangeSubfield"); - const DefRangeSubfieldSym *DefRangeSubfield; - error(consumeObject(SymData, DefRangeSubfield)); + const DefRangeSubfieldSym *DefRangeSubfield = + Record.getData(); W.printString("Program", CVStringTable.drop_front(DefRangeSubfield->Program) .split('\0') @@ -1253,56 +1244,58 @@ W.printNumber("OffsetInParent", DefRangeSubfield->OffsetInParent); printLocalVariableAddrRange(DefRangeSubfield->Range, Sec, SectionContents); - printLocalVariableAddrGap(SymData); + auto Data = Record.Data.slice(sizeof(DefRangeSubfieldSym)); + printLocalVariableAddrGap(Data); break; } case S_DEFRANGE_REGISTER: { DictScope S(W, "DefRangeRegister"); - const DefRangeRegisterSym *DefRangeRegister; - error(consumeObject(SymData, DefRangeRegister)); + const DefRangeRegisterSym *DefRangeRegister = + Record.getData(); W.printNumber("Register", DefRangeRegister->Register); W.printNumber("MayHaveNoName", DefRangeRegister->MayHaveNoName); printLocalVariableAddrRange(DefRangeRegister->Range, Sec, SectionContents); - printLocalVariableAddrGap(SymData); + auto Data = Record.Data.slice(sizeof(DefRangeRegisterSym)); + printLocalVariableAddrGap(Data); break; } case S_DEFRANGE_SUBFIELD_REGISTER: { DictScope S(W, "DefRangeSubfieldRegister"); - const DefRangeSubfieldRegisterSym *DefRangeSubfieldRegisterSym; - error(consumeObject(SymData, DefRangeSubfieldRegisterSym)); - W.printNumber("Register", DefRangeSubfieldRegisterSym->Register); - W.printNumber("MayHaveNoName", - DefRangeSubfieldRegisterSym->MayHaveNoName); - W.printNumber("OffsetInParent", - DefRangeSubfieldRegisterSym->OffsetInParent); - printLocalVariableAddrRange(DefRangeSubfieldRegisterSym->Range, Sec, + const DefRangeSubfieldRegisterSym *DefRangeSubfieldRegister = + Record.getData(); + W.printNumber("Register", DefRangeSubfieldRegister->Register); + W.printNumber("MayHaveNoName", DefRangeSubfieldRegister->MayHaveNoName); + W.printNumber("OffsetInParent", DefRangeSubfieldRegister->OffsetInParent); + printLocalVariableAddrRange(DefRangeSubfieldRegister->Range, Sec, SectionContents); - printLocalVariableAddrGap(SymData); + auto Data = Record.Data.slice(sizeof(DefRangeSubfieldRegisterSym)); + printLocalVariableAddrGap(Data); break; } case S_DEFRANGE_FRAMEPOINTER_REL: { DictScope S(W, "DefRangeFramePointerRel"); - const DefRangeFramePointerRelSym *DefRangeFramePointerRel; - error(consumeObject(SymData, DefRangeFramePointerRel)); + const DefRangeFramePointerRelSym *DefRangeFramePointerRel = + Record.getData(); W.printNumber("Offset", DefRangeFramePointerRel->Offset); printLocalVariableAddrRange(DefRangeFramePointerRel->Range, Sec, SectionContents); - printLocalVariableAddrGap(SymData); + auto Data = Record.Data.slice(sizeof(DefRangeFramePointerRelSym)); + printLocalVariableAddrGap(Data); break; } case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: { DictScope S(W, "DefRangeFramePointerRelFullScope"); const DefRangeFramePointerRelFullScopeSym - *DefRangeFramePointerRelFullScope; - error(consumeObject(SymData, DefRangeFramePointerRelFullScope)); + *DefRangeFramePointerRelFullScope = + Record.getData(); W.printNumber("Offset", DefRangeFramePointerRelFullScope->Offset); break; } case S_DEFRANGE_REGISTER_REL: { DictScope S(W, "DefRangeRegisterRel"); - const DefRangeRegisterRelSym *DefRangeRegisterRel; - error(consumeObject(SymData, DefRangeRegisterRel)); + const DefRangeRegisterRelSym *DefRangeRegisterRel = + Record.getData(); W.printNumber("BaseRegister", DefRangeRegisterRel->BaseRegister); W.printBoolean("HasSpilledUDTMember", DefRangeRegisterRel->hasSpilledUDTMember()); @@ -1311,14 +1304,14 @@ DefRangeRegisterRel->BasePointerOffset); printLocalVariableAddrRange(DefRangeRegisterRel->Range, Sec, SectionContents); - printLocalVariableAddrGap(SymData); + auto Data = Record.Data.slice(sizeof(DefRangeRegisterRelSym)); + printLocalVariableAddrGap(Data); break; } case S_CALLSITEINFO: { DictScope S(W, "CallSiteInfo"); - const CallSiteInfoSym *CallSiteInfo; - error(consumeObject(SymData, CallSiteInfo)); + const CallSiteInfoSym *CallSiteInfo = Record.getData(); StringRef LinkageName; printRelocatedField("CodeOffset", Sec, SectionContents, @@ -1332,8 +1325,8 @@ case S_HEAPALLOCSITE: { DictScope S(W, "HeapAllocationSite"); - const HeapAllocationSiteSym *HeapAllocationSite; - error(consumeObject(SymData, HeapAllocationSite)); + const HeapAllocationSiteSym *HeapAllocationSite = + Record.getData(); StringRef LinkageName; printRelocatedField("CodeOffset", Sec, SectionContents, @@ -1348,8 +1341,7 @@ case S_FRAMECOOKIE: { DictScope S(W, "FrameCookie"); - const FrameCookieSym *FrameCookie; - error(consumeObject(SymData, FrameCookie)); + const FrameCookieSym *FrameCookie = Record.getData(); StringRef LinkageName; printRelocatedField("CodeOffset", Sec, SectionContents, @@ -1365,10 +1357,9 @@ case S_LMANDATA: case S_GMANDATA: { DictScope S(W, "DataSym"); - const DataSym *Data; - error(consumeObject(SymData, Data)); + const DataSym *Data = Record.getData(); - StringRef DisplayName = SymData.split('\0').first; + StringRef DisplayName = Data->Name; StringRef LinkageName; printRelocatedField("DataOffset", Sec, SectionContents, &Data->DataOffset, &LinkageName); @@ -1381,10 +1372,9 @@ case S_LTHREAD32: case S_GTHREAD32: { DictScope S(W, "ThreadLocalDataSym"); - const ThreadLocalDataSym *Data; - error(consumeObject(SymData, Data)); + const ThreadLocalDataSym *Data = Record.getData(); - StringRef DisplayName = SymData.split('\0').first; + StringRef DisplayName = Data->Name; StringRef LinkageName; printRelocatedField("DataOffset", Sec, SectionContents, &Data->DataOffset, &LinkageName); @@ -1396,18 +1386,16 @@ case S_OBJNAME: { DictScope S(W, "ObjectName"); - const ObjNameSym *ObjName; - error(consumeObject(SymData, ObjName)); + const ObjNameSym *ObjName = Record.getData(); W.printHex("Signature", ObjName->Signature); - StringRef ObjectName = SymData.split('\0').first; + StringRef ObjectName = ObjName->Name; W.printString("ObjectName", ObjectName); break; } case S_COMPILE3: { DictScope S(W, "CompilerFlags"); - const CompileSym3 *CompFlags; - error(consumeObject(SymData, CompFlags)); + const CompileSym3 *CompFlags = Record.getData(); W.printEnum("Language", CompFlags->getLanguage(), makeArrayRef(SourceLanguages)); W.printFlags("Flags", CompFlags->flags & ~0xff, @@ -1432,15 +1420,15 @@ } W.printString("FrontendVersion", FrontendVersion); W.printString("BackendVersion", BackendVersion); - StringRef VersionName = SymData.split('\0').first; + StringRef VersionName = CompFlags->Version; W.printString("VersionName", VersionName); break; } case S_FRAMEPROC: { DictScope S(W, "FrameProc"); - const FrameProcSym *FrameProc; - error(consumeObject(SymData, FrameProc)); + const FrameProcSym *FrameProc = Record.getData(); + W.printHex("TotalFrameBytes", FrameProc->TotalFrameBytes); W.printHex("PaddingFrameBytes", FrameProc->PaddingFrameBytes); W.printHex("OffsetToPadding", FrameProc->OffsetToPadding); @@ -1454,41 +1442,41 @@ case S_UDT: case S_COBOLUDT: { DictScope S(W, "UDT"); - const UDTSym *UDT; - error(consumeObject(SymData, UDT)); + const UDTSym *UDT = Record.getData(); + printTypeIndex("Type", UDT->Type); - StringRef UDTName = SymData.split('\0').first; + StringRef UDTName = UDT->Name; W.printString("UDTName", UDTName); break; } case S_BPREL32: { DictScope S(W, "BPRelativeSym"); - const BPRelativeSym *BPRel; - error(consumeObject(SymData, BPRel)); + const BPRelativeSym *BPRel = Record.getData(); + W.printNumber("Offset", BPRel->Offset); printTypeIndex("Type", BPRel->Type); - StringRef VarName = SymData.split('\0').first; + StringRef VarName = BPRel->Name; W.printString("VarName", VarName); break; } case S_REGREL32: { DictScope S(W, "RegRelativeSym"); - const RegRelativeSym *RegRel; - error(consumeObject(SymData, RegRel)); + const RegRelativeSym *RegRel = Record.getData(); + W.printHex("Offset", RegRel->Offset); printTypeIndex("Type", RegRel->Type); W.printHex("Register", RegRel->Register); - StringRef VarName = SymData.split('\0').first; + StringRef VarName = RegRel->Name; W.printString("VarName", VarName); break; } case S_BUILDINFO: { DictScope S(W, "BuildInfo"); - const BuildInfoSym *BuildInfo; - error(consumeObject(SymData, BuildInfo)); + const BuildInfoSym *BuildInfo = Record.getData(); + W.printNumber("BuildId", BuildInfo->BuildId); break; } @@ -1496,29 +1484,33 @@ case S_CONSTANT: case S_MANCONSTANT: { DictScope S(W, "Constant"); - const ConstantSym *Constant; - error(consumeObject(SymData, Constant)); + const ConstantSym *Constant = Record.getData(); + + ArrayRef SymData = Record.Data.slice(sizeof(ConstantSym)); + printTypeIndex("Type", Constant->Type); APSInt Value; if (!decodeNumericLeaf(SymData, Value)) error(object_error::parse_failed); W.printNumber("Value", Value); - StringRef Name = SymData.split('\0').first; + StringRef Name((const char *)SymData.begin(), SymData.size()); + Name = Name.split('\0').first; W.printString("Name", Name); break; } default: { DictScope S(W, "UnknownSym"); - W.printHex("Kind", unsigned(Kind)); - W.printHex("Size", Rec->RecordLength); + W.printHex("Kind", unsigned(Record.Type)); + W.printHex("Size", Record.Length); break; } } if (opts::CodeViewSubsectionBytes) - printBinaryBlockWithRelocs("SymData", Section, SectionContents, - OrigSymData); + printBinaryBlockWithRelocs( + "SymData", Section, SectionContents, + StringRef((const char *)Record.Data.data(), Record.Data.size())); W.flush(); } W.flush(); @@ -1585,7 +1577,7 @@ W.printHex("Range", Range.Range); } -void COFFDumper::printLocalVariableAddrGap(StringRef &SymData) { +void COFFDumper::printLocalVariableAddrGap(ArrayRef &SymData) { while (!SymData.empty()) { const LocalVariableAddrGap *Gap; error(consumeObject(SymData, Gap));