[lib/Object] - Generalize the RelocationResolver API.

This allows to reuse the RelocationResolver from the code
that doesn't want to deal with `RelocationRef` class.

I am going to use it in llvm-readobj. See the description
of D91530 for more details.

Differential revision: https://reviews.llvm.org/D91533
This commit is contained in:
Georgii Rymar 2020-11-12 15:16:57 +03:00
parent 4cb510d284
commit 9a99d23a1b
9 changed files with 217 additions and 141 deletions

View File

@ -77,18 +77,23 @@ template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) {
namespace {
template <class RelTy> struct LLDRelocationResolver {
// In the ELF ABIs, S sepresents the value of the symbol in the relocation
// entry. For Rela, the addend is stored as part of the relocation entry.
static uint64_t resolve(object::RelocationRef ref, uint64_t s,
uint64_t /* A */) {
return s + ref.getRawDataRefImpl().p;
// entry. For Rela, the addend is stored as part of the relocation entry and
// is provided by the `findAux` method.
// In resolve() methods, the `type` and `offset` arguments would always be 0,
// because we don't set an owning object for the `RelocationRef` instance that
// we create in `findAux()`.
static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s,
uint64_t /*locData*/, int64_t addend) {
return s + addend;
}
};
template <class ELFT> struct LLDRelocationResolver<Elf_Rel_Impl<ELFT, false>> {
// For Rel, the addend A is supplied by the caller.
static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t s,
uint64_t a) {
return s + a;
// For Rel, the addend is extracted from the relocated location and is
// supplied by the caller.
static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s,
uint64_t locData, int64_t /*addend*/) {
return s + locData;
}
};
} // namespace

View File

@ -313,14 +313,6 @@ protected:
uint64_t getSectionOffset(DataRefImpl Sec) const override;
StringRef getRelocationTypeName(uint32_t Type) const;
/// Get the relocation section that contains \a Rel.
const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
auto RelSecOrErr = EF.getSection(Rel.d.a);
if (!RelSecOrErr)
report_fatal_error(errorToErrorCode(RelSecOrErr.takeError()).message());
return *RelSecOrErr;
}
DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const {
DataRefImpl DRI;
if (!SymTable) {
@ -419,6 +411,14 @@ public:
return *Ret;
}
/// Get the relocation section that contains \a Rel.
const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
auto RelSecOrErr = EF.getSection(Rel.d.a);
if (!RelSecOrErr)
report_fatal_error(errorToErrorCode(RelSecOrErr.takeError()).message());
return *RelSecOrErr;
}
const Elf_Shdr *getSection(DataRefImpl Sec) const {
return reinterpret_cast<const Elf_Shdr *>(Sec.p);
}

View File

@ -31,11 +31,17 @@
namespace llvm {
namespace object {
using RelocationResolver = uint64_t (*)(RelocationRef R, uint64_t S, uint64_t A);
using SupportsRelocation = bool (*)(uint64_t);
using RelocationResolver = uint64_t (*)(uint64_t Type, uint64_t Offset,
uint64_t S, uint64_t LocData,
int64_t Addend);
std::pair<bool (*)(uint64_t), RelocationResolver>
std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile &Obj);
uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
uint64_t S, uint64_t LocData);
} // end namespace object
} // end namespace llvm

View File

@ -1780,7 +1780,7 @@ public:
// Symbol to [address, section index] cache mapping.
std::map<SymbolRef, SymInfo> AddrCache;
bool (*Supports)(uint64_t);
SupportsRelocation Supports;
RelocationResolver Resolver;
std::tie(Supports, Resolver) = getRelocationResolver(Obj);
for (const RelocationRef &Reloc : Section.relocations()) {

View File

@ -53,14 +53,16 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
ErrorAsOutParameter ErrAsOut(Err);
Optional<RelocAddrEntry> E = Obj->find(*Section, *Off);
uint64_t A = getUnsigned(Off, Size, Err);
uint64_t LocData = getUnsigned(Off, Size, Err);
if (!E || (Err && *Err))
return A;
return LocData;
if (SecNdx)
*SecNdx = E->SectionIndex;
uint64_t R = E->Resolver(E->Reloc, E->SymbolValue, A);
uint64_t R =
object::resolveRelocation(E->Resolver, E->Reloc, E->SymbolValue, LocData);
if (E->Reloc2)
R = E->Resolver(*E->Reloc2, E->SymbolValue2, R);
R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2, R);
return R;
}

