Index: include/llvm/DebugInfo/DWARF/DWARFRelocMap.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFRelocMap.h +++ include/llvm/DebugInfo/DWARF/DWARFRelocMap.h @@ -10,6 +10,7 @@ #define LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/Object/RelocVisitor.h" #include namespace llvm { @@ -18,7 +19,9 @@ /// Section index is -1LL if relocation points to absolute symbol. struct RelocAddrEntry { uint64_t SectionIndex; - uint64_t Value; + object::RelocationRef Reloc; + object::RelocationResolver Resolver; + uint64_t S; }; /// In place of applying the relocations to the data we've read from disk we use Index: include/llvm/Object/RelocVisitor.h =================================================================== --- include/llvm/Object/RelocVisitor.h +++ include/llvm/Object/RelocVisitor.h @@ -31,330 +31,295 @@ namespace llvm { namespace object { -/// Base class for object file relocation visitors. -class RelocVisitor { -public: - explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {} - - // TODO: Should handle multiple applied relocations via either passing in the - // previously computed value or just count paired relocations as a single - // visit. - uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) { - if (isa(ObjToVisit)) - return visitELF(Rel, R, Value); - if (isa(ObjToVisit)) - return visitCOFF(Rel, R, Value); - if (isa(ObjToVisit)) - return visitMachO(Rel, R, Value); - if (isa(ObjToVisit)) - return visitWasm(Rel, R, Value); - - HasError = true; - return 0; - } - - bool error() { return HasError; } - -private: - const ObjectFile &ObjToVisit; - bool HasError = false; - - uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file - switch (ObjToVisit.getArch()) { - case Triple::x86_64: - return visitX86_64(Rel, R, Value); - case Triple::aarch64: - case Triple::aarch64_be: - return visitAarch64(Rel, R, Value); - case Triple::bpfel: - case Triple::bpfeb: - return visitBpf(Rel, R, Value); - case Triple::mips64el: - case Triple::mips64: - return visitMips64(Rel, R, Value); - case Triple::ppc64le: - case Triple::ppc64: - return visitPPC64(Rel, R, Value); - case Triple::systemz: - return visitSystemz(Rel, R, Value); - case Triple::sparcv9: - return visitSparc64(Rel, R, Value); - case Triple::amdgcn: - return visitAmdgpu(Rel, R, Value); - default: - HasError = true; - return 0; - } - } - - // 32-bit object file - assert(ObjToVisit.getBytesInAddress() == 4 && - "Invalid word size in object file"); - - switch (ObjToVisit.getArch()) { - case Triple::x86: - return visitX86(Rel, R, Value); - case Triple::ppc: - return visitPPC32(Rel, R, Value); - case Triple::arm: - case Triple::armeb: - return visitARM(Rel, R, Value); - case Triple::avr: - return visitAVR(Rel, R, Value); - case Triple::lanai: - return visitLanai(Rel, R, Value); - case Triple::mipsel: - case Triple::mips: - return visitMips32(Rel, R, Value); - case Triple::sparc: - return visitSparc32(Rel, R, Value); - case Triple::hexagon: - return visitHexagon(Rel, R, Value); - default: - HasError = true; - return 0; - } - } - - int64_t getELFAddend(RelocationRef R) { - Expected AddendOrErr = ELFRelocationRef(R).getAddend(); - handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { - report_fatal_error(EI.message()); - }); - return *AddendOrErr; - } - - uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { +static int64_t getELFAddend(RelocationRef R) { + Expected AddendOrErr = ELFRelocationRef(R).getAddend(); + handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { + report_fatal_error(EI.message()); + }); + return *AddendOrErr; +} + + static Optional visitX86_64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_X86_64_NONE: - return 0; + return A; case ELF::R_X86_64_64: case ELF::R_X86_64_DTPOFF32: case ELF::R_X86_64_DTPOFF64: - return Value + getELFAddend(R); + return S + getELFAddend(R); case ELF::R_X86_64_PC32: - return Value + getELFAddend(R) - R.getOffset(); + return S + getELFAddend(R) - R.getOffset(); case ELF::R_X86_64_32: case ELF::R_X86_64_32S: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; + return (S + getELFAddend(R)) & 0xFFFFFFFF; } - HasError = true; - return 0; + return None; } - uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitAarch64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_AARCH64_ABS32: { - int64_t Res = Value + getELFAddend(R); + int64_t Res = S + getELFAddend(R); if (Res < INT32_MIN || Res > UINT32_MAX) - HasError = true; + return None; return static_cast(Res); } case ELF::R_AARCH64_ABS64: - return Value + getELFAddend(R); + return S + getELFAddend(R); } - HasError = true; - return 0; + return None; } - uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitBpf(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_BPF_64_32: - return Value & 0xFFFFFFFF; + return S & 0xFFFFFFFF; case ELF::R_BPF_64_64: - return Value; + return S; } - HasError = true; - return 0; + return None; } - uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitMips64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_MIPS_32: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; + return (S + getELFAddend(R)) & 0xFFFFFFFF; case ELF::R_MIPS_64: - return Value + getELFAddend(R); + return S + getELFAddend(R); case ELF::R_MIPS_TLS_DTPREL64: - return Value + getELFAddend(R) - 0x8000; + return S + getELFAddend(R) - 0x8000; } - HasError = true; - return 0; + return None; } - uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitPPC64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_PPC64_ADDR32: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; + return (S + getELFAddend(R)) & 0xFFFFFFFF; case ELF::R_PPC64_ADDR64: - return Value + getELFAddend(R); + return S + getELFAddend(R); } - HasError = true; - return 0; + return None; } - uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitSystemz(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_390_32: { - int64_t Res = Value + getELFAddend(R); + int64_t Res = S + getELFAddend(R); if (Res < INT32_MIN || Res > UINT32_MAX) - HasError = true; + return None; return static_cast(Res); } case ELF::R_390_64: - return Value + getELFAddend(R); + return S + getELFAddend(R); } - HasError = true; - return 0; + return None; } - uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitSparc64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_SPARC_32: case ELF::R_SPARC_64: case ELF::R_SPARC_UA32: case ELF::R_SPARC_UA64: - return Value + getELFAddend(R); + return S + getELFAddend(R); } - HasError = true; - return 0; + return None; } - uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitAmdgpu(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_AMDGPU_ABS32: case ELF::R_AMDGPU_ABS64: - return Value + getELFAddend(R); + return S + getELFAddend(R); } - HasError = true; - return 0; + return None; } - uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + static Optional visitX86(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { case ELF::R_386_NONE: - return 0; + return A; case ELF::R_386_32: - return Value; + return S + A; case ELF::R_386_PC32: - return Value - R.getOffset(); + return S - R.getOffset() + A; } - HasError = true; - return 0; + return None; } - uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_PPC_ADDR32) - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - HasError = true; - return 0; + static Optional visitPPC32(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_PPC_ADDR32) + return (S + getELFAddend(R)) & 0xFFFFFFFF; + return None; } - uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_ARM_ABS32) { - if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX) - HasError = true; - return static_cast(Value); + static Optional visitARM(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_ARM_ABS32) { + if ((int64_t)S < INT32_MIN || (int64_t)S > UINT32_MAX) + return None; + return static_cast(S); } - HasError = true; - return 0; + return None; } - uint64_t visitAVR(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_AVR_16) { - return (Value + getELFAddend(R)) & 0xFFFF; - } else if (Rel == ELF::R_AVR_32) { - return (Value + getELFAddend(R)) & 0xFFFFFFFF; + static Optional visitAVR(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case ELF::R_AVR_16: + return (S + getELFAddend(R)) & 0xFFFF; + case ELF::R_AVR_32: + return (S + getELFAddend(R)) & 0xFFFFFFFF; } - HasError = true; - return 0; + return None; } - uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_LANAI_32) - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - HasError = true; - return 0; + static Optional visitLanai(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_LANAI_32) + return (S + getELFAddend(R)) & 0xFFFFFFFF; + return None; } - uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) { + static Optional visitMips32(RelocationRef R, uint64_t S, int64_t A) { // FIXME: Take in account implicit addends to get correct results. + uint32_t Rel = R.getType(); if (Rel == ELF::R_MIPS_32) - return Value & 0xFFFFFFFF; + return (S + A) & 0xFFFFFFFF; if (Rel == ELF::R_MIPS_TLS_DTPREL32) - return Value & 0xFFFFFFFF; - HasError = true; - return 0; + return (S + A) & 0xFFFFFFFF; + return None; } - uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) { + static Optional visitSparc32(RelocationRef R, uint64_t S, int64_t A) { + uint32_t Rel = R.getType(); if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) - return Value + getELFAddend(R); - HasError = true; - return 0; + return S + getELFAddend(R); + return None; } - uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_HEX_32) - return Value + getELFAddend(R); - HasError = true; - return 0; + static Optional visitHexagon(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == ELF::R_HEX_32) + return S + getELFAddend(R); + return None; } - uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (ObjToVisit.getArch()) { + static Optional visitCOFFX86(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case COFF::IMAGE_REL_I386_SECREL: + case COFF::IMAGE_REL_I386_DIR32: + return static_cast(S + A); + default: + return None; + } + } + + static Optional visitCOFFX86_64(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case COFF::IMAGE_REL_AMD64_SECREL: + return static_cast(S + A); + case COFF::IMAGE_REL_AMD64_ADDR64: + return S + A; + default: + return None; + } + } + + static Optional visitMachOX86_64(RelocationRef R, uint64_t S, int64_t A) { + if (R.getType() == MachO::X86_64_RELOC_UNSIGNED) + return S; + return None; + } + + static Optional visitWasm32(RelocationRef R, uint64_t S, int64_t A) { + switch (R.getType()) { + case wasm::R_WASM_FUNCTION_INDEX_LEB: + case wasm::R_WASM_TABLE_INDEX_SLEB: + case wasm::R_WASM_TABLE_INDEX_I32: + case wasm::R_WASM_MEMORY_ADDR_LEB: + case wasm::R_WASM_MEMORY_ADDR_SLEB: + case wasm::R_WASM_MEMORY_ADDR_I32: + case wasm::R_WASM_TYPE_INDEX_LEB: + case wasm::R_WASM_GLOBAL_INDEX_LEB: + case wasm::R_WASM_FUNCTION_OFFSET_I32: + case wasm::R_WASM_SECTION_OFFSET_I32: + case wasm::R_WASM_EVENT_INDEX_LEB: + // For wasm section, its offset at 0 -- ignoring Value + return 0; + } + return None; + } + + +using RelocationResolver = Optional (*)(RelocationRef R, uint64_t S, + int64_t A); + +static RelocationResolver getRelocationResolver(const ObjectFile &Obj) { + if (Obj.isCOFF()) + return Obj.getBytesInAddress() == 4 ? visitCOFFX86 : visitCOFFX86_64; + + if (Obj.isELF()) { + if (Obj.getBytesInAddress() == 8) { + switch (Obj.getArch()) { + case Triple::x86_64: + return visitX86_64; + case Triple::aarch64: + case Triple::aarch64_be: + return visitAarch64; + case Triple::bpfel: + case Triple::bpfeb: + return visitBpf; + case Triple::mips64el: + case Triple::mips64: + return visitMips64; + case Triple::ppc64le: + case Triple::ppc64: + return visitPPC64; + case Triple::systemz: + return visitSystemz; + case Triple::sparcv9: + return visitSparc64; + case Triple::amdgcn: + return visitAmdgpu; + default: + return nullptr; + } + } + + // 32-bit object file + assert(Obj.getBytesInAddress() == 4 && + "Invalid word size in object file"); + + switch (Obj.getArch()) { case Triple::x86: - switch (Rel) { - case COFF::IMAGE_REL_I386_SECREL: - case COFF::IMAGE_REL_I386_DIR32: - return static_cast(Value); - } - break; - case Triple::x86_64: - switch (Rel) { - case COFF::IMAGE_REL_AMD64_SECREL: - return static_cast(Value); - case COFF::IMAGE_REL_AMD64_ADDR64: - return Value; - } - break; + return visitX86; + case Triple::ppc: + return visitPPC32; + case Triple::arm: + case Triple::armeb: + return visitARM; + case Triple::avr: + return visitAVR; + case Triple::lanai: + return visitLanai; + case Triple::mipsel: + case Triple::mips: + return visitMips32; + case Triple::sparc: + return visitSparc32; + case Triple::hexagon: + return visitHexagon; default: - break; + return nullptr; } - HasError = true; - return 0; } - uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getArch() == Triple::x86_64 && - Rel == MachO::X86_64_RELOC_UNSIGNED) - return Value; - HasError = true; - return 0; - } + if (Obj.isMachO()) + return Obj.getArch() == Triple::x86_64 ? visitMachOX86_64 : nullptr; - uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getArch() == Triple::wasm32) { - switch (Rel) { - case wasm::R_WASM_FUNCTION_INDEX_LEB: - case wasm::R_WASM_TABLE_INDEX_SLEB: - case wasm::R_WASM_TABLE_INDEX_I32: - case wasm::R_WASM_MEMORY_ADDR_LEB: - case wasm::R_WASM_MEMORY_ADDR_SLEB: - case wasm::R_WASM_MEMORY_ADDR_I32: - case wasm::R_WASM_TYPE_INDEX_LEB: - case wasm::R_WASM_GLOBAL_INDEX_LEB: - case wasm::R_WASM_FUNCTION_OFFSET_I32: - case wasm::R_WASM_SECTION_OFFSET_I32: - case wasm::R_WASM_EVENT_INDEX_LEB: - // For wasm section, its offset at 0 -- ignoring Value - return 0; - } - } - HasError = true; - return 0; - } -}; + if (Obj.isWasm()) + return Obj.getArch() == Triple::wasm32 ? visitWasm32 : nullptr; + + return nullptr; +} } // end namespace object } // end namespace llvm Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1494,6 +1494,7 @@ // Symbol to [address, section index] cache mapping. std::map AddrCache; + RelocationResolver Resolver = getRelocationResolver(Obj); for (const RelocationRef &Reloc : Section.relocations()) { // FIXME: it's not clear how to correctly handle scattered // relocations. @@ -1508,9 +1509,12 @@ continue; } - object::RelocVisitor V(Obj); - uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); - if (V.error()) { + if (Optional Val = + Resolver ? Resolver(Reloc, SymInfoOrErr->Address, 0) : None) { + Map->try_emplace(Reloc.getOffset(), + RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc, + Resolver, SymInfoOrErr->Address}); + } else { SmallString<32> Type; Reloc.getTypeName(Type); ErrorPolicy EP = HandleError( @@ -1518,10 +1522,7 @@ errorCodeToError(object_error::parse_failed))); if (EP == ErrorPolicy::Halt) return; - continue; } - RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; - Map->insert({Reloc.getOffset(), Rel}); } } Index: lib/DebugInfo/DWARF/DWARFDataExtractor.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -18,12 +18,13 @@ *SecNdx = -1ULL; if (!Section) return getUnsigned(Off, Size); - Optional Rel = Obj->find(*Section, *Off); - if (!Rel) - return getUnsigned(Off, Size); + Optional E = Obj->find(*Section, *Off); + uint64_t A = getUnsigned(Off, Size); + if (!E) + return A; if (SecNdx) - *SecNdx = Rel->SectionIndex; - return getUnsigned(Off, Size) + Rel->Value; + *SecNdx = E->SectionIndex; + return E->Resolver(E->Reloc, E->S, A).getValueOr(A); } Optional