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,317 @@ namespace llvm { namespace object { -/// Base class for object file relocation visitors. -class RelocVisitor { -public: - explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {} +static int64_t getELFAddend(RelocationRef R) { + Expected AddendOrErr = ELFRelocationRef(R).getAddend(); + handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { + report_fatal_error(EI.message()); + }); + return *AddendOrErr; +} - // 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); +static Optional visitX86_64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitAarch64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitAarch64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitBpf(RelocationRef R, uint64_t S, int64_t A); +static Optional visitMips64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitPPC64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitSystemz(RelocationRef R, uint64_t S, int64_t A); +static Optional visitSparc64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitAmdgpu(RelocationRef R, uint64_t S, int64_t A); +static Optional visitX86(RelocationRef R, uint64_t S, int64_t A); +static Optional visitPPC32(RelocationRef R, uint64_t S, int64_t A); +static Optional visitARM(RelocationRef R, uint64_t S, int64_t A); +static Optional visitAVR(RelocationRef R, uint64_t S, int64_t A); +static Optional visitLanai(RelocationRef R, uint64_t S, int64_t A); +static Optional visitMips32(RelocationRef R, uint64_t S, int64_t A); +static Optional visitSparc32(RelocationRef R, uint64_t S, int64_t A); +static Optional visitHexagon(RelocationRef R, uint64_t S, int64_t A); +static Optional visitCOFFX86(RelocationRef R, uint64_t S, int64_t A); +static Optional visitCOFFX86_64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitMachOX86_64(RelocationRef R, uint64_t S, int64_t A); +static Optional visitWasm32(RelocationRef R, uint64_t S, int64_t A); - HasError = true; - return 0; - } +using RelocationResolver = Optional (*)(RelocationRef R, uint64_t S, + int64_t A); - bool error() { return HasError; } +static RelocationResolver getRelocationResolver(const ObjectFile &Obj) { + if (Obj.isCOFF()) + return Obj.getBytesInAddress() == 4 ? visitCOFFX86 : visitCOFFX86_64; -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()) { + if (Obj.isELF()) { + if (Obj.getBytesInAddress() == 8) { + switch (Obj.getArch()) { case Triple::x86_64: - return visitX86_64(Rel, R, Value); + return visitX86_64; case Triple::aarch64: case Triple::aarch64_be: - return visitAarch64(Rel, R, Value); + return visitAarch64; case Triple::bpfel: case Triple::bpfeb: - return visitBpf(Rel, R, Value); + return visitBpf; case Triple::mips64el: case Triple::mips64: - return visitMips64(Rel, R, Value); + return visitMips64; case Triple::ppc64le: case Triple::ppc64: - return visitPPC64(Rel, R, Value); + return visitPPC64; case Triple::systemz: - return visitSystemz(Rel, R, Value); + return visitSystemz; case Triple::sparcv9: - return visitSparc64(Rel, R, Value); + return visitSparc64; case Triple::amdgcn: - return visitAmdgpu(Rel, R, Value); + return visitAmdgpu; default: - HasError = true; - return 0; + return nullptr; } } // 32-bit object file - assert(ObjToVisit.getBytesInAddress() == 4 && + assert(Obj.getBytesInAddress() == 4 && "Invalid word size in object file"); - switch (ObjToVisit.getArch()) { + switch (Obj.getArch()) { case Triple::x86: - return visitX86(Rel, R, Value); + return visitX86; case Triple::ppc: - return visitPPC32(Rel, R, Value); + return visitPPC32; case Triple::arm: case Triple::armeb: - return visitARM(Rel, R, Value); + return visitARM; case Triple::avr: - return visitAVR(Rel, R, Value); + return visitAVR; case Triple::lanai: - return visitLanai(Rel, R, Value); + return visitLanai; case Triple::mipsel: case Triple::mips: - return visitMips32(Rel, R, Value); + return visitMips32; case Triple::sparc: - return visitSparc32(Rel, R, Value); + return visitSparc32; case Triple::hexagon: - return visitHexagon(Rel, R, Value); + return visitHexagon; default: - HasError = true; - return 0; + return nullptr; } } - int64_t getELFAddend(RelocationRef R) { - Expected AddendOrErr = ELFRelocationRef(R).getAddend(); - handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { - report_fatal_error(EI.message()); - }); - return *AddendOrErr; - } + if (Obj.isMachO()) + return Obj.getArch() == Triple::x86_64 ? visitMachOX86_64 : nullptr; - uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { + if (Obj.isWasm()) + return Obj.getArch() == Triple::wasm32 ? visitWasm32 : nullptr; + + return nullptr; +} + + 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()) { - 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; + 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: - break; + return None; } - 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; + 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; + } } - 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; - } + 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; } - HasError = true; - return 0; + return None; } -}; + } // 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