View File

@ -39,20 +39,21 @@ static bool supportsX86_64(uint64_t Type) {
}
}
static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t Addend) {
switch (Type) {
case ELF::R_X86_64_NONE:
return A;
return LocData;
case ELF::R_X86_64_64:
case ELF::R_X86_64_DTPOFF32:
case ELF::R_X86_64_DTPOFF64:
return S + getELFAddend(R);
return S + Addend;
case ELF::R_X86_64_PC32:
case ELF::R_X86_64_PC64:
return S + getELFAddend(R) - R.getOffset();
return S + Addend - Offset;
case ELF::R_X86_64_32:
case ELF::R_X86_64_32S:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
default:
llvm_unreachable("Invalid relocation type");
}
@ -70,16 +71,17 @@ static bool supportsAArch64(uint64_t Type) {
}
}
static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_AARCH64_ABS32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
case ELF::R_AARCH64_ABS64:
return S + getELFAddend(R);
return S + Addend;
case ELF::R_AARCH64_PREL32:
return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
return (S + Addend - Offset) & 0xFFFFFFFF;
case ELF::R_AARCH64_PREL64:
return S + getELFAddend(R) - R.getOffset();
return S + Addend - Offset;
default:
llvm_unreachable("Invalid relocation type");
}
@ -95,12 +97,13 @@ static bool supportsBPF(uint64_t Type) {
}
}
static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case ELF::R_BPF_64_32:
return (S + A) & 0xFFFFFFFF;
return (S + LocData) & 0xFFFFFFFF;
case ELF::R_BPF_64_64:
return S + A;
return S + LocData;
default:
llvm_unreachable("Invalid relocation type");
}
@ -118,16 +121,17 @@ static bool supportsMips64(uint64_t Type) {
}
}
static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_MIPS_32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
case ELF::R_MIPS_64:
return S + getELFAddend(R);
return S + Addend;
case ELF::R_MIPS_TLS_DTPREL64:
return S + getELFAddend(R) - 0x8000;
return S + Addend - 0x8000;
case ELF::R_MIPS_PC32:
return S + getELFAddend(R) - R.getOffset();
return S + Addend - Offset;
default:
llvm_unreachable("Invalid relocation type");
}
@ -143,12 +147,13 @@ static bool supportsMSP430(uint64_t Type) {
}
}
static uint64_t resolveMSP430(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_MSP430_32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
case ELF::R_MSP430_16_BYTE:
return (S + getELFAddend(R)) & 0xFFFF;
return (S + Addend) & 0xFFFF;
default:
llvm_unreachable("Invalid relocation type");
}
@ -166,16 +171,17 @@ static bool supportsPPC64(uint64_t Type) {
}
}
static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_PPC64_ADDR32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
case ELF::R_PPC64_ADDR64:
return S + getELFAddend(R);
return S + Addend;
case ELF::R_PPC64_REL32:
return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
return (S + Addend - Offset) & 0xFFFFFFFF;
case ELF::R_PPC64_REL64:
return S + getELFAddend(R) - R.getOffset();
return S + Addend - Offset;
default:
llvm_unreachable("Invalid relocation type");
}
@ -191,12 +197,13 @@ static bool supportsSystemZ(uint64_t Type) {
}
}
static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_390_32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
case ELF::R_390_64:
return S + getELFAddend(R);
return S + Addend;
default:
llvm_unreachable("Invalid relocation type");
}
@ -214,13 +221,14 @@ static bool supportsSparc64(uint64_t Type) {
}
}
static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_SPARC_32:
case ELF::R_SPARC_64:
case ELF::R_SPARC_UA32:
case ELF::R_SPARC_UA64:
return S + getELFAddend(R);
return S + Addend;
default:
llvm_unreachable("Invalid relocation type");
}
@ -236,11 +244,12 @@ static bool supportsAmdgpu(uint64_t Type) {
}
}
static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_AMDGPU_ABS32:
case ELF::R_AMDGPU_ABS64:
return S + getELFAddend(R);
return S + Addend;
default:
llvm_unreachable("Invalid relocation type");
}
@ -257,14 +266,15 @@ static bool supportsX86(uint64_t Type) {
}
}
static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case ELF::R_386_NONE:
return A;
return LocData;
case ELF::R_386_32:
return S + A;
return S + LocData;
case ELF::R_386_PC32:
return S - R.getOffset() + A;
return S - Offset + LocData;
default:
llvm_unreachable("Invalid relocation type");
}
@ -280,12 +290,13 @@ static bool supportsPPC32(uint64_t Type) {
}
}
static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_PPC_ADDR32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
case ELF::R_PPC_REL32:
return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
return (S + Addend - Offset) & 0xFFFFFFFF;
}
llvm_unreachable("Invalid relocation type");
}
@ -300,12 +311,13 @@ static bool supportsARM(uint64_t Type) {
}
}
static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case ELF::R_ARM_ABS32:
return (S + A) & 0xFFFFFFFF;
return (S + LocData) & 0xFFFFFFFF;
case ELF::R_ARM_REL32:
return (S + A - R.getOffset()) & 0xFFFFFFFF;
return (S + LocData - Offset) & 0xFFFFFFFF;
}
llvm_unreachable("Invalid relocation type");
}
@ -320,12 +332,13 @@ static bool supportsAVR(uint64_t Type) {
}
}
static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
switch (Type) {
case ELF::R_AVR_16:
return (S + getELFAddend(R)) & 0xFFFF;
return (S + Addend) & 0xFFFF;
case ELF::R_AVR_32:
return (S + getELFAddend(R)) & 0xFFFFFFFF;
return (S + Addend) & 0xFFFFFFFF;
default:
llvm_unreachable("Invalid relocation type");
}
@ -335,9 +348,10 @@ static bool supportsLanai(uint64_t Type) {
return Type == ELF::R_LANAI_32;
}
static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
if (R.getType() == ELF::R_LANAI_32)
return (S + getELFAddend(R)) & 0xFFFFFFFF;
static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
if (Type == ELF::R_LANAI_32)
return (S + Addend) & 0xFFFFFFFF;
llvm_unreachable("Invalid relocation type");
}
@ -351,13 +365,13 @@ static bool supportsMips32(uint64_t Type) {
}
}
static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
// FIXME: Take in account implicit addends to get correct results.
uint32_t Rel = R.getType();
if (Rel == ELF::R_MIPS_32)
return (S + A) & 0xFFFFFFFF;
if (Rel == ELF::R_MIPS_TLS_DTPREL32)
return (S + A) & 0xFFFFFFFF;
if (Type == ELF::R_MIPS_32)
return (S + LocData) & 0xFFFFFFFF;
if (Type == ELF::R_MIPS_TLS_DTPREL32)
return (S + LocData) & 0xFFFFFFFF;
llvm_unreachable("Invalid relocation type");
}
@ -371,20 +385,21 @@ static bool supportsSparc32(uint64_t Type) {
}
}
static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
uint32_t Rel = R.getType();
if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
return S + getELFAddend(R);
return A;
static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t Addend) {
if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
return S + Addend;
return LocData;
}
static bool supportsHexagon(uint64_t Type) {
return Type == ELF::R_HEX_32;
}
static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
if (R.getType() == ELF::R_HEX_32)
return S + getELFAddend(R);
static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t /*LocData*/, int64_t Addend) {
if (Type == ELF::R_HEX_32)
return S + Addend;
llvm_unreachable("Invalid relocation type");
}
@ -410,15 +425,17 @@ static bool supportsRISCV(uint64_t Type) {
}
}
static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
int64_t RA = getELFAddend(R);
switch (R.getType()) {
static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t Addend) {
int64_t RA = Addend;
uint64_t A = LocData;
switch (Type) {
case ELF::R_RISCV_NONE:
return A;
return LocData;
case ELF::R_RISCV_32:
return (S + RA) & 0xFFFFFFFF;
case ELF::R_RISCV_32_PCREL:
return (S + RA - R.getOffset()) & 0xFFFFFFFF;
return (S + RA - Offset) & 0xFFFFFFFF;
case ELF::R_RISCV_64:
return S + RA;
case ELF::R_RISCV_SET6:
@ -456,11 +473,12 @@ static bool supportsCOFFX86(uint64_t Type) {
}
}
static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case COFF::IMAGE_REL_I386_SECREL:
case COFF::IMAGE_REL_I386_DIR32:
return (S + A) & 0xFFFFFFFF;
return (S + LocData) & 0xFFFFFFFF;
default:
llvm_unreachable("Invalid relocation type");
}
@ -476,12 +494,13 @@ static bool supportsCOFFX86_64(uint64_t Type) {
}
}
static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case COFF::IMAGE_REL_AMD64_SECREL:
return (S + A) & 0xFFFFFFFF;
return (S + LocData) & 0xFFFFFFFF;
case COFF::IMAGE_REL_AMD64_ADDR64:
return S + A;
return S + LocData;
default:
llvm_unreachable("Invalid relocation type");
}
@ -497,11 +516,12 @@ static bool supportsCOFFARM(uint64_t Type) {
}
}
static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case COFF::IMAGE_REL_ARM_SECREL:
case COFF::IMAGE_REL_ARM_ADDR32:
return (S + A) & 0xFFFFFFFF;
return (S + LocData) & 0xFFFFFFFF;
default:
llvm_unreachable("Invalid relocation type");
}
@ -517,12 +537,13 @@ static bool supportsCOFFARM64(uint64_t Type) {
}
}
static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case COFF::IMAGE_REL_ARM64_SECREL:
return (S + A) & 0xFFFFFFFF;
return (S + LocData) & 0xFFFFFFFF;
case COFF::IMAGE_REL_ARM64_ADDR64:
return S + A;
return S + LocData;
default:
llvm_unreachable("Invalid relocation type");
}
@ -532,8 +553,9 @@ static bool supportsMachOX86_64(uint64_t Type) {
return Type == MachO::X86_64_RELOC_UNSIGNED;
}
static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
if (Type == MachO::X86_64_RELOC_UNSIGNED)
return S;
llvm_unreachable("Invalid relocation type");
}
@ -573,8 +595,9 @@ static bool supportsWasm64(uint64_t Type) {
}
}
static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t /*Addend*/) {
switch (Type) {
case wasm::R_WASM_FUNCTION_INDEX_LEB:
case wasm::R_WASM_TABLE_INDEX_SLEB:
case wasm::R_WASM_TABLE_INDEX_I32:
@ -589,14 +612,15 @@ static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
case wasm::R_WASM_GLOBAL_INDEX_I32:
case wasm::R_WASM_TABLE_NUMBER_LEB:
// For wasm section, its offset at 0 -- ignoring Value
return A;
return LocData;
default:
llvm_unreachable("Invalid relocation type");
}
}
static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) {
switch (R.getType()) {
static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
uint64_t LocData, int64_t Addend) {
switch (Type) {
case wasm::R_WASM_MEMORY_ADDR_LEB64:
case wasm::R_WASM_MEMORY_ADDR_SLEB64:
case wasm::R_WASM_MEMORY_ADDR_I64:
@ -604,13 +628,13 @@ static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) {
case wasm::R_WASM_TABLE_INDEX_I64:
case wasm::R_WASM_FUNCTION_OFFSET_I64:
// For wasm section, its offset at 0 -- ignoring Value
return A;
return LocData;
default:
return resolveWasm32(R, S, A);
return resolveWasm32(Type, Offset, S, LocData, Addend);
}
}
std::pair<bool (*)(uint64_t), RelocationResolver>
std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile &Obj) {
if (Obj.isCOFF()) {
switch (Obj.getArch()) {
@ -701,5 +725,38 @@ getRelocationResolver(const ObjectFile &Obj) {
llvm_unreachable("Invalid object file");
}
uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
uint64_t S, uint64_t LocData) {
if (const ObjectFile *Obj = R.getObject()) {
int64_t Addend = 0;
if (Obj->isELF()) {
auto GetRelSectionType = [&]() -> unsigned {
if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
};
if (GetRelSectionType() == ELF::SHT_RELA)
Addend = getELFAddend(R);
}
return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
}
// Sometimes the caller might want to use its own specific implementation of
// the resolver function. E.g. this is used by LLD when it resolves debug
// relocations and assumes that all of them have the same computation (S + A).
// The relocation R has no owner object in this case and we don't need to
// provide Type and Offset fields. It is also assumed the DataRefImpl.p
// contains the addend, provided by the caller.
return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
R.getRawDataRefImpl().p);
}
} // namespace object
} // namespace llvm

