diff options
author | Peter Smith <peter.smith@linaro.org> | 2019-08-08 13:38:09 +0000 |
---|---|---|
committer | Peter Smith <peter.smith@linaro.org> | 2019-08-08 13:38:09 +0000 |
commit | d4695e1d75a358d3161b5a81c9754c410c1ed2bc (patch) | |
tree | c15eca1626db76bc753e83e25f67ab7786bbcfdf /lld | |
parent | 59fabf9c606ecc69342463e514faefdfa2361be6 (diff) | |
download | llvm-d4695e1d75a358d3161b5a81c9754c410c1ed2bc.zip llvm-d4695e1d75a358d3161b5a81c9754c410c1ed2bc.tar.gz llvm-d4695e1d75a358d3161b5a81c9754c410c1ed2bc.tar.bz2 |
[ELF][AArch64] Support for movz, movk tprel relocations
This patch Implements the R_AARCH64_TLSLE_MOVW_TPREL_G*[_NC]. These are
logically the same calculation as the existing TLSLE relocations with
the result written back to mov[nz] and movk instructions. A typical code
sequence is:
movz x0, #:tprel_g2:foo // bits [47:32] of R_TLS with overflow check
movk x0, #:tprel_g1_nc:foo // bits [31:16] of R_TLS with no overflow check
movk x0, #:tprel_g0_nc:foo // bits [15:0] of R_TLS with no overflow check
This type of code sequence is usually used with a large code model.
Differential Revision: https://reviews.llvm.org/D65882
Fixes: PR42853
llvm-svn: 368293
Diffstat (limited to 'lld')
-rw-r--r-- | lld/ELF/Arch/AArch64.cpp | 10 | ||||
-rw-r--r-- | lld/test/ELF/aarch64-movw-error.s | 19 | ||||
-rw-r--r-- | lld/test/ELF/aarch64-movw-tprel.s | 65 |
3 files changed, 94 insertions, 0 deletions
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index f864c36..600e902 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -90,6 +90,11 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G0: + case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G1: + case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G2: return R_TLS; case R_AARCH64_CALL26: case R_AARCH64_CONDBR19: @@ -376,20 +381,25 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; case R_AARCH64_MOVW_PREL_G0: case R_AARCH64_MOVW_SABS_G0: + case R_AARCH64_TLSLE_MOVW_TPREL_G0: checkInt(loc, val, 17, type); LLVM_FALLTHROUGH; case R_AARCH64_MOVW_PREL_G0_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: writeSMovWImm(loc, val); break; case R_AARCH64_MOVW_PREL_G1: case R_AARCH64_MOVW_SABS_G1: + case R_AARCH64_TLSLE_MOVW_TPREL_G1: checkInt(loc, val, 33, type); LLVM_FALLTHROUGH; case R_AARCH64_MOVW_PREL_G1_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: writeSMovWImm(loc, val >> 16); break; case R_AARCH64_MOVW_PREL_G2: case R_AARCH64_MOVW_SABS_G2: + case R_AARCH64_TLSLE_MOVW_TPREL_G2: checkInt(loc, val, 49, type); LLVM_FALLTHROUGH; case R_AARCH64_MOVW_PREL_G2_NC: diff --git a/lld/test/ELF/aarch64-movw-error.s b/lld/test/ELF/aarch64-movw-error.s index 9974ed4..03575b1 100644 --- a/lld/test/ELF/aarch64-movw-error.s +++ b/lld/test/ELF/aarch64-movw-error.s @@ -34,3 +34,22 @@ movn x0, #:prel_g0:.-0x10001 movn x0, #:prel_g1:.-0x100010000 # CHECK: relocation R_AARCH64_MOVW_PREL_G2 out of range: -281479271677952 is not in [-281474976710656, 281474976710655] movn x0, #:prel_g2:.-0x1000100000000 + +movz x0, #:tprel_g0: v1 +# CHECK: relocation R_AARCH64_TLSLE_MOVW_TPREL_G0 out of range: 65552 is not in [-65536, 65535] +movz x0, #:tprel_g1: v2 +# CHECK: relocation R_AARCH64_TLSLE_MOVW_TPREL_G1 out of range: 4295032848 is not in [-4294967296, 4294967295] +movz x0, #:tprel_g2: v3 +# CHECK: relocation R_AARCH64_TLSLE_MOVW_TPREL_G2 out of range: 281479271743496 is not in [-281474976710656, 281474976710655] + +.section .tbss,"awT",@nobits +.balign 16 +.space 0x10000 +v1: +.quad 0 +.space 0x100000000 - 8 +v2: +.quad 0 +.space 0x1000000000000 - 16 +v3: +.quad 0 diff --git a/lld/test/ELF/aarch64-movw-tprel.s b/lld/test/ELF/aarch64-movw-tprel.s new file mode 100644 index 0000000..11932e8 --- /dev/null +++ b/lld/test/ELF/aarch64-movw-tprel.s @@ -0,0 +1,65 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d %t +# RUN: llvm-readobj --symbols %t +# RUN: llvm-objdump --no-show-raw-insn -d %t | FileCheck %s +# RUN: llvm-readobj --symbols %t | FileCheck --check-prefix=CHECK-SYM %s + +## Test the the local exec relocations that map to: +## R_AARCH64_TLSLE_MOVW_TPREL_G2 +## R_AARCH64_TLSLE_MOVW_TPREL_G1 +## R_AARCH64_TLSLE_MOVW_TPREL_G1_NC +## R_AARCH64_TLSLE_MOVW_TPREL_G0 +## R_AARCH64_TLSLE_MOVW_TPREL_G0_NC +## They calculate the same value as the other TPREL relocations, namely the +## offset from the thread pointer TP. The G0, G1 and G2 refer to partitions +## of the result with G2 bits [47:32], G1 bits [31:16] and G0 bits [15:0] +## the NC variant does not check for overflow. +## In AArch64 the structure of the TLS at runtime is: +## | TCB | Alignment Padding | TLS Block | +## With TP pointing to the start of the TCB. All offsets will be positive. + +.text +## Access variable in first partition +movz x0, #:tprel_g0:v0 +## TCB + 0 == 16 +# CHECK: mov x0, #16 + +# CHECK-SYM: Name: v0 +# CHECK-SYM-NEXT: Value: 0x0 + +## Access variable in second partition +movz x0, #:tprel_g1:v1 +movk x0, #:tprel_g0_nc:v1 + +## TCB + 65536 across movz and movk +# CHECK-NEXT: mov x0, #65536 +# CHECK-NEXT: movk x0, #16 + +# CHECK-SYM: Name: v1 +# CHECK-SYM-NEXT: Value: 0x10000 + +## Access variable in third partition +movz x0, #:tprel_g2:v2 +movk x0, #:tprel_g1_nc:v2 +movk x0, #:tprel_g0_nc:v2 + +## TCB + 65536 + 4294967296 across movz and 2 movk instructions +# CHECK-NEXT: mov x0, #4294967296 +# CHECK-NEXT: movk x0, #1, lsl #16 +# CHECK-NEXT: movk x0, #16 + +# CHECK-SYM: Name: v2 +# CHECK-SYM-NEXT: Value: 0x100010000 + +.section .tbss,"awT",@nobits +.balign 16 +v0: +.quad 0 +.space 0x10000 - 8 +v1: +.quad 0 +.space 0x100000000 - 8 +v2: +.quad 0 |