diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -1279,6 +1279,9 @@ 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: diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp --- a/bolt/lib/Core/Relocation.cpp +++ b/bolt/lib/Core/Relocation.cpp @@ -74,7 +74,9 @@ 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 @@ 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 @@ case ELF::R_AARCH64_ABS32: return 4; case ELF::R_AARCH64_ABS64: + case ELF::R_AARCH64_PREL64: return 8; } } @@ -258,7 +262,9 @@ 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 @@ case ELF::R_AARCH64_ABS32: case ELF::R_AARCH64_ABS64: return Contents; + case ELF::R_AARCH64_PREL16: + return static_cast(PC) + SignExtend64<16>(Contents & 0xffff); case ELF::R_AARCH64_PREL32: return static_cast(PC) + SignExtend64<32>(Contents & 0xffffffff); + case ELF::R_AARCH64_PREL64: + return static_cast(PC) + Contents; case ELF::R_AARCH64_TLSDESC_CALL: case ELF::R_AARCH64_JUMP26: case ELF::R_AARCH64_CALL26: @@ -505,7 +515,9 @@ 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; } } diff --git a/bolt/test/lit.cfg.py b/bolt/test/lit.cfg.py --- a/bolt/test/lit.cfg.py +++ b/bolt/test/lit.cfg.py @@ -90,6 +90,7 @@ 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) diff --git a/bolt/test/runtime/AArch64/r_aarch64_prelxx.s b/bolt/test/runtime/AArch64/r_aarch64_prelxx.s new file mode 100644 --- /dev/null +++ b/bolt/test/runtime/AArch64/r_aarch64_prelxx.s @@ -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 diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -446,6 +446,13 @@ write(isBE, TargetPtr, static_cast(Result)); break; } + case ELF::R_AARCH64_PREL16: { + uint64_t Result = Value + Addend - FinalAddress; + assert(static_cast(Result) >= INT16_MIN && + static_cast(Result) <= UINT16_MAX); + write(isBE, TargetPtr, static_cast(Result & 0xffffU)); + break; + } case ELF::R_AARCH64_PREL32: { uint64_t Result = Value + Addend - FinalAddress; assert(static_cast(Result) >= INT32_MIN && diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -78,6 +78,7 @@ 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 @@ 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: