Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -43,17 +43,11 @@ class MemoryBuffer; class raw_ostream; -// In place of applying the relocations to the data we've read from disk we use -// a separate mapping table to the side and checking that at locations in the -// dwarf where we expect relocated values. This adds a bit of complexity to the -// dwarf parsing/extraction at the benefit of not allocating memory for the -// entire size of the debug info sections. -typedef DenseMap> RelocAddrMap; - /// Reads a value from data extractor and applies a relocation to the result if /// one exists for the given offset. uint64_t getRelocatedValue(const DataExtractor &Data, uint32_t Size, - uint32_t *Off, const RelocAddrMap *Relocs); + uint32_t *Off, const RelocAddrMap *Relocs, + uint64_t *SecNdx = nullptr); /// DWARFContext /// This data structure is the top level entity that deals with dwarf debug Index: include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -22,8 +22,14 @@ class raw_ostream; +struct DWARFAddress { + uint64_t LowPC; + uint64_t HighPC; + uint64_t SecNdx; +}; + /// DWARFAddressRangesVector - represents a set of absolute address ranges. -typedef std::vector> DWARFAddressRangesVector; +typedef std::vector DWARFAddressRangesVector; class DWARFDebugRangeList { public: @@ -39,6 +45,8 @@ // address past the end of the address range. The ending address must // be greater than or equal to the beginning address. uint64_t EndAddress; + // A section index this range belongs to. + uint64_t SecNdx; // The end of any given range list is marked by an end of list entry, // which consists of a 0 for the beginning address offset Index: include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDie.h +++ include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -195,8 +195,9 @@ /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. /// Returns true if both attributes are present. - bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const; - + bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, + uint64_t &SecNdx) const; + /// Get the address ranges for this DIE. /// /// Get the hi/low PC range if both attributes are available or exrtracts the Index: include/llvm/DebugInfo/DWARF/DWARFFormValue.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -47,6 +47,7 @@ const char *cstr; }; const uint8_t *data = nullptr; + uint64_t SecNdx; // Section index for reference forms. }; dwarf::Form Form; // Form for this value. @@ -58,6 +59,7 @@ dwarf::Form getForm() const { return Form; } uint64_t getRawUValue() const { return Value.uval; } + uint64_t getSecNdxValue() const { return Value.SecNdx; } void setForm(dwarf::Form F) { Form = F; } void setUValue(uint64_t V) { Value.uval = V; } void setSValue(int64_t V) { Value.sval = V; } Index: include/llvm/DebugInfo/DWARF/DWARFRelocMap.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFRelocMap.h +++ include/llvm/DebugInfo/DWARF/DWARFRelocMap.h @@ -16,7 +16,17 @@ namespace llvm { -typedef DenseMap> RelocAddrMap; +struct RelocAddrEntry { + uint64_t SecNdx; + int64_t Value; +}; + +// In place of applying the relocations to the data we've read from disk we use +// a separate mapping table to the side and checking that at locations in the +// dwarf where we expect relocated values. This adds a bit of complexity to the +// dwarf parsing/extraction at the benefit of not allocating memory for the +// entire size of the debug info sections. +typedef DenseMap RelocAddrMap; } // end namespace llvm Index: include/llvm/Object/COFF.h =================================================================== --- include/llvm/Object/COFF.h +++ include/llvm/Object/COFF.h @@ -782,6 +782,7 @@ std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -235,6 +235,7 @@ std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; @@ -646,6 +647,15 @@ } template +uint64_t ELFObjectFile::getSectionIndex(DataRefImpl Sec) const { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return 0; + const Elf_Shdr *First = (*SectionsOrErr).begin(); + return getSection(Sec) - First; +} + +template uint64_t ELFObjectFile::getSectionSize(DataRefImpl Sec) const { return getSection(Sec)->sh_size; } Index: include/llvm/Object/MachO.h =================================================================== --- include/llvm/Object/MachO.h +++ include/llvm/Object/MachO.h @@ -290,6 +290,7 @@ std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; Index: include/llvm/Object/ObjectFile.h =================================================================== --- include/llvm/Object/ObjectFile.h +++ include/llvm/Object/ObjectFile.h @@ -95,6 +95,7 @@ std::error_code getName(StringRef &Result) const; uint64_t getAddress() const; + uint64_t getIndex() const; uint64_t getSize() const; std::error_code getContents(StringRef &Result) const; @@ -222,6 +223,7 @@ virtual std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0; virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; virtual std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const = 0; @@ -393,6 +395,10 @@ return OwningObject->getSectionAddress(SectionPimpl); } +inline uint64_t SectionRef::getIndex() const { + return OwningObject->getSectionIndex(SectionPimpl); +} + inline uint64_t SectionRef::getSize() const { return OwningObject->getSectionSize(SectionPimpl); } Index: include/llvm/Object/Wasm.h =================================================================== --- include/llvm/Object/Wasm.h +++ include/llvm/Object/Wasm.h @@ -119,6 +119,7 @@ std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -60,13 +60,16 @@ typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; uint64_t llvm::getRelocatedValue(const DataExtractor &Data, uint32_t Size, - uint32_t *Off, const RelocAddrMap *Relocs) { + uint32_t *Off, const RelocAddrMap *Relocs, + uint64_t *SecNdx) { if (!Relocs) return Data.getUnsigned(Off, Size); RelocAddrMap::const_iterator AI = Relocs->find(*Off); if (AI == Relocs->end()) return Data.getUnsigned(Off, Size); - return Data.getUnsigned(Off, Size) + AI->second.second; + if (SecNdx) + *SecNdx = AI->second.SecNdx; + return Data.getUnsigned(Off, Size) + AI->second.Value; } static void dumpAccelSection(raw_ostream &OS, StringRef Name, @@ -902,12 +905,12 @@ inconvertibleErrorCode()); } -/// Returns the address of symbol relocation used against. Used for futher -/// relocations computation. Symbol's section load address is taken in account if -/// LoadedObjectInfo interface is provided. -static Expected getSymbolAddress(const object::ObjectFile &Obj, - const RelocationRef &Reloc, - const LoadedObjectInfo *L) { +/// Returns the address of symbol relocation used against and a section index. +/// Used for futher relocations computation. Symbol's section load address is +/// taken in account if LoadedObjectInfo interface is provided. +static Expected> +getSymbolInfo(const object::ObjectFile &Obj, const RelocationRef &Reloc, + const LoadedObjectInfo *L) { uint64_t Ret = 0; object::section_iterator RSec = Obj.section_end(); object::symbol_iterator Sym = Reloc.getSymbol(); @@ -943,7 +946,7 @@ if (L && RSec != Obj.section_end()) if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec)) Ret += SectionLoadAddress - RSec->getAddress(); - return Ret; + return std::make_pair(Ret, RSec->getIndex()); } static bool isRelocScattered(const object::ObjectFile &Obj, @@ -1083,14 +1086,16 @@ if (isRelocScattered(Obj, Reloc)) continue; - Expected SymAddrOrErr = getSymbolAddress(Obj, Reloc, L); - if (!SymAddrOrErr) { - errs() << toString(SymAddrOrErr.takeError()) << '\n'; + Expected> SymInfoOrErr = + getSymbolInfo(Obj, Reloc, L); + if (!SymInfoOrErr) { + errs() << toString(SymInfoOrErr.takeError()) << '\n'; continue; } object::RelocVisitor V(Obj); - object::RelocToApply R(V.visit(Reloc.getType(), Reloc, *SymAddrOrErr)); + object::RelocToApply R( + V.visit(Reloc.getType(), Reloc, (*SymInfoOrErr).first)); if (V.error()) { SmallString<32> Name; Reloc.getTypeName(Name); @@ -1114,7 +1119,9 @@ << " at " << format("%p", Address) << " with width " << format("%d", R.Width) << "\n"); - Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); + + llvm::RelocAddrEntry Rel = {(*SymInfoOrErr).second, R.Value}; + Map->insert(std::make_pair(Address, Rel)); } } } Index: lib/DebugInfo/DWARF/DWARFDebugAranges.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -54,9 +54,8 @@ if (ParsedCUOffsets.insert(CUOffset).second) { DWARFAddressRangesVector CURanges; CU->collectAddressRanges(CURanges); - for (const auto &R : CURanges) { - appendRange(CUOffset, R.first, R.second); - } + for (const auto &R : CURanges) + appendRange(CUOffset, R.LowPC, R.HighPC); } } Index: lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -35,8 +35,8 @@ while (true) { RangeListEntry entry; uint32_t prev_offset = *offset_ptr; - entry.StartAddress = - getRelocatedValue(data, AddressSize, offset_ptr, &Relocs); + entry.StartAddress = getRelocatedValue(data, AddressSize, offset_ptr, + &Relocs, &entry.SecNdx); entry.EndAddress = getRelocatedValue(data, AddressSize, offset_ptr, &Relocs); @@ -66,12 +66,11 @@ DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { - if (RLE.isBaseAddressSelectionEntry(AddressSize)) { + if (RLE.isBaseAddressSelectionEntry(AddressSize)) BaseAddress = RLE.EndAddress; - } else { - Res.push_back(std::make_pair(BaseAddress + RLE.StartAddress, - BaseAddress + RLE.EndAddress)); - } + else + Res.push_back({BaseAddress + RLE.StartAddress, + BaseAddress + RLE.EndAddress, RLE.SecNdx}); } return Res; } Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -60,8 +60,8 @@ OS << '\n'; OS.indent(Indent); OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", - AddressSize*2, Range.first, - AddressSize*2, Range.second); + AddressSize*2, Range.LowPC, + AddressSize*2, Range.HighPC); } } @@ -211,13 +211,16 @@ return None; } -bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const { - auto LowPcAddr = toAddress(find(DW_AT_low_pc)); +bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, + uint64_t &SecNdx) const { + auto F = find(DW_AT_low_pc); + auto LowPcAddr = toAddress(F); if (!LowPcAddr) return false; if (auto HighPcAddr = getHighPC(*LowPcAddr)) { LowPC = *LowPcAddr; HighPC = *HighPcAddr; + SecNdx = F->getSecNdxValue(); return true; } return false; @@ -228,10 +231,10 @@ if (isNULL()) return DWARFAddressRangesVector(); // Single range specified by low/high PC. - uint64_t LowPC, HighPC; - if (getLowAndHighPC(LowPC, HighPC)) { - return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); - } + uint64_t LowPC, HighPC, SecNdx; + if (getLowAndHighPC(LowPC, HighPC, SecNdx)) + return {{LowPC, HighPC, SecNdx}}; + // Multiple ranges from .debug_ranges section. auto RangesOffset = toSectionOffset(find(DW_AT_ranges)); if (RangesOffset) { @@ -257,7 +260,7 @@ bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { for (const auto& R : getAddressRanges()) { - if (R.first <= Address && Address < R.second) + if (R.LowPC <= Address && Address < R.HighPC) return true; } return false; Index: lib/DebugInfo/DWARF/DWARFFormValue.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -333,8 +333,8 @@ return false; uint16_t AddrSize = (Form == DW_FORM_addr) ? U->getAddressByteSize() : U->getRefAddrByteSize(); - Value.uval = - getRelocatedValue(Data, AddrSize, OffsetPtr, U->getRelocMap()); + Value.uval = getRelocatedValue(Data, AddrSize, OffsetPtr, + U->getRelocMap(), &Value.SecNdx); break; } case DW_FORM_exprloc: Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -349,18 +349,18 @@ if (Die.isSubroutineDIE()) { for (const auto &R : Die.getAddressRanges()) { // Ignore 0-sized ranges. - if (R.first == R.second) + if (R.LowPC == R.HighPC) continue; - auto B = AddrDieMap.upper_bound(R.first); - if (B != AddrDieMap.begin() && R.first < (--B)->second.first) { + auto B = AddrDieMap.upper_bound(R.LowPC); + if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { // The range is a sub-range of existing ranges, we need to split the // existing range. - if (R.second < B->second.first) - AddrDieMap[R.second] = B->second; - if (R.first > B->first) - AddrDieMap[B->first].first = R.first; + if (R.HighPC < B->second.first) + AddrDieMap[R.HighPC] = B->second; + if (R.LowPC > B->first) + AddrDieMap[B->first].first = R.LowPC; } - AddrDieMap[R.first] = std::make_pair(R.second, Die); + AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); } } // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to Index: lib/Object/COFFObjectFile.cpp =================================================================== --- lib/Object/COFFObjectFile.cpp +++ lib/Object/COFFObjectFile.cpp @@ -293,6 +293,11 @@ return Result; } +uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const { + // TODO: COFFObjectFile::getSectionIndex() not implemented + return -1LL; +} + uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { return getSectionSize(toSec(Ref)); } Index: lib/Object/MachOObjectFile.cpp =================================================================== --- lib/Object/MachOObjectFile.cpp +++ lib/Object/MachOObjectFile.cpp @@ -1820,6 +1820,11 @@ return getSection(Sec).addr; } +uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { + // TODO: COFFObjectFile::getSectionIndex() not implemented + return -1LL; +} + uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { // In the case if a malformed Mach-O file where the section offset is past // the end of the file or some part of the section size is past the end of Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -743,6 +743,11 @@ uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } +uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { + // TODO: COFFObjectFile::getSectionIndex() not implemented + return -1LL; +} + uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { const WasmSection &S = Sections[Sec.d.a]; return S.Content.size();