Index: lib/DebugInfo/DWARFCompileUnit.h =================================================================== --- lib/DebugInfo/DWARFCompileUnit.h +++ lib/DebugInfo/DWARFCompileUnit.h @@ -14,12 +14,13 @@ namespace llvm { -class DWARFCompileUnit : public DWARFUnit { +class DWARFCompileUnit : public DWARFUnitImpl { public: DWARFCompileUnit(DWARFContext& Context, const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, StringRef SS, StringRef SOS, - StringRef AOS, const RelocAddrMap *M, bool LE) - : DWARFUnit(Context, DA, IS, RS, SS, SOS, AOS, M, LE) {} + StringRef AOS, const RelocAddrMap *M, bool LE, + const UnitVector &Units) + : DWARFUnitImpl(Context, DA, IS, RS, SS, SOS, AOS, M, LE, Units) {} void dump(raw_ostream &OS); // VTable anchor. ~DWARFCompileUnit() override; Index: lib/DebugInfo/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARFContext.cpp +++ lib/DebugInfo/DWARFContext.cpp @@ -321,7 +321,7 @@ std::unique_ptr CU(new DWARFCompileUnit(*this, getDebugAbbrev(), getInfoSection().Data, getRangeSection(), getStringSection(), StringRef(), getAddrSection(), - &getInfoSection().Relocs, isLittleEndian())); + &getInfoSection().Relocs, isLittleEndian(), CUs)); if (!CU->extract(DIData, &offset)) { break; } @@ -341,7 +341,7 @@ std::unique_ptr TU(new DWARFTypeUnit(*this, getDebugAbbrev(), I.second.Data, getRangeSection(), getStringSection(), StringRef(), getAddrSection(), - &I.second.Relocs, isLittleEndian())); + &I.second.Relocs, isLittleEndian(), TUs)); if (!TU->extract(DIData, &offset)) break; TUs.push_back(std::move(TU)); @@ -360,7 +360,7 @@ std::unique_ptr DWOCU(new DWARFCompileUnit(*this, getDebugAbbrevDWO(), getInfoDWOSection().Data, getRangeDWOSection(), getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), - &getInfoDWOSection().Relocs, isLittleEndian())); + &getInfoDWOSection().Relocs, isLittleEndian(), DWOCUs)); if (!DWOCU->extract(DIData, &offset)) { break; } @@ -380,7 +380,7 @@ std::unique_ptr TU(new DWARFTypeUnit(*this, getDebugAbbrevDWO(), I.second.Data, getRangeDWOSection(), getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), - &I.second.Relocs, isLittleEndian())); + &I.second.Relocs, isLittleEndian(), DWOTUs)); if (!TU->extract(DIData, &offset)) break; DWOTUs.push_back(std::move(TU)); @@ -389,33 +389,9 @@ } } -namespace { - struct OffsetComparator { - - bool operator()(const std::unique_ptr &LHS, - const std::unique_ptr &RHS) const { - return LHS->getOffset() < RHS->getOffset(); - } - bool operator()(const std::unique_ptr &LHS, - uint32_t RHS) const { - return LHS->getOffset() < RHS; - } - bool operator()(uint32_t LHS, - const std::unique_ptr &RHS) const { - return LHS < RHS->getOffset(); - } - }; -} - DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { parseCompileUnits(); - - std::unique_ptr *CU = - std::lower_bound(CUs.begin(), CUs.end(), Offset, OffsetComparator()); - if (CU != CUs.end()) { - return CU->get(); - } - return nullptr; + return DWARFUnit::getUnitForOffset(CUs, Offset); } DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { Index: lib/DebugInfo/DWARFTypeUnit.h =================================================================== --- lib/DebugInfo/DWARFTypeUnit.h +++ lib/DebugInfo/DWARFTypeUnit.h @@ -14,15 +14,16 @@ namespace llvm { -class DWARFTypeUnit : public DWARFUnit { +class DWARFTypeUnit : public DWARFUnitImpl { private: uint64_t TypeHash; uint32_t TypeOffset; public: DWARFTypeUnit(DWARFContext &Context, const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, StringRef SS, StringRef SOS, - StringRef AOS, const RelocAddrMap *M, bool LE) - : DWARFUnit(Context, DA, IS, RS, SS, SOS, AOS, M, LE) {} + StringRef AOS, const RelocAddrMap *M, bool LE, + const UnitVector &Units) + : DWARFUnitImpl(Context, DA, IS, RS, SS, SOS, AOS, M, LE, Units) {} uint32_t getHeaderSize() const override { return DWARFUnit::getHeaderSize() + 12; } Index: lib/DebugInfo/DWARFUnit.h =================================================================== --- lib/DebugInfo/DWARFUnit.h +++ lib/DebugInfo/DWARFUnit.h @@ -136,6 +136,10 @@ /// chain is valid as long as parsed compile unit DIEs are not cleared. DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); + /// Returns the Unit that contains the given section offset in the + /// same section this Unit originated from. + virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; + private: /// Size in bytes of the .debug_info data associated with this compile unit. size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } @@ -161,8 +165,57 @@ /// encompassing the provided address. The pointer is alive as long as parsed /// compile unit DIEs are not cleared. const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); + + template + struct UnitOffsetComparator { + bool operator()(const std::unique_ptr &LHS, + const std::unique_ptr &RHS) const { + return LHS->getNextUnitOffset() < RHS->getNextUnitOffset(); + } + bool operator()(const std::unique_ptr &LHS, + uint32_t RHS) const { + return LHS->getNextUnitOffset() < RHS; + } + bool operator()(uint32_t LHS, + const std::unique_ptr &RHS) const { + return LHS < RHS->getNextUnitOffset(); + } + }; + +public: + template + static UnitType * + getUnitForOffset(const SmallVectorImpl> &Units, + uint32_t Offset) { + auto *Unit = std::upper_bound(Units.begin(), Units.end(), Offset, + UnitOffsetComparator()); + if (Unit != Units.end()) + return Unit->get(); + return nullptr; + } }; -} +/// Small wrapper for the DWARFUnit class that allows to embed a +/// reference to the list of all the units extracted from the same +/// section as this one. +template +class DWARFUnitImpl : public DWARFUnit { +protected: + typedef SmallVectorImpl> UnitVector; + /// This is a reference to the vector of all units extracted from + /// the same section as this. The vector is owned by the DWARFContext. + const UnitVector &Units; + +public: + DWARFUnitImpl(DWARFContext& Context, const DWARFDebugAbbrev *DA, StringRef IS, + StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, + const RelocAddrMap *M, bool LE, const UnitVector &Units) + : DWARFUnit(Context, DA, IS, RS, SS, SOS, AOS, M, LE), Units(Units) {} + DWARFUnit *getUnitForOffset(uint32_t Offset) const override { + return DWARFUnit::getUnitForOffset(Units, Offset); + } +}; + +} #endif