forked from OSchip/llvm-project
[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:
parent
4cb510d284
commit
9a99d23a1b
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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});
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 =
|
||||
|
|
Loading…
Reference in New Issue