forked from OSchip/llvm-project
[PR] Fix aarch64 TLS relocations handling
Summary: There are few problems found when dealing with TLS relocations for aarch64. * RewriteInstance.cpp ** While analyzing TLS relocation we don't have to modify SymbolAddress (which is the offset from the TLS section), so we need to just skip verifiction ** The non-got related TLS relocations on aarch64 might be skipped too ** The forse relocation must be applied for GOT relocations on Aarch64. The symbol adress for GOT relocation might no be pointing on GOT section (for example ADRP GOT may point to the wrong section, since GOT table is not page-aligned), so we won't try to get section by the symbol address. * Relocation.cpp - Remove R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLE_ADD_TPREL_LO12_NC from isGOT check, since they are not got-related relocations * BinaryFunction.h ** Remove R_AARCH64_TLSLE_ADD_TPREL_HI12 and R_AARCH64_TLSLE_ADD_TPREL_LO12_NC from adding to relocation list, since this is actually an offset in TLS section and BOLT does not change it we don't need to do something with this relocations, the value won't change in new binary files ** Refactor the code, separating aarch64 and x86 relocations * AArch64MCPlusBuilder.cpp ** Add forgotten LO12 relocations to switch case to getTargetExprFor Vladislav Khmelevsky, Advanced Software Technology Lab, Huawei (cherry picked from FBD31003349)
This commit is contained in:
parent
48fbeb1a46
commit
542c03c3a3
|
@ -1286,6 +1286,64 @@ public:
|
|||
return InputOffsetToAddressMap;
|
||||
}
|
||||
|
||||
void addRelocationAArch64(uint64_t Offset, MCSymbol *Symbol, uint64_t RelType,
|
||||
uint64_t Addend, uint64_t Value) {
|
||||
switch (RelType) {
|
||||
case ELF::R_AARCH64_ABS64:
|
||||
case ELF::R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_ADR_GOT_PAGE:
|
||||
case ELF::R_AARCH64_ADR_PREL_LO21:
|
||||
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC:
|
||||
case ELF::R_AARCH64_LD64_GOT_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSDESC_ADD_LO12:
|
||||
case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
|
||||
case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
|
||||
case ELF::R_AARCH64_TLSDESC_LD64_LO12:
|
||||
case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
Relocations[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value};
|
||||
return;
|
||||
case ELF::R_AARCH64_CALL26:
|
||||
case ELF::R_AARCH64_JUMP26:
|
||||
case ELF::R_AARCH64_TLSDESC_CALL:
|
||||
case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
return;
|
||||
default:
|
||||
llvm_unreachable("Unexpected AArch64 relocation type in code");
|
||||
}
|
||||
}
|
||||
|
||||
void addRelocationX86(uint64_t Offset, MCSymbol *Symbol, uint64_t RelType,
|
||||
uint64_t Addend, uint64_t Value) {
|
||||
switch (RelType) {
|
||||
case ELF::R_X86_64_8:
|
||||
case ELF::R_X86_64_16:
|
||||
case ELF::R_X86_64_32:
|
||||
case ELF::R_X86_64_32S:
|
||||
case ELF::R_X86_64_64:
|
||||
Relocations[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value};
|
||||
return;
|
||||
case ELF::R_X86_64_PC32:
|
||||
case ELF::R_X86_64_PC8:
|
||||
case ELF::R_X86_64_PLT32:
|
||||
case ELF::R_X86_64_GOTPCRELX:
|
||||
case ELF::R_X86_64_REX_GOTPCRELX:
|
||||
case ELF::R_X86_64_GOTPCREL:
|
||||
case ELF::R_X86_64_TPOFF32:
|
||||
case ELF::R_X86_64_GOTTPOFF:
|
||||
return;
|
||||
default:
|
||||
llvm_unreachable("Unexpected x86 relocation type in code");
|
||||
}
|
||||
}
|
||||
|
||||
/// Register relocation type \p RelType at a given \p Address in the function
|
||||
/// against \p Symbol.
|
||||
/// Assert if the \p Address is not inside this function.
|
||||
|
@ -1294,52 +1352,10 @@ public:
|
|||
assert(Address >= getAddress() && Address < getAddress() + getMaxSize() &&
|
||||
"address is outside of the function");
|
||||
uint64_t Offset = Address - getAddress();
|
||||
switch (RelType) {
|
||||
case ELF::R_X86_64_8:
|
||||
case ELF::R_X86_64_16:
|
||||
case ELF::R_X86_64_32:
|
||||
case ELF::R_X86_64_32S:
|
||||
case ELF::R_X86_64_64:
|
||||
case ELF::R_AARCH64_ABS64:
|
||||
case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSDESC_LD64_LO12:
|
||||
case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
case ELF::R_AARCH64_LD64_GOT_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSDESC_ADD_LO12:
|
||||
case ELF::R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_ADR_GOT_PAGE:
|
||||
case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
|
||||
case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
|
||||
case ELF::R_AARCH64_ADR_PREL_LO21:
|
||||
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC:
|
||||
Relocations[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value};
|
||||
break;
|
||||
case ELF::R_X86_64_PC32:
|
||||
case ELF::R_X86_64_PC8:
|
||||
case ELF::R_X86_64_PLT32:
|
||||
case ELF::R_X86_64_GOTPCRELX:
|
||||
case ELF::R_X86_64_REX_GOTPCRELX:
|
||||
case ELF::R_AARCH64_JUMP26:
|
||||
case ELF::R_AARCH64_CALL26:
|
||||
case ELF::R_AARCH64_TLSDESC_CALL:
|
||||
break;
|
||||
if (BC.isAArch64())
|
||||
return addRelocationAArch64(Offset, Symbol, RelType, Addend, Value);
|
||||
|
||||
// The following relocations are ignored.
|
||||
case ELF::R_X86_64_GOTPCREL:
|
||||
case ELF::R_X86_64_TPOFF32:
|
||||
case ELF::R_X86_64_GOTTPOFF:
|
||||
return;
|
||||
default:
|
||||
llvm_unreachable("unexpected relocation type in code");
|
||||
}
|
||||
return addRelocationX86(Offset, Symbol, RelType, Addend, Value);
|
||||
}
|
||||
|
||||
/// Return the name of the section this function originated from.
|
||||
|
|
|
@ -243,11 +243,9 @@ bool isGOTAArch64(uint64_t 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:
|
||||
case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
|
||||
case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
|
||||
case ELF::R_AARCH64_TLSDESC_LD64_LO12:
|
||||
|
|
|
@ -1899,6 +1899,8 @@ bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel,
|
|||
if (Relocation::isGOT(RType)) {
|
||||
Addend = 0;
|
||||
SymbolAddress = ExtractedValue + PCRelOffset;
|
||||
} else if (Relocation::isTLS(RType)) {
|
||||
SkipVerification = true;
|
||||
} else if (!SymbolAddress) {
|
||||
assert(!IsSectionRelocation);
|
||||
if (ExtractedValue || Addend == 0 || IsPCRelative) {
|
||||
|
@ -1927,9 +1929,6 @@ bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel,
|
|||
if (SymbolName == "__hot_start" || SymbolName == "__hot_end")
|
||||
return true;
|
||||
|
||||
if (Relocation::isTLS(RType))
|
||||
return true;
|
||||
|
||||
if (RType == ELF::R_X86_64_PLT32)
|
||||
return true;
|
||||
|
||||
|
@ -2317,9 +2316,15 @@ void RewriteInstance::readRelocations(const SectionRef &Section) {
|
|||
RType &= ~ELF::R_X86_64_converted_reloc_bit;
|
||||
}
|
||||
|
||||
// No special handling required for TLS relocations on X86.
|
||||
if (Relocation::isTLS(RType) && BC->isX86())
|
||||
continue;
|
||||
if (Relocation::isTLS(RType)) {
|
||||
// No special handling required for TLS relocations on X86.
|
||||
if (BC->isX86())
|
||||
continue;
|
||||
|
||||
// The non-got related TLS relocations on AArch64 also could be skipped.
|
||||
if (!Relocation::isGOT(RType))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BC->getDynamicRelocationAt(Rel.getOffset())) {
|
||||
LLVM_DEBUG(
|
||||
|
@ -2398,16 +2403,17 @@ void RewriteInstance::readRelocations(const SectionRef &Section) {
|
|||
}
|
||||
|
||||
bool ForceRelocation = BC->forceSymbolRelocations(SymbolName);
|
||||
|
||||
if (BC->isAArch64() && RType == ELF::R_AARCH64_ADR_GOT_PAGE)
|
||||
ForceRelocation = true;
|
||||
|
||||
ErrorOr<BinarySection &> RefSection =
|
||||
BC->getSectionForAddress(SymbolAddress);
|
||||
if (!RefSection && !ForceRelocation) {
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "BOLT-DEBUG: cannot determine referenced section.\n");
|
||||
continue;
|
||||
std::make_error_code(std::errc::bad_address);
|
||||
if (BC->isAArch64() && Relocation::isGOT(RType)) {
|
||||
ForceRelocation = true;
|
||||
} else {
|
||||
RefSection = BC->getSectionForAddress(SymbolAddress);
|
||||
if (!RefSection && !ForceRelocation) {
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "BOLT-DEBUG: cannot determine referenced section.\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const bool IsToCode = RefSection && RefSection->isText();
|
||||
|
|
|
@ -335,14 +335,17 @@ public:
|
|||
return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, Ctx);
|
||||
} else {
|
||||
switch(RelType) {
|
||||
case ELF::R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LD64_GOT_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_LD64_GOT_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSDESC_LD64_LO12:
|
||||
case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSDESC_ADD_LO12:
|
||||
case ELF::R_AARCH64_TLSDESC_LD64_LO12:
|
||||
case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_LO12, Ctx);
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Test checks that BOLT can process binaries with TLS relocations
|
||||
|
||||
__thread struct str {
|
||||
int a;
|
||||
int b;
|
||||
} tbssstruct = {}, tdatastruct = {4, 2};
|
||||
|
||||
extern __thread struct str extstruct;
|
||||
|
||||
extern void processAddr(volatile void *);
|
||||
|
||||
int main() {
|
||||
// R_AARCH64_TLSDESC_ADR_PAGE21 and R_AARCH64_TLSDESC_LD64_LO12_NC are
|
||||
// produced for pie binaries in all cases below.
|
||||
|
||||
// The R_TLSLE_ADD_TPREL_HI12 and R_TLSLE_ADD_TPREL_LO12_NC for
|
||||
// relocations in .tbss and .tdata
|
||||
processAddr(&tbssstruct.b);
|
||||
processAddr(&tdatastruct.b);
|
||||
|
||||
// The R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 and
|
||||
// R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC relocations
|
||||
processAddr(&extstruct.b);
|
||||
}
|
||||
|
||||
// REQUIRES: system-linux
|
||||
|
||||
// RUN: %host_cc %cflags -no-pie %s -o %t.exe -Wl,-q \
|
||||
// RUN: -Wl,--unresolved-symbols=ignore-all
|
||||
// RUN: llvm-bolt %t.exe -o %t.bolt
|
||||
// RUN: %host_cc %cflags -fPIC -pie -%s -o %t_pie.exe -Wl,-q \
|
||||
// RUN: -Wl,--unresolved-symbols=ignore-all
|
||||
// RUN: llvm-bolt %t_pie.exe -o %t.bolt
|
Loading…
Reference in New Issue