diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-06-04 23:33:31 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-06-04 23:33:31 +0000 |
commit | 812fef1ded963b81ec6fa9dd96953df1adc814dc (patch) | |
tree | 0464c7f279a6f7a43c33a85d0bf38ca1d3d6dfe3 | |
parent | f7fa63f9963ea4a83b26318dfa7bea6de7b0e02c (diff) |
Implement gd to ie relaxation for aarch64.
git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@271815 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | ELF/InputSection.cpp | 4 | ||||
-rw-r--r-- | ELF/Relocations.cpp | 2 | ||||
-rw-r--r-- | ELF/Relocations.h | 2 | ||||
-rw-r--r-- | ELF/Target.cpp | 46 | ||||
-rw-r--r-- | test/ELF/Inputs/aarch64-tls-gdie.s | 4 | ||||
-rw-r--r-- | test/ELF/aarch64-tls-gdie.s | 34 |
6 files changed, 91 insertions, 1 deletions
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp index a90b3098a..713933c11 100644 --- a/ELF/InputSection.cpp +++ b/ELF/InputSection.cpp @@ -183,8 +183,10 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, case R_GOT_FROM_END: return Body.getGotOffset<ELFT>() + A - Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); + case R_RELAX_TLS_GD_TO_IE_ABS: case R_GOT: return Body.getGotVA<ELFT>() + A; + case R_RELAX_TLS_GD_TO_IE_PAGE_PC: case R_GOT_PAGE_PC: return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P); case R_RELAX_TLS_GD_TO_IE: @@ -324,6 +326,8 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) { Target->relaxTlsGdToLe(BufLoc, Type, SymVA); break; case R_RELAX_TLS_GD_TO_IE: + case R_RELAX_TLS_GD_TO_IE_ABS: + case R_RELAX_TLS_GD_TO_IE_PAGE_PC: case R_RELAX_TLS_GD_TO_IE_END: Target->relaxTlsGdToIe(BufLoc, Type, SymVA); break; diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 736e44748..3e59a0e2c 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -156,7 +156,7 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, Body.getGotOffset<ELFT>(), false, &Body, 0}); } - return 2; + return Target->TlsGdRelaxSkip; } C.Relocations.push_back( {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, diff --git a/ELF/Relocations.h b/ELF/Relocations.h index 8f6a5ce75..346122009 100644 --- a/ELF/Relocations.h +++ b/ELF/Relocations.h @@ -43,6 +43,8 @@ enum RelExpr { R_RELAX_GOT_PC_NOPIC, R_RELAX_TLS_GD_TO_IE, R_RELAX_TLS_GD_TO_IE_END, + R_RELAX_TLS_GD_TO_IE_ABS, + R_RELAX_TLS_GD_TO_IE_PAGE_PC, R_RELAX_TLS_GD_TO_LE, R_RELAX_TLS_GD_TO_LE_NEG, R_RELAX_TLS_IE_TO_LE, diff --git a/ELF/Target.cpp b/ELF/Target.cpp index 073e613b3..529abacae 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -156,7 +156,10 @@ public: int32_t Index, unsigned RelOff) const override; bool usesOnlyLowPageBits(uint32_t Type) const override; void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const override; void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; }; @@ -1141,6 +1144,16 @@ RelExpr AArch64TargetInfo::getRelExpr(uint32_t Type, } } +RelExpr AArch64TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const { + if (Expr == R_RELAX_TLS_GD_TO_IE) { + if (Type == R_AARCH64_TLSDESC_ADR_PAGE21) + return R_RELAX_TLS_GD_TO_IE_PAGE_PC; + return R_RELAX_TLS_GD_TO_IE_ABS; + } + return Expr; +} + bool AArch64TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { switch (Type) { default: @@ -1320,6 +1333,7 @@ void AArch64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12_NC] // add x0, x0, :tlsdesc_los:v [_AARCH64_TLSDESC_ADD_LO12_NC] // .tlsdesccall [R_AARCH64_TLSDESC_CALL] + // blr x1 // And it can optimized to: // movz x0, #0x0, lsl #16 // movk x0, #0x10 @@ -1348,6 +1362,38 @@ void AArch64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, write32le(Loc, NewInst); } +void AArch64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { + // TLSDESC Global-Dynamic relocation are in the form: + // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] + // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12_NC] + // add x0, x0, :tlsdesc_los:v [_AARCH64_TLSDESC_ADD_LO12_NC] + // .tlsdesccall [R_AARCH64_TLSDESC_CALL] + // blr x1 + // And it can optimized to: + // adrp x0, :gottprel:v + // ldr x0, [x0, :gottprel_lo12:v] + // nop + // nop + + switch (Type) { + case R_AARCH64_TLSDESC_ADD_LO12_NC: + case R_AARCH64_TLSDESC_CALL: + write32le(Loc, 0xd503201f); // nop + break; + case R_AARCH64_TLSDESC_ADR_PAGE21: + write32le(Loc, 0x90000000); // adrp + relocateOne(Loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, Val); + break; + case R_AARCH64_TLSDESC_LD64_LO12_NC: + write32le(Loc, 0xf9400000); // ldr + relocateOne(Loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, Val); + break; + default: + llvm_unreachable("unsupported Relocation for TLS GD to LE relax"); + } +} + void AArch64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { checkUInt<32>(Val, Type); diff --git a/test/ELF/Inputs/aarch64-tls-gdie.s b/test/ELF/Inputs/aarch64-tls-gdie.s new file mode 100644 index 000000000..289cae523 --- /dev/null +++ b/test/ELF/Inputs/aarch64-tls-gdie.s @@ -0,0 +1,4 @@ + .section .tdata,"awT",@progbits + .globl a +a: + .word 42 diff --git a/test/ELF/aarch64-tls-gdie.s b/test/ELF/aarch64-tls-gdie.s new file mode 100644 index 000000000..709cc53a8 --- /dev/null +++ b/test/ELF/aarch64-tls-gdie.s @@ -0,0 +1,34 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux +// RUN: llvm-mc %p/Inputs/aarch64-tls-gdie.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux +// RUN: ld.lld %t2.o -o %t2.so -shared +// RUN: ld.lld %t.o %t2.so -o %t +// RUN: llvm-readobj -s %t | FileCheck --check-prefix=SEC %s +// RUN: llvm-objdump -d %t | FileCheck %s + + .globl _start +_start: + nop + adrp x0, :tlsdesc:a + ldr x1, [x0, :tlsdesc_lo12:a] + add x0, x0, :tlsdesc_lo12:a + .tlsdesccall a + blr x1 + +// SEC: Name: .got +// SEC-NEXT: Type: SHT_PROGBITS +// SEC-NEXT: Flags [ +// SEC-NEXT: SHF_ALLOC +// SEC-NEXT: SHF_WRITE +// SEC-NEXT: ] +// SEC-NEXT: Address: 0x120B0 + +// page(0x120B0) - page(0x11004) = 4096 +// 0x0B0 = 176 + +// CHECK: _start: +// CHECK-NEXT: 11000: {{.*}} nop +// CHECK-NEXT: 11004: {{.*}} adrp x0, #4096 +// CHECK-NEXT: 11008: {{.*}} ldr x0, [x0, #176] +// CHECK-NEXT: 1100c: {{.*}} nop +// CHECK-NEXT: 11010: {{.*}} nop |