View File

@ -109,28 +109,32 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
return static_cast<uint32_t>(0);
}(ObjFile.getBinary());
bool (*SupportsRelocation)(uint64_t);
object::SupportsRelocation Supports;
object::RelocationResolver Resolver;
std::tie(SupportsRelocation, Resolver) =
std::tie(Supports, Resolver) =
object::getRelocationResolver(*ObjFile.getBinary());
for (const object::SectionRef &Section : Sections) {
for (const object::RelocationRef &Reloc : Section.relocations()) {
if (ObjFile.getBinary()->getArch() == Triple::arm) {
if (SupportsRelocation && SupportsRelocation(Reloc.getType())) {
if (Supports && Supports(Reloc.getType())) {
Expected<uint64_t> ValueOrErr = Reloc.getSymbol()->getValue();
if (!ValueOrErr)
return ValueOrErr.takeError();
Relocs.insert({Reloc.getOffset(), Resolver(Reloc, *ValueOrErr, 0)});
Relocs.insert(
{Reloc.getOffset(),
object::resolveRelocation(Resolver, Reloc, *ValueOrErr, 0)});
}
} else if (SupportsRelocation && SupportsRelocation(Reloc.getType())) {
} else if (Supports && Supports(Reloc.getType())) {
auto AddendOrErr = object::ELFRelocationRef(Reloc).getAddend();
auto A = AddendOrErr ? *AddendOrErr : 0;
Expected<uint64_t> ValueOrErr = Reloc.getSymbol()->getValue();
if (!ValueOrErr)
// TODO: Test this error.
return ValueOrErr.takeError();
Relocs.insert({Reloc.getOffset(), Resolver(Reloc, *ValueOrErr, A)});
Relocs.insert(
{Reloc.getOffset(),
object::resolveRelocation(Resolver, Reloc, *ValueOrErr, A)});
} else if (Reloc.getType() == RelativeRelocation) {
if (auto AddendOrErr = object::ELFRelocationRef(Reloc).getAddend())
Relocs.insert({Reloc.getOffset(), *AddendOrErr});

View File

@ -43,13 +43,14 @@ Sections:
# INVALID-STRTAB-SIZE: error: '[[FILE]]': section [index 1] has a sh_offset (0x70) + sh_size (0xffffff) that is greater than the file size (0x218)
## Check that llvm-dwarfdump reports an error during relocation resolution
## when instead of expected SHT_RELA section it locates a section of a different type.
## Document that llvm-dwarfdump doesn't reports errors/warnings during relocation resolution
## when instead of SHT_RELA section we have a SHT_REL section in an object.
## In this case it just doesn't try to read relocation addends and assumes they are 0.
## Note: we don't check the output, because the intention of this test is just to check the
## exit code and to document the fact that no warnings are reported.
# RUN: yaml2obj %s --docnum=3 -o %t3
# RUN: not --crash llvm-dwarfdump -debug-line %t3 2>&1 | FileCheck --check-prefix=RELA %s
# RELA: LLVM ERROR: Section is not SHT_RELA
# RUN: llvm-dwarfdump -debug-line %t3 2>&1 | FileCheck --implicit-check-not=warning: %s
--- !ELF
FileHeader:

View File

@ -5849,7 +5849,7 @@ void DumpStyle<ELFT>::printStackSize(RelocationRef Reloc,
}
uint64_t Addend = Data.getAddress(&Offset);
uint64_t SymValue = Resolver(Reloc, RelocSymValue, Addend);
uint64_t SymValue = resolveRelocation(Resolver, Reloc, RelocSymValue, Addend);
this->printFunctionStackSize(SymValue, FunctionSec, StackSizeSec, Data,
&Offset);
}
@ -5947,7 +5947,8 @@ void DumpStyle<ELFT>::printRelocatableStackSizes(
// described in it.
const Elf_Shdr *FunctionSec = unwrapOrError(
this->FileName, Obj.getSection(StackSizesELFSec->sh_link));
bool (*IsSupportedFn)(uint64_t);
SupportsRelocation IsSupportedFn;
RelocationResolver Resolver;
std::tie(IsSupportedFn, Resolver) = getRelocationResolver(ElfObj);
ArrayRef<uint8_t> Contents =