Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -45,10 +45,67 @@ class MemoryBuffer; class raw_ostream; +// 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() {} + 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; +}; + /// 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 +152,16 @@ /// and store them in DWOTUs. void parseDWOTypeUnits(); +protected: + const DWARFObj &DObj; + public: - DWARFContext() : DIContext(CK_DWARF) {} + DWARFContext(const DWARFObj &DObj) : DIContext(CK_DWARF), DObj(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,49 +284,7 @@ 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; } @@ -289,62 +309,7 @@ /// 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); + std::unique_ptr DObjP; /// Function used to handle default error reporting policy. Prints a error /// message and returns Continue, so DWARF context ignores the error. @@ -359,61 +324,6 @@ 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 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/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); }); @@ -796,7 +799,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; @@ -906,208 +909,355 @@ return MachObj->isRelocationScattered(RelocInfo); } -Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec, - StringRef Name, StringRef &Data) { - if (!Decompressor::isCompressed(Sec)) - return Error::success(); +ErrorPolicy DWARFContextInMemory::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(); + + return Error::success(); + } - // 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. +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; - // Map platform specific debug section names to DWARF standard section - // names. - Name = Obj.mapDebugSectionName(Name); + 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; + } - 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; + // 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; + } -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); + // 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 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); + } +}; + +DWARFContextInMemory::DWARFContextInMemory( + const object::ObjectFile &Obj, const LoadedObjectInfo *L, + function_ref HandleError) + : DWARFContext(*new DWARFObjInMemory(Obj, L, HandleError)) { + DObjP.reset(&this->DObj); } -void DWARFContextInMemory::anchor() {} +DWARFContextInMemory::DWARFContextInMemory( + const StringMap> &Sections, uint8_t AddrSize, + bool IsLittleEndian) + : DWARFContext(*new DWARFObjInMemory(Sections, AddrSize, IsLittleEndian)) { + DObjP.reset(&this->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 @@ -31,7 +31,7 @@ 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 >= DCtx.getDWARFObj().getRangeSection().Data.size()) { ++NumDebugInfoErrors; OS << "error: DW_AT_ranges offset is beyond .debug_ranges " "bounds:\n"; @@ -48,7 +48,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 >= DCtx.getDWARFObj().getLineSection().Data.size()) { ++NumDebugInfoErrors; OS << "error: DW_AT_stmt_list offset is beyond .debug_line " "bounds: " @@ -71,6 +71,7 @@ void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue) { + const DWARFObj &D = DCtx.getDWARFObj(); const auto Form = AttrValue.Value.getForm(); switch (Form) { case DW_FORM_ref1: @@ -107,7 +108,7 @@ Optional RefVal = AttrValue.Value.getAsReference(); assert(RefVal); if (RefVal) { - if (*RefVal >= DCtx.getInfoSection().Data.size()) { + if (*RefVal >= D.getInfoSection().Data.size()) { ++NumDebugInfoErrors; OS << "error: DW_FORM_ref_addr offset beyond .debug_info " "bounds:\n"; @@ -124,7 +125,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 >= D.getStringSection().size()) { ++NumDebugInfoErrors; OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n"; Die.dump(OS, 0); @@ -189,7 +190,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) @@ -279,10 +280,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: 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); @@ -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; Index: tools/obj2yaml/dwarf2yaml.cpp =================================================================== --- tools/obj2yaml/dwarf2yaml.cpp +++ tools/obj2yaml/dwarf2yaml.cpp @@ -49,7 +49,7 @@ } void dumpDebugStrings(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { - StringRef RemainingTable = DCtx.getStringSection(); + StringRef RemainingTable = DCtx.getDWARFObj().getStringSection(); while (RemainingTable.size() > 0) { auto SymbolPair = RemainingTable.split('\0'); RemainingTable = SymbolPair.second; @@ -58,7 +58,8 @@ } void dumpDebugARanges(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { - DataExtractor ArangesData(DCtx.getARangeSection(), DCtx.isLittleEndian(), 0); + DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(), + DCtx.isLittleEndian(), 0); uint32_t Offset = 0; DWARFDebugArangeSet Set; @@ -98,17 +99,18 @@ } void dumpDebugPubSections(DWARFContextInMemory &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) { @@ -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();