[BOLT] Add R_AARCH64_PREL16/32/64 relocations support

Reviewed By: yota9, rafauler

Differential Revision: https://reviews.llvm.org/D122294
This commit is contained in:
Alexey Moksyakov 2022-04-21 13:52:00 +03:00 committed by Vladislav Khmelevsky
parent 63686af1e1
commit 48e894a536
6 changed files with 63 additions and 0 deletions

View file

@ -1279,6 +1279,9 @@ public:
case ELF::R_AARCH64_MOVW_UABS_G2:
case ELF::R_AARCH64_MOVW_UABS_G2_NC:
case ELF::R_AARCH64_MOVW_UABS_G3:
case ELF::R_AARCH64_PREL16:
case ELF::R_AARCH64_PREL32:
case ELF::R_AARCH64_PREL64:
Rels[Offset] = Relocation{Offset, Symbol, RelType, Addend, Value};
return;
case ELF::R_AARCH64_CALL26:

View file

@ -74,7 +74,9 @@ bool isSupportedAArch64(uint64_t Type) {
case ELF::R_AARCH64_TLSDESC_ADD_LO12:
case ELF::R_AARCH64_TLSDESC_CALL:
case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case ELF::R_AARCH64_PREL16:
case ELF::R_AARCH64_PREL32:
case ELF::R_AARCH64_PREL64:
case ELF::R_AARCH64_ABS16:
case ELF::R_AARCH64_ABS32:
case ELF::R_AARCH64_ABS64:
@ -121,6 +123,7 @@ size_t getSizeForTypeAArch64(uint64_t Type) {
errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n';
llvm_unreachable("unsupported relocation type");
case ELF::R_AARCH64_ABS16:
case ELF::R_AARCH64_PREL16:
return 2;
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_JUMP26:
@ -157,6 +160,7 @@ size_t getSizeForTypeAArch64(uint64_t Type) {
case ELF::R_AARCH64_ABS32:
return 4;
case ELF::R_AARCH64_ABS64:
case ELF::R_AARCH64_PREL64:
return 8;
}
}
@ -258,7 +262,9 @@ uint64_t adjustValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) {
llvm_unreachable("not supported relocation");
case ELF::R_AARCH64_ABS32:
break;
case ELF::R_AARCH64_PREL16:
case ELF::R_AARCH64_PREL32:
case ELF::R_AARCH64_PREL64:
Value -= PC;
break;
}
@ -282,8 +288,12 @@ uint64_t extractValueAArch64(uint64_t Type, uint64_t Contents, uint64_t PC) {
case ELF::R_AARCH64_ABS32:
case ELF::R_AARCH64_ABS64:
return Contents;
case ELF::R_AARCH64_PREL16:
return static_cast<int64_t>(PC) + SignExtend64<16>(Contents & 0xffff);
case ELF::R_AARCH64_PREL32:
return static_cast<int64_t>(PC) + SignExtend64<32>(Contents & 0xffffffff);
case ELF::R_AARCH64_PREL64:
return static_cast<int64_t>(PC) + Contents;
case ELF::R_AARCH64_TLSDESC_CALL:
case ELF::R_AARCH64_JUMP26:
case ELF::R_AARCH64_CALL26:
@ -505,7 +515,9 @@ bool isPCRelativeAArch64(uint64_t Type) {
case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case ELF::R_AARCH64_TLSDESC_ADR_PREL21:
case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
case ELF::R_AARCH64_PREL16:
case ELF::R_AARCH64_PREL32:
case ELF::R_AARCH64_PREL64:
return true;
}
}

View file

@ -90,6 +90,7 @@ tools = [
ToolSubst('llvm-readelf', unresolved='fatal'),
ToolSubst('link_fdata', command=link_fdata_cmd, unresolved='fatal'),
ToolSubst('merge-fdata', unresolved='fatal'),
ToolSubst('llvm-readobj', unresolved='fatal'),
]
llvm_config.add_tool_substitutions(tools, tool_dirs)

View file

@ -0,0 +1,37 @@
// This test checks processing of R_AARCH64_PREL64/32/16 relocations
// RUN: %clang %cflags -nostartfiles -nostdlib %s -o %t.exe -Wl,-q \
// RUN: -Wl,-z,max-page-size=4
// RUN: llvm-readelf -Wa %t.exe | FileCheck %s -check-prefix=CHECKPREL
// CHECKPREL: R_AARCH64_PREL16 {{.*}} .dummy + 0
// CHECKPREL-NEXT: R_AARCH64_PREL32 {{.*}} _start + 4
// CHECKPREL-NEXT: R_AARCH64_PREL64 {{.*}} _start + 8
// RUN: llvm-bolt %t.exe -o %t.bolt
// RUN: llvm-readobj -S --section-data %t.bolt | FileCheck %s
// CHECK: Name: .data
// CHECK: SectionData (
// CHECK: 0000: FCFF0000 44FF3F00 44FF3F00 00000000
// CHECK: )
.text
.align 4
.globl _start
.type _start, %function
_start:
adr x0, datatable
mov x0, #0
ret
.section .dummy, "da"
dummy:
.word 0
.section .data
datatable:
.hword dummy - datatable
.align 2
.word _start - datatable
.xword _start - datatable

View file

@ -446,6 +446,13 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
write(isBE, TargetPtr, static_cast<uint32_t>(Result));
break;
}
case ELF::R_AARCH64_PREL16: {
uint64_t Result = Value + Addend - FinalAddress;
assert(static_cast<int64_t>(Result) >= INT16_MIN &&
static_cast<int64_t>(Result) <= UINT16_MAX);
write(isBE, TargetPtr, static_cast<uint16_t>(Result & 0xffffU));
break;
}
case ELF::R_AARCH64_PREL32: {
uint64_t Result = Value + Addend - FinalAddress;
assert(static_cast<int64_t>(Result) >= INT32_MIN &&

View file

@ -78,6 +78,7 @@ static bool supportsAArch64(uint64_t Type) {
switch (Type) {
case ELF::R_AARCH64_ABS32:
case ELF::R_AARCH64_ABS64:
case ELF::R_AARCH64_PREL16:
case ELF::R_AARCH64_PREL32:
case ELF::R_AARCH64_PREL64:
return true;
@ -93,6 +94,8 @@ static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
return (S + Addend) & 0xFFFFFFFF;
case ELF::R_AARCH64_ABS64:
return S + Addend;
case ELF::R_AARCH64_PREL16:
return (S + Addend - Offset) & 0xFFFF;
case ELF::R_AARCH64_PREL32:
return (S + Addend - Offset) & 0xFFFFFFFF;
case ELF::R_AARCH64_PREL64: