Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -26,6 +26,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" +#include "llvm/DebugInfo/DWARF/DWARFObj.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" @@ -45,10 +46,14 @@ class MemoryBuffer; class raw_ostream; +/// Used as a return value for a error callback passed to DWARF context. +/// Callback should return Halt if client application wants to stop +/// object parsing, or should return Continue otherwise. +enum class ErrorPolicy { Halt, Continue }; + /// DWARFContext /// This data structure is the top level entity that deals with dwarf debug -/// information parsing. The actual data is supplied through pure virtual -/// methods that a concrete implementation provides. +/// information parsing. The actual data is supplied through DWARFObj. class DWARFContext : public DIContext { DWARFUnitSection CUs; std::deque> TUs; @@ -95,11 +100,17 @@ /// and store them in DWOTUs. void parseDWOTypeUnits(); +protected: + std::unique_ptr DObj; + public: - DWARFContext() : DIContext(CK_DWARF) {} + DWARFContext(std::unique_ptr DObj) + : DIContext(CK_DWARF), DObj(std::move(DObj)) {} DWARFContext(DWARFContext &) = delete; DWARFContext &operator=(DWARFContext &) = delete; + const DWARFObj &getDWARFObj() const { return *DObj; } + static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_DWARF; } @@ -222,55 +233,24 @@ DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - virtual StringRef getFileName() const = 0; - virtual bool isLittleEndian() const = 0; - virtual uint8_t getAddressSize() const = 0; - virtual const DWARFSection &getInfoSection() = 0; - virtual void forEachTypesSections(function_ref F) = 0; - virtual StringRef getAbbrevSection() = 0; - virtual const DWARFSection &getLocSection() = 0; - virtual StringRef getARangeSection() = 0; - virtual StringRef getDebugFrameSection() = 0; - virtual StringRef getEHFrameSection() = 0; - virtual const DWARFSection &getLineSection() = 0; - virtual StringRef getStringSection() = 0; - virtual const DWARFSection& getRangeSection() = 0; - virtual StringRef getMacinfoSection() = 0; - virtual StringRef getPubNamesSection() = 0; - virtual StringRef getPubTypesSection() = 0; - virtual StringRef getGnuPubNamesSection() = 0; - virtual StringRef getGnuPubTypesSection() = 0; - - /// DWARF v5 - /// @{ - virtual const DWARFSection &getStringOffsetSection() = 0; - /// @} - - // Sections for DWARF5 split dwarf proposal. - virtual const DWARFSection &getInfoDWOSection() = 0; - virtual void - forEachTypesDWOSections(function_ref F) = 0; - virtual StringRef getAbbrevDWOSection() = 0; - virtual const DWARFSection &getLineDWOSection() = 0; - virtual const DWARFSection &getLocDWOSection() = 0; - virtual StringRef getStringDWOSection() = 0; - virtual const DWARFSection &getStringOffsetDWOSection() = 0; - virtual const DWARFSection &getRangeDWOSection() = 0; - virtual const DWARFSection &getAddrSection() = 0; - virtual const DWARFSection& getAppleNamesSection() = 0; - virtual const DWARFSection& getAppleTypesSection() = 0; - virtual const DWARFSection& getAppleNamespacesSection() = 0; - virtual const DWARFSection& getAppleObjCSection() = 0; - virtual StringRef getCUIndexSection() = 0; - virtual StringRef getGdbIndexSection() = 0; - virtual StringRef getTUIndexSection() = 0; - + bool isLittleEndian() const { return DObj->isLittleEndian(); } static bool isSupportedVersion(unsigned version) { return version == 2 || version == 3 || version == 4 || version == 5; } std::shared_ptr getDWOContext(StringRef AbsolutePath); + /// Function used to handle default error reporting policy. Prints a error + /// message and returns Continue, so DWARF context ignores the error. + static ErrorPolicy defaultErrorHandler(Error E); + static std::unique_ptr + create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, + function_ref HandleError = defaultErrorHandler); + + static std::unique_ptr + create(const StringMap> &Sections, + uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost); + private: /// Return the compile unit that includes an offset (relative to .debug_info). DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); @@ -280,142 +260,6 @@ DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); }; -/// Used as a return value for a error callback passed to DWARF context. -/// Callback should return Halt if client application wants to stop -/// object parsing, or should return Continue otherwise. -enum class ErrorPolicy { Halt, Continue }; - -/// DWARFContextInMemory is the simplest possible implementation of a -/// DWARFContext. It assumes all content is available in memory and stores -/// pointers to it. -class DWARFContextInMemory : public DWARFContext { - virtual void anchor(); - - using TypeSectionMap = MapVector>; - - StringRef FileName; - bool IsLittleEndian; - uint8_t AddressSize; - DWARFSection InfoSection; - TypeSectionMap TypesSections; - StringRef AbbrevSection; - DWARFSection LocSection; - StringRef ARangeSection; - StringRef DebugFrameSection; - StringRef EHFrameSection; - DWARFSection LineSection; - StringRef StringSection; - DWARFSection RangeSection; - StringRef MacinfoSection; - StringRef PubNamesSection; - StringRef PubTypesSection; - StringRef GnuPubNamesSection; - StringRef GnuPubTypesSection; - - /// DWARF v5 - /// @{ - DWARFSection StringOffsetSection; - /// @} - - // Sections for DWARF5 split dwarf proposal. - DWARFSection InfoDWOSection; - TypeSectionMap TypesDWOSections; - StringRef AbbrevDWOSection; - DWARFSection LineDWOSection; - DWARFSection LocDWOSection; - StringRef StringDWOSection; - DWARFSection StringOffsetDWOSection; - DWARFSection RangeDWOSection; - DWARFSection AddrSection; - DWARFSection AppleNamesSection; - DWARFSection AppleTypesSection; - DWARFSection AppleNamespacesSection; - DWARFSection AppleObjCSection; - StringRef CUIndexSection; - StringRef GdbIndexSection; - StringRef TUIndexSection; - - SmallVector, 4> UncompressedSections; - - DWARFSection *mapNameToDWARFSection(StringRef Name); - StringRef *mapSectionToMember(StringRef Name); - - /// If Sec is compressed section, decompresses and updates its contents - /// provided by Data. Otherwise leaves it unchanged. - Error maybeDecompress(const object::SectionRef &Sec, StringRef Name, - StringRef &Data); - - /// Function used to handle default error reporting policy. Prints a error - /// message and returns Continue, so DWARF context ignores the error. - static ErrorPolicy defaultErrorHandler(Error E); - -public: - DWARFContextInMemory( - const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, - function_ref HandleError = defaultErrorHandler); - - DWARFContextInMemory(const StringMap> &Sections, - uint8_t AddrSize, - bool isLittleEndian = sys::IsLittleEndianHost); - - StringRef getFileName() const override { return FileName; } - bool isLittleEndian() const override { return IsLittleEndian; } - uint8_t getAddressSize() const override { return AddressSize; } - const DWARFSection &getInfoSection() override { return InfoSection; } - void forEachTypesSections(function_ref F) override { - for (auto &P : TypesSections) - F(P.second); - } - StringRef getAbbrevSection() override { return AbbrevSection; } - const DWARFSection &getLocSection() override { return LocSection; } - StringRef getARangeSection() override { return ARangeSection; } - StringRef getDebugFrameSection() override { return DebugFrameSection; } - StringRef getEHFrameSection() override { return EHFrameSection; } - const DWARFSection &getLineSection() override { return LineSection; } - StringRef getStringSection() override { return StringSection; } - const DWARFSection &getRangeSection() override { return RangeSection; } - StringRef getMacinfoSection() override { return MacinfoSection; } - StringRef getPubNamesSection() override { return PubNamesSection; } - StringRef getPubTypesSection() override { return PubTypesSection; } - StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } - StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } - const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; } - const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; } - const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; } - const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; } - - // DWARF v5 - const DWARFSection &getStringOffsetSection() override { - return StringOffsetSection; - } - - // Sections for DWARF5 split dwarf proposal. - const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; } - - void forEachTypesDWOSections(function_ref F) override { - for (auto &P : TypesDWOSections) - F(P.second); - } - - StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } - const DWARFSection &getLineDWOSection() override { return LineDWOSection; } - const DWARFSection &getLocDWOSection() override { return LocDWOSection; } - StringRef getStringDWOSection() override { return StringDWOSection; } - - const DWARFSection &getStringOffsetDWOSection() override { - return StringOffsetDWOSection; - } - - const DWARFSection &getRangeDWOSection() override { return RangeDWOSection; } - - const DWARFSection &getAddrSection() override { return AddrSection; } - - StringRef getCUIndexSection() override { return CUIndexSection; } - StringRef getGdbIndexSection() override { return GdbIndexSection; } - StringRef getTUIndexSection() override { return TUIndexSection; } -}; - } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H Index: include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -14,18 +14,21 @@ #include "llvm/Support/DataExtractor.h" namespace llvm { +class DWARFObj; /// A DataExtractor (typically for an in-memory copy of an object-file section) /// plus a relocation map for that section, if there is one. class DWARFDataExtractor : public DataExtractor { - const RelocAddrMap *RelocMap = nullptr; + const DWARFObj *Obj = nullptr; + const DWARFSection *Section = nullptr; + public: /// Constructor for the normal case of extracting data from a DWARF section. /// The DWARFSection's lifetime must be at least as long as the extractor's. - DWARFDataExtractor(const DWARFSection &Section, bool IsLittleEndian, - uint8_t AddressSize) - : DataExtractor(Section.Data, IsLittleEndian, AddressSize), - RelocMap(&Section.Relocs) {} + DWARFDataExtractor(const DWARFObj &Obj, const DWARFSection &Section, + bool IsLittleEndian, uint8_t AddressSize) + : DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj), + Section(&Section) {} /// Constructor for cases when there are no relocations. DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize) Index: include/llvm/DebugInfo/DWARF/DWARFObj.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/DWARF/DWARFObj.h @@ -0,0 +1,75 @@ +//===- DWARFObj.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_DWARF_DWARFOBJ_H +#define LLVM_DEBUGINFO_DWARF_DWARFOBJ_H + +#include "llvm/DebugInfo/DWARF/DWARFSection.h" + +namespace llvm { +// This is responsible for low level access to the object file. It +// knows how to find the required sections and compute relocated +// values. +// The default implementations of the get
methods return dummy values. +// This is to allow clients that only need some of those to implement just the +// ones they need. We can't use unreachable for as many cases because the parser +// implementation is eager and will call some of these methods even if the +// result is not used. +class DWARFObj { + DWARFSection Dummy; + +public: + virtual ~DWARFObj() = default; + virtual StringRef getFileName() const { llvm_unreachable("unimplemented"); } + virtual bool isLittleEndian() const = 0; + virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); } + virtual const DWARFSection &getInfoSection() const { return Dummy; } + virtual void + forEachTypesSections(function_ref F) const {} + virtual StringRef getAbbrevSection() const { return ""; } + virtual const DWARFSection &getLocSection() const { return Dummy; } + virtual StringRef getARangeSection() const { return ""; } + virtual StringRef getDebugFrameSection() const { return ""; } + virtual StringRef getEHFrameSection() const { return ""; } + virtual const DWARFSection &getLineSection() const { return Dummy; } + virtual StringRef getStringSection() const { return ""; } + virtual const DWARFSection &getRangeSection() const { return Dummy; } + virtual StringRef getMacinfoSection() const { return ""; } + virtual StringRef getPubNamesSection() const { return ""; } + virtual StringRef getPubTypesSection() const { return ""; } + virtual StringRef getGnuPubNamesSection() const { return ""; } + virtual StringRef getGnuPubTypesSection() const { return ""; } + virtual const DWARFSection &getStringOffsetSection() const { return Dummy; } + virtual const DWARFSection &getInfoDWOSection() const { return Dummy; } + virtual void + forEachTypesDWOSections(function_ref F) const {} + virtual StringRef getAbbrevDWOSection() const { return ""; } + virtual const DWARFSection &getLineDWOSection() const { return Dummy; } + virtual const DWARFSection &getLocDWOSection() const { return Dummy; } + virtual StringRef getStringDWOSection() const { return ""; } + virtual const DWARFSection &getStringOffsetDWOSection() const { + return Dummy; + } + virtual const DWARFSection &getRangeDWOSection() const { return Dummy; } + virtual const DWARFSection &getAddrSection() const { return Dummy; } + virtual const DWARFSection &getAppleNamesSection() const { return Dummy; } + virtual const DWARFSection &getAppleTypesSection() const { return Dummy; } + virtual const DWARFSection &getAppleNamespacesSection() const { + return Dummy; + } + virtual const DWARFSection &getAppleObjCSection() const { return Dummy; } + virtual StringRef getCUIndexSection() const { return ""; } + virtual StringRef getGdbIndexSection() const { return ""; } + virtual StringRef getTUIndexSection() const { return ""; } + virtual Optional find(const DWARFSection &Sec, + uint64_t Pos) const = 0; +}; + +} // namespace llvm +#endif Index: include/llvm/DebugInfo/DWARF/DWARFSection.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFSection.h +++ include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -17,6 +17,9 @@ struct DWARFSection { StringRef Data; +}; + +struct DWARFSectionMap final : public DWARFSection { RelocAddrMap Relocs; }; Index: include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -197,19 +197,12 @@ bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const; - DWARFDataExtractor getDebugInfoExtractor() const { - return DWARFDataExtractor(InfoSection, isLittleEndian, - getAddressByteSize()); - } + DWARFDataExtractor getDebugInfoExtractor() const; DataExtractor getStringExtractor() const { return DataExtractor(StringSection, false, 0); } - const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; } - const RelocAddrMap &getStringOffsetsRelocMap() const { - return StringOffsetSection.Relocs; - } bool extract(DataExtractor debug_info, uint32_t* offset_ptr); Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -60,9 +60,9 @@ using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; static void dumpAccelSection(raw_ostream &OS, StringRef Name, - const DWARFSection& Section, StringRef StringSection, - bool LittleEndian) { - DWARFDataExtractor AccelSection(Section, LittleEndian, 0); + const DWARFObj &Obj, const DWARFSection &Section, + StringRef StringSection, bool LittleEndian) { + DWARFDataExtractor AccelSection(Obj, Section, LittleEndian, 0); DataExtractor StrData(StringSection, LittleEndian, 0); OS << "\n." << Name << " contents:\n"; DWARFAcceleratorTable Accel(AccelSection, StrData); @@ -73,9 +73,10 @@ static void dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName, + const DWARFObj &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, bool LittleEndian) { - DWARFDataExtractor StrOffsetExt(StringOffsetsSection, LittleEndian, 0); + DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0); uint32_t Offset = 0; uint64_t SectionSize = StringOffsetsSection.Data.size(); @@ -153,6 +154,7 @@ // monolithic series of string offsets, as generated by the pre-DWARF v5 // implementation of split DWARF. static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, + const DWARFObj &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, bool LittleEndian, unsigned MaxVersion) { @@ -163,7 +165,7 @@ // we assume that the section is formatted like a DWARF v5 string offsets // section. if (MaxVersion >= 5) - dumpDWARFv5StringOffsetsSection(OS, SectionName, StringOffsetsSection, + dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection, StringSection, LittleEndian); else { DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); @@ -259,7 +261,7 @@ uint32_t offset = 0; if (DumpType == DIDT_All || DumpType == DIDT_Aranges) { OS << "\n.debug_aranges contents:\n"; - DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); + DataExtractor arangesData(DObj->getARangeSection(), isLittleEndian(), 0); DWARFDebugArangeSet set; while (set.extract(arangesData, &offset)) set.dump(OS); @@ -274,8 +276,8 @@ if (!CUDIE) continue; if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) { - DWARFDataExtractor lineData(getLineSection(), isLittleEndian(), - savedAddressByteSize); + DWARFDataExtractor lineData(*DObj, DObj->getLineSection(), + isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; uint32_t Offset = *StmtOffset; LineTable.parse(lineData, &Offset); @@ -297,8 +299,8 @@ if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) { OS << "\n.debug_line.dwo contents:\n"; unsigned stmtOffset = 0; - DWARFDataExtractor lineData(getLineDWOSection(), isLittleEndian(), - savedAddressByteSize); + DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(), + isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; while (LineTable.Prologue.parse(lineData, &stmtOffset)) { LineTable.dump(OS); @@ -308,7 +310,7 @@ if (DumpType == DIDT_All || DumpType == DIDT_Str) { OS << "\n.debug_str contents:\n"; - DataExtractor strData(getStringSection(), isLittleEndian(), 0); + DataExtractor strData(DObj->getStringSection(), isLittleEndian(), 0); offset = 0; uint32_t strOffset = 0; while (const char *s = strData.getCStr(&offset)) { @@ -318,9 +320,9 @@ } if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) && - !getStringDWOSection().empty()) { + !DObj->getStringDWOSection().empty()) { OS << "\n.debug_str.dwo contents:\n"; - DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0); + DataExtractor strDWOData(DObj->getStringDWOSection(), isLittleEndian(), 0); offset = 0; uint32_t strDWOOffset = 0; while (const char *s = strDWOData.getCStr(&offset)) { @@ -335,8 +337,8 @@ // sizes, but for simplicity we just use the address byte size of the last // compile unit (there is no easy and fast way to associate address range // list and the compile unit it describes). - DWARFDataExtractor rangesData(getRangeSection(), isLittleEndian(), - savedAddressByteSize); + DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(), + isLittleEndian(), savedAddressByteSize); offset = 0; DWARFDebugRangeList rangeList; while (rangeList.extract(rangesData, &offset)) @@ -344,55 +346,56 @@ } if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) - DWARFDebugPubTable(getPubNamesSection(), isLittleEndian(), false) + DWARFDebugPubTable(DObj->getPubNamesSection(), isLittleEndian(), false) .dump("debug_pubnames", OS); if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes) - DWARFDebugPubTable(getPubTypesSection(), isLittleEndian(), false) + DWARFDebugPubTable(DObj->getPubTypesSection(), isLittleEndian(), false) .dump("debug_pubtypes", OS); if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames) - DWARFDebugPubTable(getGnuPubNamesSection(), isLittleEndian(), + DWARFDebugPubTable(DObj->getGnuPubNamesSection(), isLittleEndian(), true /* GnuStyle */) .dump("debug_gnu_pubnames", OS); if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes) - DWARFDebugPubTable(getGnuPubTypesSection(), isLittleEndian(), + DWARFDebugPubTable(DObj->getGnuPubTypesSection(), isLittleEndian(), true /* GnuStyle */) .dump("debug_gnu_pubtypes", OS); if (DumpType == DIDT_All || DumpType == DIDT_StrOffsets) - dumpStringOffsetsSection(OS, "debug_str_offsets", getStringOffsetSection(), - getStringSection(), isLittleEndian(), - getMaxVersion()); + dumpStringOffsetsSection( + OS, "debug_str_offsets", *DObj, DObj->getStringOffsetSection(), + DObj->getStringSection(), isLittleEndian(), getMaxVersion()); if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) { - dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", - getStringOffsetDWOSection(), getStringDWOSection(), - isLittleEndian(), getMaxVersion()); + dumpStringOffsetsSection( + OS, "debug_str_offsets.dwo", *DObj, DObj->getStringOffsetDWOSection(), + DObj->getStringDWOSection(), isLittleEndian(), getMaxVersion()); } if ((DumpType == DIDT_All || DumpType == DIDT_GdbIndex) && - !getGdbIndexSection().empty()) { + !DObj->getGdbIndexSection().empty()) { OS << "\n.gnu_index contents:\n"; getGdbIndex().dump(OS); } if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) - dumpAccelSection(OS, "apple_names", getAppleNamesSection(), - getStringSection(), isLittleEndian()); + dumpAccelSection(OS, "apple_names", *DObj, DObj->getAppleNamesSection(), + DObj->getStringSection(), isLittleEndian()); if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes) - dumpAccelSection(OS, "apple_types", getAppleTypesSection(), - getStringSection(), isLittleEndian()); + dumpAccelSection(OS, "apple_types", *DObj, DObj->getAppleTypesSection(), + DObj->getStringSection(), isLittleEndian()); if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces) - dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(), - getStringSection(), isLittleEndian()); + dumpAccelSection(OS, "apple_namespaces", *DObj, + DObj->getAppleNamespacesSection(), + DObj->getStringSection(), isLittleEndian()); if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC) - dumpAccelSection(OS, "apple_objc", getAppleObjCSection(), - getStringSection(), isLittleEndian()); + dumpAccelSection(OS, "apple_objc", *DObj, DObj->getAppleObjCSection(), + DObj->getStringSection(), isLittleEndian()); } DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { @@ -433,7 +436,7 @@ if (CUIndex) return *CUIndex; - DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(), 0); + DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0); CUIndex = llvm::make_unique(DW_SECT_INFO); CUIndex->parse(CUIndexData); @@ -444,7 +447,7 @@ if (TUIndex) return *TUIndex; - DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(), 0); + DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0); TUIndex = llvm::make_unique(DW_SECT_TYPES); TUIndex->parse(TUIndexData); @@ -455,7 +458,7 @@ if (GdbIndex) return *GdbIndex; - DataExtractor GdbIndexData(getGdbIndexSection(), true /*LE*/, 0); + DataExtractor GdbIndexData(DObj->getGdbIndexSection(), true /*LE*/, 0); GdbIndex = llvm::make_unique(); GdbIndex->parse(GdbIndexData); return *GdbIndex; @@ -465,7 +468,7 @@ if (Abbrev) return Abbrev.get(); - DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); + DataExtractor abbrData(DObj->getAbbrevSection(), isLittleEndian(), 0); Abbrev.reset(new DWARFDebugAbbrev()); Abbrev->extract(abbrData); @@ -476,7 +479,7 @@ if (AbbrevDWO) return AbbrevDWO.get(); - DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0); + DataExtractor abbrData(DObj->getAbbrevDWOSection(), isLittleEndian(), 0); AbbrevDWO.reset(new DWARFDebugAbbrev()); AbbrevDWO->extract(abbrData); return AbbrevDWO.get(); @@ -489,7 +492,7 @@ Loc.reset(new DWARFDebugLoc); // assume all compile units have the same address byte size if (getNumCompileUnits()) { - DWARFDataExtractor LocData(getLocSection(), isLittleEndian(), + DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(), getCompileUnitAtIndex(0)->getAddressByteSize()); Loc->parse(LocData); } @@ -500,7 +503,7 @@ if (LocDWO) return LocDWO.get(); - DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0); + DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 0); LocDWO.reset(new DWARFDebugLocDWO()); LocDWO->parse(LocData); return LocDWO.get(); @@ -528,8 +531,8 @@ // provides this information). This problem is fixed in DWARFv4 // See this dwarf-discuss discussion for more details: // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html - DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(), - getAddressSize()); + DataExtractor debugFrameData(DObj->getDebugFrameSection(), isLittleEndian(), + DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); @@ -539,8 +542,8 @@ if (EHFrame) return EHFrame.get(); - DataExtractor debugFrameData(getEHFrameSection(), isLittleEndian(), - getAddressSize()); + DataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(), + DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); @@ -550,7 +553,7 @@ if (Macro) return Macro.get(); - DataExtractor MacinfoData(getMacinfoSection(), isLittleEndian(), 0); + DataExtractor MacinfoData(DObj->getMacinfoSection(), isLittleEndian(), 0); Macro.reset(new DWARFDebugMacro()); Macro->parse(MacinfoData); return Macro.get(); @@ -579,32 +582,32 @@ return nullptr; // We have to parse it first. - DWARFDataExtractor lineData(U->getLineSection(), isLittleEndian(), + DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); return Line->getOrParseLineTable(lineData, stmtOffset); } void DWARFContext::parseCompileUnits() { - CUs.parse(*this, getInfoSection()); + CUs.parse(*this, DObj->getInfoSection()); } void DWARFContext::parseTypeUnits() { if (!TUs.empty()) return; - forEachTypesSections([&](const DWARFSection &S) { + DObj->forEachTypesSections([&](const DWARFSection &S) { TUs.emplace_back(); TUs.back().parse(*this, S); }); } void DWARFContext::parseDWOCompileUnits() { - DWOCUs.parseDWO(*this, getInfoDWOSection()); + DWOCUs.parseDWO(*this, DObj->getInfoDWOSection()); } void DWARFContext::parseDWOTypeUnits() { if (!DWOTUs.empty()) return; - forEachTypesDWOSections([&](const DWARFSection &S) { + DObj->forEachTypesDWOSections([&](const DWARFSection &S) { DWOTUs.emplace_back(); DWOTUs.back().parseDWO(*this, S); }); @@ -779,6 +782,20 @@ return InliningInfo; } +/// DWARFContextInMemory is the simplest possible implementation of a +/// DWARFContext. It assumes all content is available in memory and stores +/// pointers to it. +class DWARFContextInMemory : public DWARFContext { +public: + DWARFContextInMemory( + const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, + function_ref HandleError = defaultErrorHandler); + + DWARFContextInMemory(const StringMap> &Sections, + uint8_t AddrSize, + bool isLittleEndian = sys::IsLittleEndianHost); +}; + std::shared_ptr DWARFContext::getDWOContext(StringRef AbsolutePath) { if (auto S = DWP.lock()) { @@ -796,7 +813,7 @@ SmallString<128> DWPName; Expected> Obj = [&] { if (!CheckedForDWP) { - (getFileName() + ".dwp").toVector(DWPName); + (DObj->getFileName() + ".dwp").toVector(DWPName); auto Obj = object::ObjectFile::createObjectFile(DWPName); if (Obj) { Entry = &DWP; @@ -820,7 +837,7 @@ auto S = std::make_shared(); S->File = std::move(Obj.get()); - S->Context = llvm::make_unique(*S->File.getBinary()); + S->Context = DWARFContext::create(*S->File.getBinary()); *Entry = S; auto *Ctxt = S->Context.get(); return std::shared_ptr(std::move(S), Ctxt); @@ -906,208 +923,355 @@ return MachObj->isRelocationScattered(RelocInfo); } -Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec, - StringRef Name, StringRef &Data) { - if (!Decompressor::isCompressed(Sec)) - return Error::success(); +ErrorPolicy DWARFContext::defaultErrorHandler(Error E) { + errs() << "error: " + toString(std::move(E)) << '\n'; + return ErrorPolicy::Continue; +} - Expected Decompressor = - Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8); - if (!Decompressor) - return Decompressor.takeError(); +class DWARFObjInMemory final : public DWARFObj { + bool IsLittleEndian; + uint8_t AddressSize; + StringRef FileName; + + using TypeSectionMap = MapVector>; + + TypeSectionMap TypesSections; + TypeSectionMap TypesDWOSections; + + DWARFSectionMap InfoSection; + DWARFSectionMap LocSection; + DWARFSectionMap LineSection; + DWARFSectionMap RangeSection; + DWARFSectionMap StringOffsetSection; + DWARFSectionMap InfoDWOSection; + DWARFSectionMap LineDWOSection; + DWARFSectionMap LocDWOSection; + DWARFSectionMap StringOffsetDWOSection; + DWARFSectionMap RangeDWOSection; + DWARFSectionMap AddrSection; + DWARFSectionMap AppleNamesSection; + DWARFSectionMap AppleTypesSection; + DWARFSectionMap AppleNamespacesSection; + DWARFSectionMap AppleObjCSection; + + DWARFSectionMap *mapNameToDWARFSection(StringRef Name) { + return StringSwitch(Name) + .Case("debug_info", &InfoSection) + .Case("debug_loc", &LocSection) + .Case("debug_line", &LineSection) + .Case("debug_str_offsets", &StringOffsetSection) + .Case("debug_ranges", &RangeSection) + .Case("debug_info.dwo", &InfoDWOSection) + .Case("debug_loc.dwo", &LocDWOSection) + .Case("debug_line.dwo", &LineDWOSection) + .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) + .Case("debug_addr", &AddrSection) + .Case("apple_names", &AppleNamesSection) + .Case("apple_types", &AppleTypesSection) + .Case("apple_namespaces", &AppleNamespacesSection) + .Case("apple_namespac", &AppleNamespacesSection) + .Case("apple_objc", &AppleObjCSection) + .Default(nullptr); + } - SmallString<32> Out; - if (auto Err = Decompressor->resizeAndDecompress(Out)) - return Err; + StringRef AbbrevSection; + StringRef ARangeSection; + StringRef DebugFrameSection; + StringRef EHFrameSection; + StringRef StringSection; + StringRef MacinfoSection; + StringRef PubNamesSection; + StringRef PubTypesSection; + StringRef GnuPubNamesSection; + StringRef AbbrevDWOSection; + StringRef StringDWOSection; + StringRef GnuPubTypesSection; + StringRef CUIndexSection; + StringRef GdbIndexSection; + StringRef TUIndexSection; + + SmallVector, 4> UncompressedSections; + + StringRef *mapSectionToMember(StringRef Name) { + if (DWARFSection *Sec = mapNameToDWARFSection(Name)) + return &Sec->Data; + return StringSwitch(Name) + .Case("debug_abbrev", &AbbrevSection) + .Case("debug_aranges", &ARangeSection) + .Case("debug_frame", &DebugFrameSection) + .Case("eh_frame", &EHFrameSection) + .Case("debug_str", &StringSection) + .Case("debug_macinfo", &MacinfoSection) + .Case("debug_pubnames", &PubNamesSection) + .Case("debug_pubtypes", &PubTypesSection) + .Case("debug_gnu_pubnames", &GnuPubNamesSection) + .Case("debug_gnu_pubtypes", &GnuPubTypesSection) + .Case("debug_abbrev.dwo", &AbbrevDWOSection) + .Case("debug_str.dwo", &StringDWOSection) + .Case("debug_cu_index", &CUIndexSection) + .Case("debug_tu_index", &TUIndexSection) + .Case("gdb_index", &GdbIndexSection) + // Any more debug info sections go here. + .Default(nullptr); + } - UncompressedSections.emplace_back(std::move(Out)); - Data = UncompressedSections.back(); + /// If Sec is compressed section, decompresses and updates its contents + /// provided by Data. Otherwise leaves it unchanged. + Error maybeDecompress(const object::SectionRef &Sec, StringRef Name, + StringRef &Data) { + if (!Decompressor::isCompressed(Sec)) + return Error::success(); - return Error::success(); -} + Expected Decompressor = + Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8); + if (!Decompressor) + return Decompressor.takeError(); -ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) { - errs() << "error: " + toString(std::move(E)) << '\n'; - return ErrorPolicy::Continue; -} + SmallString<32> Out; + if (auto Err = Decompressor->resizeAndDecompress(Out)) + return Err; -DWARFContextInMemory::DWARFContextInMemory( - const object::ObjectFile &Obj, const LoadedObjectInfo *L, - function_ref HandleError) - : FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()), - AddressSize(Obj.getBytesInAddress()) { - for (const SectionRef &Section : Obj.sections()) { - StringRef Name; - Section.getName(Name); - // Skip BSS and Virtual sections, they aren't interesting. - if (Section.isBSS() || Section.isVirtual()) - continue; - - StringRef Data; - section_iterator RelocatedSection = Section.getRelocatedSection(); - // Try to obtain an already relocated version of this section. - // Else use the unrelocated section from the object file. We'll have to - // apply relocations ourselves later. - if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) - Section.getContents(Data); - - if (auto Err = maybeDecompress(Section, Name, Data)) { - ErrorPolicy EP = HandleError( - createError("failed to decompress '" + Name + "', ", std::move(Err))); - if (EP == ErrorPolicy::Halt) - return; - continue; - } + UncompressedSections.emplace_back(std::move(Out)); + Data = UncompressedSections.back(); - // Compressed sections names in GNU style starts from ".z", - // at this point section is decompressed and we drop compression prefix. - Name = Name.substr( - Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes. + return Error::success(); + } - // Map platform specific debug section names to DWARF standard section - // names. - Name = Obj.mapDebugSectionName(Name); +public: + DWARFObjInMemory(const StringMap> &Sections, + uint8_t AddrSize, bool IsLittleEndian) + : IsLittleEndian(IsLittleEndian) { + for (const auto &SecIt : Sections) { + if (StringRef *SectionData = mapSectionToMember(SecIt.first())) + *SectionData = SecIt.second->getBuffer(); + } + } + DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L, + function_ref HandleError) + : IsLittleEndian(Obj.isLittleEndian()), + AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()) { + + for (const SectionRef &Section : Obj.sections()) { + StringRef Name; + Section.getName(Name); + // Skip BSS and Virtual sections, they aren't interesting. + if (Section.isBSS() || Section.isVirtual()) + continue; - if (StringRef *SectionData = mapSectionToMember(Name)) { - *SectionData = Data; - if (Name == "debug_ranges") { - // FIXME: Use the other dwo range section when we emit it. - RangeDWOSection.Data = Data; + StringRef Data; + section_iterator RelocatedSection = Section.getRelocatedSection(); + // Try to obtain an already relocated version of this section. + // Else use the unrelocated section from the object file. We'll have to + // apply relocations ourselves later. + if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) + Section.getContents(Data); + + if (auto Err = maybeDecompress(Section, Name, Data)) { + ErrorPolicy EP = HandleError(createError( + "failed to decompress '" + Name + "', ", std::move(Err))); + if (EP == ErrorPolicy::Halt) + return; + continue; + } + + // Compressed sections names in GNU style starts from ".z", + // at this point section is decompressed and we drop compression prefix. + Name = Name.substr( + Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes. + + // Map platform specific debug section names to DWARF standard section + // names. + Name = Obj.mapDebugSectionName(Name); + + if (StringRef *SectionData = mapSectionToMember(Name)) { + *SectionData = Data; + if (Name == "debug_ranges") { + // FIXME: Use the other dwo range section when we emit it. + RangeDWOSection.Data = Data; + } + } else if (Name == "debug_types") { + // Find debug_types data by section rather than name as there are + // multiple, comdat grouped, debug_types sections. + TypesSections[Section].Data = Data; + } else if (Name == "debug_types.dwo") { + TypesDWOSections[Section].Data = Data; } - } else if (Name == "debug_types") { - // Find debug_types data by section rather than name as there are - // multiple, comdat grouped, debug_types sections. - TypesSections[Section].Data = Data; - } else if (Name == "debug_types.dwo") { - TypesDWOSections[Section].Data = Data; - } - if (RelocatedSection == Obj.section_end()) - continue; - - StringRef RelSecName; - StringRef RelSecData; - RelocatedSection->getName(RelSecName); - - // If the section we're relocating was relocated already by the JIT, - // then we used the relocated version above, so we do not need to process - // relocations for it now. - if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData)) - continue; - - // In Mach-o files, the relocations do not need to be applied if - // there is no load offset to apply. The value read at the - // relocation point already factors in the section address - // (actually applying the relocations will produce wrong results - // as the section address will be added twice). - if (!L && isa(&Obj)) - continue; - - RelSecName = RelSecName.substr( - RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes. - - // TODO: Add support for relocations in other sections as needed. - // Record relocations for the debug_info and debug_line sections. - DWARFSection *Sec = mapNameToDWARFSection(RelSecName); - RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr; - if (!Map) { - // Find debug_types relocs by section rather than name as there are - // multiple, comdat grouped, debug_types sections. - if (RelSecName == "debug_types") - Map = &TypesSections[*RelocatedSection].Relocs; - else if (RelSecName == "debug_types.dwo") - Map = &TypesDWOSections[*RelocatedSection].Relocs; - else + if (RelocatedSection == Obj.section_end()) continue; - } - if (Section.relocation_begin() == Section.relocation_end()) - continue; + StringRef RelSecName; + StringRef RelSecData; + RelocatedSection->getName(RelSecName); - // Symbol to [address, section index] cache mapping. - std::map AddrCache; - for (const RelocationRef &Reloc : Section.relocations()) { - // FIXME: it's not clear how to correctly handle scattered - // relocations. - if (isRelocScattered(Obj, Reloc)) + // If the section we're relocating was relocated already by the JIT, + // then we used the relocated version above, so we do not need to process + // relocations for it now. + if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData)) continue; - Expected SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache); - if (!SymInfoOrErr) { - if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt) - return; + // In Mach-o files, the relocations do not need to be applied if + // there is no load offset to apply. The value read at the + // relocation point already factors in the section address + // (actually applying the relocations will produce wrong results + // as the section address will be added twice). + if (!L && isa(&Obj)) continue; + + RelSecName = RelSecName.substr( + RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes. + + // TODO: Add support for relocations in other sections as needed. + // Record relocations for the debug_info and debug_line sections. + DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName); + RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr; + if (!Map) { + // Find debug_types relocs by section rather than name as there are + // multiple, comdat grouped, debug_types sections. + if (RelSecName == "debug_types") + Map = + &static_cast(TypesSections[*RelocatedSection]) + .Relocs; + else if (RelSecName == "debug_types.dwo") + Map = &static_cast( + TypesDWOSections[*RelocatedSection]) + .Relocs; + else + continue; } - object::RelocVisitor V(Obj); - uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); - if (V.error()) { - SmallString<32> Type; - Reloc.getTypeName(Type); - ErrorPolicy EP = HandleError( - createError("failed to compute relocation: " + Type + ", ", - errorCodeToError(object_error::parse_failed))); - if (EP == ErrorPolicy::Halt) - return; + if (Section.relocation_begin() == Section.relocation_end()) continue; + + // Symbol to [address, section index] cache mapping. + std::map AddrCache; + for (const RelocationRef &Reloc : Section.relocations()) { + // FIXME: it's not clear how to correctly handle scattered + // relocations. + if (isRelocScattered(Obj, Reloc)) + continue; + + Expected SymInfoOrErr = + getSymbolInfo(Obj, Reloc, L, AddrCache); + if (!SymInfoOrErr) { + if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt) + return; + continue; + } + + object::RelocVisitor V(Obj); + uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); + if (V.error()) { + SmallString<32> Type; + Reloc.getTypeName(Type); + ErrorPolicy EP = HandleError( + createError("failed to compute relocation: " + Type + ", ", + errorCodeToError(object_error::parse_failed))); + if (EP == ErrorPolicy::Halt) + return; + continue; + } + RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; + Map->insert({Reloc.getOffset(), Rel}); } - RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; - Map->insert({Reloc.getOffset(), Rel}); } } -} -DWARFContextInMemory::DWARFContextInMemory( - const StringMap> &Sections, uint8_t AddrSize, - bool isLittleEndian) - : IsLittleEndian(isLittleEndian), AddressSize(AddrSize) { - for (const auto &SecIt : Sections) { - if (StringRef *SectionData = mapSectionToMember(SecIt.first())) - *SectionData = SecIt.second->getBuffer(); + Optional find(const DWARFSection &S, + uint64_t Pos) const override { + auto &Sec = static_cast(S); + RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos); + if (AI == Sec.Relocs.end()) + return None; + return AI->second; } -} -DWARFSection *DWARFContextInMemory::mapNameToDWARFSection(StringRef Name) { - return StringSwitch(Name) - .Case("debug_info", &InfoSection) - .Case("debug_loc", &LocSection) - .Case("debug_line", &LineSection) - .Case("debug_str_offsets", &StringOffsetSection) - .Case("debug_ranges", &RangeSection) - .Case("debug_info.dwo", &InfoDWOSection) - .Case("debug_loc.dwo", &LocDWOSection) - .Case("debug_line.dwo", &LineDWOSection) - .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) - .Case("debug_addr", &AddrSection) - .Case("apple_names", &AppleNamesSection) - .Case("apple_types", &AppleTypesSection) - .Case("apple_namespaces", &AppleNamespacesSection) - .Case("apple_namespac", &AppleNamespacesSection) - .Case("apple_objc", &AppleObjCSection) - .Default(nullptr); -} + bool isLittleEndian() const override { return IsLittleEndian; } + StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; } + const DWARFSection &getLineDWOSection() const override { + return LineDWOSection; + } + const DWARFSection &getLocDWOSection() const override { + return LocDWOSection; + } + StringRef getStringDWOSection() const override { return StringDWOSection; } + const DWARFSection &getStringOffsetDWOSection() const override { + return StringOffsetDWOSection; + } + const DWARFSection &getRangeDWOSection() const override { + return RangeDWOSection; + } + const DWARFSection &getAddrSection() const override { return AddrSection; } + StringRef getCUIndexSection() const override { return CUIndexSection; } + StringRef getGdbIndexSection() const override { return GdbIndexSection; } + StringRef getTUIndexSection() const override { return TUIndexSection; } + + // DWARF v5 + const DWARFSection &getStringOffsetSection() const override { + return StringOffsetSection; + } + + // Sections for DWARF5 split dwarf proposal. + const DWARFSection &getInfoDWOSection() const override { + return InfoDWOSection; + } + void forEachTypesDWOSections( + function_ref F) const override { + for (auto &P : TypesDWOSections) + F(P.second); + } -StringRef *DWARFContextInMemory::mapSectionToMember(StringRef Name) { - if (DWARFSection *Sec = mapNameToDWARFSection(Name)) - return &Sec->Data; - return StringSwitch(Name) - .Case("debug_abbrev", &AbbrevSection) - .Case("debug_aranges", &ARangeSection) - .Case("debug_frame", &DebugFrameSection) - .Case("eh_frame", &EHFrameSection) - .Case("debug_str", &StringSection) - .Case("debug_macinfo", &MacinfoSection) - .Case("debug_pubnames", &PubNamesSection) - .Case("debug_pubtypes", &PubTypesSection) - .Case("debug_gnu_pubnames", &GnuPubNamesSection) - .Case("debug_gnu_pubtypes", &GnuPubTypesSection) - .Case("debug_abbrev.dwo", &AbbrevDWOSection) - .Case("debug_str.dwo", &StringDWOSection) - .Case("debug_cu_index", &CUIndexSection) - .Case("debug_tu_index", &TUIndexSection) - .Case("gdb_index", &GdbIndexSection) - // Any more debug info sections go here. - .Default(nullptr); + StringRef getAbbrevSection() const override { return AbbrevSection; } + const DWARFSection &getLocSection() const override { return LocSection; } + StringRef getARangeSection() const override { return ARangeSection; } + StringRef getDebugFrameSection() const override { return DebugFrameSection; } + StringRef getEHFrameSection() const override { return EHFrameSection; } + const DWARFSection &getLineSection() const override { return LineSection; } + StringRef getStringSection() const override { return StringSection; } + const DWARFSection &getRangeSection() const override { return RangeSection; } + StringRef getMacinfoSection() const override { return MacinfoSection; } + StringRef getPubNamesSection() const override { return PubNamesSection; } + StringRef getPubTypesSection() const override { return PubTypesSection; } + StringRef getGnuPubNamesSection() const override { + return GnuPubNamesSection; + } + StringRef getGnuPubTypesSection() const override { + return GnuPubTypesSection; + } + const DWARFSection &getAppleNamesSection() const override { + return AppleNamesSection; + } + const DWARFSection &getAppleTypesSection() const override { + return AppleTypesSection; + } + const DWARFSection &getAppleNamespacesSection() const override { + return AppleNamespacesSection; + } + const DWARFSection &getAppleObjCSection() const override { + return AppleObjCSection; + } + + StringRef getFileName() const override { return FileName; } + uint8_t getAddressSize() const override { return AddressSize; } + const DWARFSection &getInfoSection() const override { return InfoSection; } + void forEachTypesSections( + function_ref F) const override { + for (auto &P : TypesSections) + F(P.second); + } +}; + +std::unique_ptr +DWARFContext::create(const object::ObjectFile &Obj, const LoadedObjectInfo *L, + function_ref HandleError) { + auto DObj = make_unique(Obj, L, HandleError); + return make_unique(std::move(DObj)); } -void DWARFContextInMemory::anchor() {} +std::unique_ptr +DWARFContext::create(const StringMap> &Sections, + uint8_t AddrSize, bool isLittleEndian) { + auto DObj = make_unique(Sections, AddrSize, isLittleEndian); + return make_unique(std::move(DObj)); +} Index: lib/DebugInfo/DWARF/DWARFDataExtractor.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -8,17 +8,18 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" using namespace llvm; uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, uint64_t *SecNdx) const { - if (!RelocMap) + if (!Section) return getUnsigned(Off, Size); - RelocAddrMap::const_iterator AI = RelocMap->find(*Off); - if (AI == RelocMap->end()) + Optional Rel = Obj->find(*Section, *Off); + if (!Rel) return getUnsigned(Off, Size); if (SecNdx) - *SecNdx = AI->second.SectionIndex; - return getUnsigned(Off, Size) + AI->second.Value; + *SecNdx = Rel->SectionIndex; + return getUnsigned(Off, Size) + Rel->Value; } Index: lib/DebugInfo/DWARF/DWARFDebugAranges.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -43,7 +43,8 @@ return; // Extract aranges from .debug_aranges section. - DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0); + DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(), + CTX->isLittleEndian(), 0); extract(ArangesData); // Generate aranges from DIEs: even if .debug_aranges section is present, Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -30,17 +30,19 @@ using namespace dwarf; void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { - parseImpl(C, Section, C.getDebugAbbrev(), &C.getRangeSection(), - C.getStringSection(), C.getStringOffsetSection(), - &C.getAddrSection(), C.getLineSection(), C.isLittleEndian(), false); + const DWARFObj &D = C.getDWARFObj(); + parseImpl(C, Section, C.getDebugAbbrev(), &D.getRangeSection(), + D.getStringSection(), D.getStringOffsetSection(), + &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false); } void DWARFUnitSectionBase::parseDWO(DWARFContext &C, const DWARFSection &DWOSection, DWARFUnitIndex *Index) { - parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &C.getRangeDWOSection(), - C.getStringDWOSection(), C.getStringOffsetDWOSection(), - &C.getAddrSection(), C.getLineDWOSection(), C.isLittleEndian(), + const DWARFObj &D = C.getDWARFObj(); + parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), + D.getStringDWOSection(), D.getStringOffsetDWOSection(), + &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(), true); } @@ -59,13 +61,18 @@ DWARFUnit::~DWARFUnit() = default; +DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { + return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian, + getAddressByteSize()); +} + bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const { uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) return false; - DWARFDataExtractor DA(*AddrOffsetSection, isLittleEndian, - getAddressByteSize()); + DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, + isLittleEndian, getAddressByteSize()); Result = DA.getRelocatedAddress(&Offset); return true; } @@ -76,7 +83,8 @@ uint32_t Offset = StringOffsetSectionBase + Index * ItemSize; if (StringOffsetSection.Data.size() < Offset + ItemSize) return false; - DWARFDataExtractor DA(StringOffsetSection, isLittleEndian, 0); + DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, + isLittleEndian, 0); Result = DA.getRelocatedValue(ItemSize, &Offset); return true; } @@ -141,8 +149,8 @@ DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. assert(!DieArray.empty()); - DWARFDataExtractor RangesData(*RangeSection, isLittleEndian, - getAddressByteSize()); + DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, + isLittleEndian, getAddressByteSize()); uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; return RangeList.extract(RangesData, &ActualRangeListOffset); } Index: lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -105,7 +105,8 @@ bool DWARFVerifier::handleDebugInfo() { OS << "Verifying .debug_info Unit Header Chain...\n"; - DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(), + const DWARFObj &DObj = DCtx.getDWARFObj(); + DWARFDataExtractor DebugInfoData(DObj, DObj.getInfoSection(), DCtx.isLittleEndian(), 0); uint32_t NumDebugInfoErrors = 0; uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0; @@ -127,10 +128,10 @@ case dwarf::DW_UT_split_type: { DWARFUnitSection TUSection{}; Unit.reset(new DWARFTypeUnit( - DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(), - &DCtx.getRangeSection(), DCtx.getStringSection(), - DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(), - DCtx.getLineSection(), DCtx.isLittleEndian(), false, TUSection, + DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(), + &DObj.getRangeSection(), DObj.getStringSection(), + DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), + DObj.getLineSection(), DCtx.isLittleEndian(), false, TUSection, nullptr)); break; } @@ -143,10 +144,10 @@ case 0: { DWARFUnitSection CUSection{}; Unit.reset(new DWARFCompileUnit( - DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(), - &DCtx.getRangeSection(), DCtx.getStringSection(), - DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(), - DCtx.getLineSection(), DCtx.isLittleEndian(), false, CUSection, + DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(), + &DObj.getRangeSection(), DObj.getStringSection(), + DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), + DObj.getLineSection(), DCtx.isLittleEndian(), false, CUSection, nullptr)); break; } @@ -169,13 +170,14 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue) { + const DWARFObj &DObj = DCtx.getDWARFObj(); unsigned NumErrors = 0; const auto Attr = AttrValue.Attr; switch (Attr) { case DW_AT_ranges: // Make sure the offset in the DW_AT_ranges attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DCtx.getRangeSection().Data.size()) { + if (*SectionOffset >= DObj.getRangeSection().Data.size()) { ++NumErrors; OS << "error: DW_AT_ranges offset is beyond .debug_ranges " "bounds:\n"; @@ -192,7 +194,7 @@ case DW_AT_stmt_list: // Make sure the offset in the DW_AT_stmt_list attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DCtx.getLineSection().Data.size()) { + if (*SectionOffset >= DObj.getLineSection().Data.size()) { ++NumErrors; OS << "error: DW_AT_stmt_list offset is beyond .debug_line " "bounds: " @@ -216,6 +218,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue) { + const DWARFObj &DObj = DCtx.getDWARFObj(); unsigned NumErrors = 0; const auto Form = AttrValue.Value.getForm(); switch (Form) { @@ -253,7 +256,7 @@ Optional RefVal = AttrValue.Value.getAsReference(); assert(RefVal); if (RefVal) { - if (*RefVal >= DCtx.getInfoSection().Data.size()) { + if (*RefVal >= DObj.getInfoSection().Data.size()) { ++NumErrors; OS << "error: DW_FORM_ref_addr offset beyond .debug_info " "bounds:\n"; @@ -270,7 +273,7 @@ case DW_FORM_strp: { auto SecOffset = AttrValue.Value.getAsSectionOffset(); assert(SecOffset); // DW_FORM_strp is a section offset. - if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) { + if (SecOffset && *SecOffset >= DObj.getStringSection().size()) { ++NumErrors; OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n"; Die.dump(OS, 0); @@ -318,7 +321,7 @@ continue; const uint32_t LineTableOffset = *StmtSectionOffset; auto LineTable = DCtx.getLineTableForUnit(CU.get()); - if (LineTableOffset < DCtx.getLineSection().Data.size()) { + if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) { if (!LineTable) { ++NumDebugLineErrors; OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) @@ -408,10 +411,10 @@ bool DWARFVerifier::handleAppleNames() { NumAppleNamesErrors = 0; - - DWARFDataExtractor AppleNamesSection(DCtx.getAppleNamesSection(), + const DWARFObj &D = DCtx.getDWARFObj(); + DWARFDataExtractor AppleNamesSection(D, D.getAppleNamesSection(), DCtx.isLittleEndian(), 0); - DataExtractor StrData(DCtx.getStringSection(), DCtx.isLittleEndian(), 0); + DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0); DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData); if (!AppleNames.extract()) { Index: lib/DebugInfo/Symbolize/Symbolize.cpp =================================================================== --- lib/DebugInfo/Symbolize/Symbolize.cpp +++ lib/DebugInfo/Symbolize/Symbolize.cpp @@ -409,7 +409,7 @@ } } if (!Context) - Context.reset(new DWARFContextInMemory(*Objects.second)); + Context = DWARFContext::create(*Objects.second); assert(Context); auto InfoOrErr = SymbolizableObjectFile::create(Objects.first, std::move(Context)); Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -845,7 +845,7 @@ MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection()); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); - const DWARFSection &InputSec = Dwarf.getLocSection(); + const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection(); DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize); DWARFUnit &OrigUnit = Unit.getOrigUnit(); auto OrigUnitDie = OrigUnit.getUnitDIE(false); @@ -1301,7 +1301,7 @@ /// Construct the output DIE tree by cloning the DIEs we /// chose to keep above. If there are no valid relocs, then there's /// nothing to clone/emit. - void cloneAllCompileUnits(DWARFContextInMemory &DwarfContext); + void cloneAllCompileUnits(DWARFContext &DwarfContext); private: typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec; @@ -2873,7 +2873,8 @@ DWARFDebugRangeList RangeList; const auto &FunctionRanges = Unit.getFunctionRanges(); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); - DWARFDataExtractor RangeExtractor(OrigDwarf.getRangeSection(), + DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(), + OrigDwarf.getDWARFObj().getRangeSection(), OrigDwarf.isLittleEndian(), AddressSize); auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; DWARFUnit &OrigUnit = Unit.getOrigUnit(); @@ -2984,9 +2985,9 @@ // Parse the original line info for the unit. DWARFDebugLine::LineTable LineTable; uint32_t StmtOffset = *StmtList; - DWARFDataExtractor LineExtractor(OrigDwarf.getLineSection(), - OrigDwarf.isLittleEndian(), - Unit.getOrigUnit().getAddressByteSize()); + DWARFDataExtractor LineExtractor( + OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(), + OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); LineTable.parse(LineExtractor, &StmtOffset); // This vector is the output line table. @@ -3086,7 +3087,7 @@ LineTable.Prologue.OpcodeBase > 13) reportWarning("line table parameters mismatch. Cannot emit."); else { - StringRef LineData = OrigDwarf.getLineSection().Data; + StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data; MCDwarfLineTableParams Params; Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; Params.DWARF2LineBase = LineTable.Prologue.LineBase; @@ -3112,7 +3113,7 @@ void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO, DWARFContext &OrigDwarf, unsigned AddrSize) { - StringRef FrameData = OrigDwarf.getDebugFrameSection(); + StringRef FrameData = OrigDwarf.getDWARFObj().getDebugFrameSection(); if (FrameData.empty()) return; @@ -3323,9 +3324,9 @@ std::unique_ptr Unit; // Setup access to the debug info. - DWARFContextInMemory DwarfContext(*ErrOrObj); + auto DwarfContext = DWARFContext::create(*ErrOrObj); RelocationManager RelocMgr(*this); - for (const auto &CU : DwarfContext.compile_units()) { + for (const auto &CU : DwarfContext->compile_units()) { auto CUDie = CU->getUnitDIE(false); // Recursively get all modules imported by this one. if (!registerModuleReference(CUDie, *CU, ModuleMap, Indent)) { @@ -3365,11 +3366,10 @@ std::vector> CompileUnits; CompileUnits.push_back(std::move(Unit)); DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options) - .cloneAllCompileUnits(DwarfContext); + .cloneAllCompileUnits(*DwarfContext); } -void DwarfLinker::DIECloner::cloneAllCompileUnits( - DWARFContextInMemory &DwarfContext) { +void DwarfLinker::DIECloner::cloneAllCompileUnits(DWARFContext &DwarfContext) { if (!Linker.Streamer) return; @@ -3438,11 +3438,11 @@ } // Setup access to the debug info. - DWARFContextInMemory DwarfContext(*ErrOrObj); - startDebugObject(DwarfContext, *Obj); + auto DwarfContext = DWARFContext::create(*ErrOrObj); + startDebugObject(*DwarfContext, *Obj); // In a first phase, just read in the debug info and load all clang modules. - for (const auto &CU : DwarfContext.compile_units()) { + for (const auto &CU : DwarfContext->compile_units()) { auto CUDie = CU->getUnitDIE(false); if (Options.Verbose) { outs() << "Input compilation unit:"; @@ -3476,9 +3476,9 @@ RelocMgr.resetValidRelocs(); if (RelocMgr.hasValidRelocs()) DIECloner(*this, RelocMgr, DIEAlloc, Units, Options) - .cloneAllCompileUnits(DwarfContext); + .cloneAllCompileUnits(*DwarfContext); if (!Options.NoOutput && !Units.empty()) - patchFrameInfoForObject(*Obj, DwarfContext, + patchFrameInfoForObject(*Obj, *DwarfContext, Units[0]->getOrigUnit().getAddressByteSize()); // Clean-up before starting working on the next object. Index: tools/llvm-dwarfdump/llvm-dwarfdump.cpp =================================================================== --- tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -94,7 +94,7 @@ } static void DumpObjectFile(ObjectFile &Obj, Twine Filename) { - std::unique_ptr DICtx(new DWARFContextInMemory(Obj)); + std::unique_ptr DICtx = DWARFContext::create(Obj); outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName() << "\n\n"; @@ -131,8 +131,8 @@ } static bool VerifyObjectFile(ObjectFile &Obj, Twine Filename) { - std::unique_ptr DICtx(new DWARFContextInMemory(Obj)); - + std::unique_ptr DICtx = DWARFContext::create(Obj); + // Verify the DWARF and exit with non-zero exit status if verification // fails. raw_ostream &stream = Quiet ? nulls() : outs(); Index: tools/llvm-objdump/MachODump.cpp =================================================================== --- tools/llvm-objdump/MachODump.cpp +++ tools/llvm-objdump/MachODump.cpp @@ -1275,7 +1275,7 @@ printWeakBindTable(MachOOF); if (DwarfDumpType != DIDT_Null) { - std::unique_ptr DICtx(new DWARFContextInMemory(*MachOOF)); + std::unique_ptr DICtx = DWARFContext::create(*MachOOF); // Dump the complete DWARF structure. DIDumpOptions DumpOpts; DumpOpts.DumpType = DwarfDumpType; @@ -6594,7 +6594,7 @@ } // Setup the DIContext - diContext.reset(new DWARFContextInMemory(*DbgObj)); + diContext = DWARFContext::create(*DbgObj); } if (FilterSections.size() == 0) Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -62,8 +62,8 @@ #include #include #include -#include #include +#include using namespace llvm; using namespace object; @@ -2081,7 +2081,7 @@ if (PrintFaultMaps) printFaultMaps(o); if (DwarfDumpType != DIDT_Null) { - std::unique_ptr DICtx(new DWARFContextInMemory(*o)); + std::unique_ptr DICtx = DWARFContext::create(*o); // Dump the complete DWARF structure. DIDumpOptions DumpOpts; DumpOpts.DumpType = DwarfDumpType; Index: tools/llvm-rtdyld/llvm-rtdyld.cpp =================================================================== --- tools/llvm-rtdyld/llvm-rtdyld.cpp +++ tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -324,8 +324,8 @@ } } - std::unique_ptr Context( - new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get())); + std::unique_ptr Context = + DWARFContext::create(*SymbolObj, LoadedObjInfo.get()); std::vector> SymAddr = object::computeSymbolSizes(*SymbolObj); Index: tools/obj2yaml/dwarf2yaml.cpp =================================================================== --- tools/obj2yaml/dwarf2yaml.cpp +++ tools/obj2yaml/dwarf2yaml.cpp @@ -24,7 +24,7 @@ InitialLength.TotalLength64 = Data.getU64(&Offset); } -void dumpDebugAbbrev(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { +void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) { auto AbbrevSetPtr = DCtx.getDebugAbbrev(); if (AbbrevSetPtr) { for (auto AbbrvDeclSet : *AbbrevSetPtr) { @@ -48,8 +48,8 @@ } } -void dumpDebugStrings(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { - StringRef RemainingTable = DCtx.getStringSection(); +void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) { + StringRef RemainingTable = DCtx.getDWARFObj().getStringSection(); while (RemainingTable.size() > 0) { auto SymbolPair = RemainingTable.split('\0'); RemainingTable = SymbolPair.second; @@ -57,8 +57,9 @@ } } -void dumpDebugARanges(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { - DataExtractor ArangesData(DCtx.getARangeSection(), DCtx.isLittleEndian(), 0); +void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) { + DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(), + DCtx.isLittleEndian(), 0); uint32_t Offset = 0; DWARFDebugArangeSet Set; @@ -79,7 +80,7 @@ } } -void dumpPubSection(DWARFContextInMemory &DCtx, DWARFYAML::PubSection &Y, +void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y, StringRef Section) { DataExtractor PubSectionData(Section, DCtx.isLittleEndian(), 0); uint32_t Offset = 0; @@ -97,21 +98,22 @@ } } -void dumpDebugPubSections(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { +void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) { + const DWARFObj &D = DCtx.getDWARFObj(); Y.PubNames.IsGNUStyle = false; - dumpPubSection(DCtx, Y.PubNames, DCtx.getPubNamesSection()); + dumpPubSection(DCtx, Y.PubNames, D.getPubNamesSection()); Y.PubTypes.IsGNUStyle = false; - dumpPubSection(DCtx, Y.PubTypes, DCtx.getPubTypesSection()); + dumpPubSection(DCtx, Y.PubTypes, D.getPubTypesSection()); Y.GNUPubNames.IsGNUStyle = true; - dumpPubSection(DCtx, Y.GNUPubNames, DCtx.getGnuPubNamesSection()); + dumpPubSection(DCtx, Y.GNUPubNames, D.getGnuPubNamesSection()); Y.GNUPubTypes.IsGNUStyle = true; - dumpPubSection(DCtx, Y.GNUPubTypes, DCtx.getGnuPubTypesSection()); + dumpPubSection(DCtx, Y.GNUPubTypes, D.getGnuPubTypesSection()); } -void dumpDebugInfo(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { +void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) { for (const auto &CU : DCtx.compile_units()) { DWARFYAML::Unit NewUnit; NewUnit.Length.setLength(CU->getLength()); @@ -235,7 +237,7 @@ return true; } -void dumpDebugLines(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { +void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) { for (const auto &CU : DCtx.compile_units()) { auto CUDIE = CU->getUnitDIE(); if (!CUDIE) @@ -243,8 +245,8 @@ if (auto StmtOffset = dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) { DWARFYAML::LineTable DebugLines; - DataExtractor LineData(DCtx.getLineSection().Data, DCtx.isLittleEndian(), - CU->getAddressByteSize()); + DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data, + DCtx.isLittleEndian(), CU->getAddressByteSize()); uint32_t Offset = *StmtOffset; dumpInitialLength(LineData, Offset, DebugLines.Length); uint64_t LineTableLength = DebugLines.Length.getLength(); @@ -344,7 +346,7 @@ } } -std::error_code dwarf2yaml(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { +std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) { dumpDebugAbbrev(DCtx, Y); dumpDebugStrings(DCtx, Y); dumpDebugARanges(DCtx, Y); Index: tools/obj2yaml/macho2yaml.cpp =================================================================== --- tools/obj2yaml/macho2yaml.cpp +++ tools/obj2yaml/macho2yaml.cpp @@ -35,9 +35,9 @@ ArrayRef OpcodeBuffer, bool Lazy = false); void dumpExportTrie(std::unique_ptr &Y); void dumpSymbols(std::unique_ptr &Y); - void dumpDebugAbbrev(DWARFContextInMemory &DCtx, + void dumpDebugAbbrev(DWARFContext &DCtx, std::unique_ptr &Y); - void dumpDebugStrings(DWARFContextInMemory &DCtx, + void dumpDebugStrings(DWARFContext &DCtx, std::unique_ptr &Y); public: @@ -187,8 +187,8 @@ dumpLoadCommands(Y); dumpLinkEdit(Y); - DWARFContextInMemory DICtx(Obj); - if (auto Err = dwarf2yaml(DICtx, Y->DWARF)) + std::unique_ptr DICtx = DWARFContext::create(Obj); + if (auto Err = dwarf2yaml(*DICtx, Y->DWARF)) return errorCodeToError(Err); return std::move(Y); } Index: tools/obj2yaml/obj2yaml.h =================================================================== --- tools/obj2yaml/obj2yaml.h +++ tools/obj2yaml/obj2yaml.h @@ -29,13 +29,12 @@ // Forward decls for dwarf2yaml namespace llvm { -class DWARFContextInMemory; +class DWARFContext; namespace DWARFYAML { struct Data; } } -std::error_code dwarf2yaml(llvm::DWARFContextInMemory &DCtx, - llvm::DWARFYAML::Data &Y); +std::error_code dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); #endif Index: unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp =================================================================== --- unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -14,8 +14,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/Config/llvm-config.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Config/llvm-config.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" @@ -28,8 +28,8 @@ #include "llvm/ObjectYAML/DWARFYAML.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/TargetSelect.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" #include @@ -228,10 +228,10 @@ MemoryBufferRef FileBuffer(FileBytes, "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); auto DieDG = U->getUnitDIE(false); EXPECT_TRUE(DieDG.isValid()); @@ -458,12 +458,12 @@ MemoryBufferRef FileBuffer(FileBytes, "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto DieDG = U->getUnitDIE(false); @@ -629,13 +629,13 @@ MemoryBufferRef FileBuffer(FileBytes, "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 2u); - DWARFCompileUnit *U1 = DwarfContext.getCompileUnitAtIndex(0); - DWARFCompileUnit *U2 = DwarfContext.getCompileUnitAtIndex(1); + DWARFCompileUnit *U1 = DwarfContext->getCompileUnitAtIndex(0); + DWARFCompileUnit *U2 = DwarfContext->getCompileUnitAtIndex(1); // Get the compile unit DIE is valid. auto Unit1DieDG = U1->getUnitDIE(false); @@ -837,12 +837,12 @@ MemoryBufferRef FileBuffer(FileBytes, "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto DieDG = U->getUnitDIE(false); @@ -1012,12 +1012,12 @@ MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto CUDie = U->getUnitDIE(false); @@ -1127,12 +1127,12 @@ MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto CUDie = U->getUnitDIE(false); @@ -1188,12 +1188,13 @@ auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto CUDie = U->getUnitDIE(false); @@ -1235,12 +1236,12 @@ MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto CUDie = U->getUnitDIE(false); @@ -1299,12 +1300,12 @@ MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto CUDie = U->getUnitDIE(false); @@ -1505,12 +1506,12 @@ MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); // Verify the number of compile units is correct. - uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. auto CUDie = U->getUnitDIE(false); @@ -1568,8 +1569,8 @@ MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); - DWARFContextInMemory DwarfContext(*Obj.get()); - DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + std::unique_ptr DwarfContext = DWARFContext::create(*Obj.get()); + DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0); EXPECT_TRUE((bool)U); const auto *Abbrevs = U->getAbbreviations(); @@ -1708,10 +1709,11 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); - VerifyError(DwarfContext, "error: DW_FORM_ref4 CU offset 0x00001234 is " - "invalid (must be less than CU size of " - "0x0000001a):"); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + VerifyError(*DwarfContext, "error: DW_FORM_ref4 CU offset 0x00001234 is " + "invalid (must be less than CU size of " + "0x0000001a):"); } TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddr) { @@ -1756,8 +1758,9 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); - VerifyError(DwarfContext, + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + VerifyError(*DwarfContext, "error: DW_FORM_ref_addr offset beyond .debug_info bounds:"); } @@ -1792,8 +1795,9 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); - VerifyError(DwarfContext, + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + VerifyError(*DwarfContext, "error: DW_AT_ranges offset is beyond .debug_ranges bounds:"); } @@ -1828,9 +1832,10 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); VerifyError( - DwarfContext, + *DwarfContext, "error: DW_AT_stmt_list offset is beyond .debug_line bounds: 0x00001000"); } @@ -1860,8 +1865,9 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); - VerifyError(DwarfContext, + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + VerifyError(*DwarfContext, "error: DW_FORM_strp offset beyond .debug_str bounds:"); } @@ -1907,9 +1913,10 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); VerifyError( - DwarfContext, + *DwarfContext, "error: invalid DIE reference 0x00000011. Offset is in between DIEs:"); } @@ -1977,9 +1984,10 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); - VerifyError(DwarfContext, "error: .debug_line[0x00000000] row[1] decreases " - "in address from previous row:"); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + VerifyError(*DwarfContext, "error: .debug_line[0x00000000] row[1] decreases " + "in address from previous row:"); } TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) { @@ -2048,9 +2056,10 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); - VerifyError(DwarfContext, "error: .debug_line[0x00000000][1] has invalid " - "file index 5 (valid values are [1,1]):"); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + VerifyError(*DwarfContext, "error: .debug_line[0x00000000][1] has invalid " + "file index 5 (valid values are [1,1]):"); } TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) { @@ -2128,10 +2137,12 @@ )"; auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata); ASSERT_TRUE((bool)ErrOrSections); - DWARFContextInMemory DwarfContext(*ErrOrSections, 8); - VerifyError(DwarfContext, "error: two compile unit DIEs, 0x0000000b and " - "0x0000001f, have the same DW_AT_stmt_list section " - "offset:"); + std::unique_ptr DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + VerifyError(*DwarfContext, + "error: two compile unit DIEs, 0x0000000b and " + "0x0000001f, have the same DW_AT_stmt_list section " + "offset:"); } TEST(DWARFDebugInfo, TestErrorReportingPolicy) { @@ -2161,20 +2172,22 @@ // DWARFContextInMemory // to parse whole file and find both two errors we know about. int Errors = 0; - DWARFContextInMemory Ctx1(*Obj.get(), nullptr, [&](Error E) { - ++Errors; - consumeError(std::move(E)); - return ErrorPolicy::Continue; - }); + std::unique_ptr Ctx1 = + DWARFContext::create(*Obj.get(), nullptr, [&](Error E) { + ++Errors; + consumeError(std::move(E)); + return ErrorPolicy::Continue; + }); EXPECT_TRUE(Errors == 2); // Case 2: error handler stops parsing of object after first error. Errors = 0; - DWARFContextInMemory Ctx2(*Obj.get(), nullptr, [&](Error E) { - ++Errors; - consumeError(std::move(E)); - return ErrorPolicy::Halt; - }); + std::unique_ptr Ctx2 = + DWARFContext::create(*Obj.get(), nullptr, [&](Error E) { + ++Errors; + consumeError(std::move(E)); + return ErrorPolicy::Halt; + }); EXPECT_TRUE(Errors == 1); }