[BOLT] Refactor relocations class impl per arch, NFC

Summary:
Do not mix relocation codes from different archs. Even though
they do not intersect at the moment, this could easily introduce bugs
once new relocations are supported (for example, ILP32 for AArch64).

(cherry picked from FBD24169425)
This commit is contained in:
Rafael Auler 2020-10-07 15:40:51 -07:00 committed by Maksim Panchenko
parent 59c21b42da
commit 35632d4828
3 changed files with 137 additions and 30 deletions

View File

@ -18,7 +18,9 @@ using namespace bolt;
Triple::ArchType Relocation::Arch;
bool Relocation::isSupported(uint64_t Type) {
namespace {
bool isSupportedX86(uint64_t Type) {
switch (Type) {
default:
return false;
@ -36,6 +38,14 @@ bool Relocation::isSupported(uint64_t Type) {
case ELF::R_X86_64_TPOFF32:
case ELF::R_X86_64_GOTPCRELX:
case ELF::R_X86_64_REX_GOTPCRELX:
return true;
}
}
bool isSupportedAArch64(uint64_t Type) {
switch (Type) {
default:
return false;
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
@ -61,7 +71,7 @@ bool Relocation::isSupported(uint64_t Type) {
}
}
size_t Relocation::getSizeForType(uint64_t Type) {
size_t getSizeForTypeX86(uint64_t Type) {
switch (Type) {
default:
llvm_unreachable("unsupported relocation type");
@ -79,6 +89,18 @@ size_t Relocation::getSizeForType(uint64_t Type) {
case ELF::R_X86_64_TPOFF32:
case ELF::R_X86_64_GOTPCRELX:
case ELF::R_X86_64_REX_GOTPCRELX:
return 4;
case ELF::R_X86_64_PC64:
case ELF::R_X86_64_64:
return 8;
}
}
size_t getSizeForTypeAArch64(uint64_t Type) {
switch (Type) {
default:
dbgs() << "Reloc num: " << Type << "\n";
llvm_unreachable("unsupported relocation type");
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
@ -100,20 +122,23 @@ size_t Relocation::getSizeForType(uint64_t Type) {
case ELF::R_AARCH64_JUMP26:
case ELF::R_AARCH64_PREL32:
return 4;
case ELF::R_X86_64_PC64:
case ELF::R_X86_64_64:
case ELF::R_AARCH64_ABS64:
return 8;
}
}
uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents,
uint64_t PC) {
uint64_t extractValueX86(uint64_t Type, uint64_t Contents, uint64_t PC) {
if (Type == ELF::R_X86_64_32S)
return SignExtend64<32>(Contents & 0xffffffff);
return Contents;
}
uint64_t extractValueAArch64(uint64_t Type, uint64_t Contents, uint64_t PC) {
switch (Type) {
default:
llvm_unreachable("unsupported relocation type");
case ELF::R_AARCH64_ABS64:
return Contents;
case ELF::R_X86_64_32S:
return SignExtend64<32>(Contents & 0xffffffff);
case ELF::R_AARCH64_PREL32:
return static_cast<int64_t>(PC) + SignExtend64<32>(Contents & 0xffffffff);
case ELF::R_AARCH64_TLSDESC_CALL:
@ -180,7 +205,7 @@ uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents,
}
}
bool Relocation::isGOT(uint64_t Type) {
bool isGOTX86(uint64_t Type) {
switch (Type) {
default:
return false;
@ -196,6 +221,14 @@ bool Relocation::isGOT(uint64_t Type) {
case ELF::R_X86_64_GOTPC32_TLSDESC:
case ELF::R_X86_64_GOTPCRELX:
case ELF::R_X86_64_REX_GOTPCRELX:
return true;
}
}
bool isGOTAArch64(uint64_t Type) {
switch (Type) {
default:
return false;
case ELF::R_AARCH64_ADR_GOT_PAGE:
case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
case ELF::R_AARCH64_LD64_GOT_LO12_NC:
@ -210,13 +243,21 @@ bool Relocation::isGOT(uint64_t Type) {
}
}
bool Relocation::isTLS(uint64_t Type) {
bool isTLSX86(uint64_t Type) {
switch (Type) {
default:
return false;
case ELF::R_X86_64_TPOFF32:
case ELF::R_X86_64_TPOFF64:
case ELF::R_X86_64_GOTTPOFF:
return true;
}
}
bool isTLSAArch64(uint64_t Type) {
switch (Type) {
default:
return false;
case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
@ -229,17 +270,33 @@ bool Relocation::isTLS(uint64_t Type) {
}
}
bool Relocation::isPCRelative(uint64_t Type) {
bool isPCRelativeX86(uint64_t Type) {
switch (Type) {
default:
llvm_unreachable("Unknown relocation type");
case ELF::R_X86_64_64:
case ELF::R_X86_64_32:
case ELF::R_X86_64_32S:
case ELF::R_X86_64_16:
case ELF::R_X86_64_8:
case ELF::R_X86_64_TPOFF32:
return false;
case ELF::R_X86_64_PC8:
case ELF::R_X86_64_PC32:
case ELF::R_X86_64_PC64:
case ELF::R_X86_64_GOTPCREL:
case ELF::R_X86_64_PLT32:
case ELF::R_X86_64_GOTTPOFF:
case ELF::R_X86_64_GOTPCRELX:
case ELF::R_X86_64_REX_GOTPCRELX:
return true;
}
}
bool isPCRelativeAArch64(uint64_t Type) {
switch (Type) {
default:
llvm_unreachable("Unknown relocation type");
case ELF::R_AARCH64_ABS64:
case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
case ELF::R_AARCH64_ADD_ABS_LO12_NC:
@ -254,15 +311,6 @@ bool Relocation::isPCRelative(uint64_t Type) {
case ELF::R_AARCH64_TLSDESC_LD64_LO12:
case ELF::R_AARCH64_TLSDESC_ADD_LO12:
return false;
case ELF::R_X86_64_PC8:
case ELF::R_X86_64_PC32:
case ELF::R_X86_64_PC64:
case ELF::R_X86_64_GOTPCREL:
case ELF::R_X86_64_PLT32:
case ELF::R_X86_64_GOTTPOFF:
case ELF::R_X86_64_GOTPCRELX:
case ELF::R_X86_64_REX_GOTPCRELX:
case ELF::R_AARCH64_TLSDESC_CALL:
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
@ -275,6 +323,57 @@ bool Relocation::isPCRelative(uint64_t Type) {
}
}
} // end anonymous namespace
bool Relocation::isSupported(uint64_t Type) {
if (Arch == Triple::aarch64)
return isSupportedAArch64(Type);
return isSupportedX86(Type);
}
size_t Relocation::getSizeForType(uint64_t Type) {
if (Arch == Triple::aarch64)
return getSizeForTypeAArch64(Type);
return getSizeForTypeX86(Type);
}
uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents,
uint64_t PC) {
if (Arch == Triple::aarch64)
return extractValueAArch64(Type, Contents, PC);
return extractValueX86(Type, Contents, PC);
}
bool Relocation::isGOT(uint64_t Type) {
if (Arch == Triple::aarch64)
return isGOTAArch64(Type);
return isGOTX86(Type);
}
bool Relocation::isTLS(uint64_t Type) {
if (Arch == Triple::aarch64)
return isTLSAArch64(Type);
return isTLSX86(Type);
}
bool Relocation::isPCRelative(uint64_t Type) {
if (Arch == Triple::aarch64)
return isPCRelativeAArch64(Type);
return isPCRelativeX86(Type);
}
uint64_t Relocation::getPC32() {
if (Arch == Triple::aarch64)
return ELF::R_AARCH64_PREL32;
return ELF::R_X86_64_PC32;
}
uint64_t Relocation::getPC64() {
if (Arch == Triple::aarch64)
return ELF::R_AARCH64_PREL64;
return ELF::R_X86_64_PC64;
}
size_t Relocation::emit(MCStreamer *Streamer) const {
const auto Size = getSizeForType(Type);
auto &Ctx = Streamer->getContext();

View File

@ -30,7 +30,7 @@ namespace bolt {
/// Relocation class.
struct Relocation {
static Triple::ArchType Arch; /// for printing, set by BinaryContext ctor.
static Triple::ArchType Arch; /// set by BinaryContext ctor.
/// The offset of this relocation in the object it is contained in.
uint64_t Offset;
@ -73,6 +73,12 @@ struct Relocation {
/// Return true if relocation type is for thread local storage.
static bool isTLS(uint64_t Type);
/// Return code for a PC-relative 4-byte relocation
static uint64_t getPC32();
/// Return code for a PC-relative 8-byte relocation
static uint64_t getPC64();
/// Return true if this relocation is PC-relative. Return false otherwise.
bool isPCRelative() const {
return isPCRelative(Type);

View File

@ -1480,12 +1480,12 @@ void RewriteInstance::relocateEHFrameSection() {
llvm_unreachable("unsupported DWARF encoding type");
case dwarf::DW_EH_PE_sdata4:
case dwarf::DW_EH_PE_udata4:
RelType = ELF::R_X86_64_PC32;
RelType = Relocation::getPC32();
Offset -= 4;
break;
case dwarf::DW_EH_PE_sdata8:
case dwarf::DW_EH_PE_udata8:
RelType = ELF::R_X86_64_PC64;
RelType = Relocation::getPC64();
Offset -= 8;
break;
}
@ -1967,15 +1967,15 @@ void RewriteInstance::processLKExTable() {
// fixup
if (FunctionOffset)
ReferencedSymbol = ContainingBF->addEntryPointAtOffset(FunctionOffset);
BC->addRelocation(EntryAddress, ReferencedSymbol, ELF::R_X86_64_PC32, 0,
*Offset);
BC->addRelocation(EntryAddress, ReferencedSymbol, Relocation::getPC32(),
0, *Offset);
break;
case 8:
// handler
assert(!FunctionOffset &&
"__ex_table handler entry should point to function start");
BC->addRelocation(EntryAddress, ReferencedSymbol, ELF::R_X86_64_PC32, 0,
*Offset);
BC->addRelocation(EntryAddress, ReferencedSymbol, Relocation::getPC32(),
0, *Offset);
break;
}
}
@ -2003,7 +2003,7 @@ void RewriteInstance::processLKPCIFixup() {
auto *HookupFunction = BC->getBinaryFunctionAtAddress(HookupAddress);
assert(HookupFunction && "expected function for entry in .pci_fixup");
BC->addRelocation(PC, HookupFunction->getSymbol(),
ELF::R_X86_64_PC32, 0, *Offset);
Relocation::getPC32(), 0, *Offset);
}
}
@ -2036,7 +2036,7 @@ void RewriteInstance::processLKKSymtab(bool IsGPL) {
if (!BF)
continue;
BC->addRelocation(EntryAddress, BF->getSymbol(), ELF::R_X86_64_PC32, 0,
BC->addRelocation(EntryAddress, BF->getSymbol(), Relocation::getPC32(), 0,
*Offset);
}
}
@ -4465,6 +4465,8 @@ template <typename ELFT>
void
RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
auto &OS = Out->os();
if (!BC->isX86())
return;
for (auto &RelaSection : BC->allocatableRelaSections()) {
for (const auto &Rel : RelaSection.getSectionRef().relocations()) {