Skip to content

Commit e1979ae

Browse files
committed
Implement gd to ie relaxation for aarch64.
llvm-svn: 271815
1 parent 69f5402 commit e1979ae

File tree

6 files changed

+91
-1
lines changed

6 files changed

+91
-1
lines changed

lld/ELF/InputSection.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,10 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
183183
case R_GOT_FROM_END:
184184
return Body.getGotOffset<ELFT>() + A -
185185
Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
186+
case R_RELAX_TLS_GD_TO_IE_ABS:
186187
case R_GOT:
187188
return Body.getGotVA<ELFT>() + A;
189+
case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
188190
case R_GOT_PAGE_PC:
189191
return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P);
190192
case R_RELAX_TLS_GD_TO_IE:
@@ -324,6 +326,8 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) {
324326
Target->relaxTlsGdToLe(BufLoc, Type, SymVA);
325327
break;
326328
case R_RELAX_TLS_GD_TO_IE:
329+
case R_RELAX_TLS_GD_TO_IE_ABS:
330+
case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
327331
case R_RELAX_TLS_GD_TO_IE_END:
328332
Target->relaxTlsGdToIe(BufLoc, Type, SymVA);
329333
break;

lld/ELF/Relocations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
156156
Body.getGotOffset<ELFT>(), false, &Body,
157157
0});
158158
}
159-
return 2;
159+
return Target->TlsGdRelaxSkip;
160160
}
161161
C.Relocations.push_back(
162162
{Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type,

lld/ELF/Relocations.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ enum RelExpr {
4343
R_RELAX_GOT_PC_NOPIC,
4444
R_RELAX_TLS_GD_TO_IE,
4545
R_RELAX_TLS_GD_TO_IE_END,
46+
R_RELAX_TLS_GD_TO_IE_ABS,
47+
R_RELAX_TLS_GD_TO_IE_PAGE_PC,
4648
R_RELAX_TLS_GD_TO_LE,
4749
R_RELAX_TLS_GD_TO_LE_NEG,
4850
R_RELAX_TLS_IE_TO_LE,

lld/ELF/Target.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,10 @@ class AArch64TargetInfo final : public TargetInfo {
156156
int32_t Index, unsigned RelOff) const override;
157157
bool usesOnlyLowPageBits(uint32_t Type) const override;
158158
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
159+
RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
160+
RelExpr Expr) const override;
159161
void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
162+
void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
160163
void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
161164
};
162165

@@ -1141,6 +1144,16 @@ RelExpr AArch64TargetInfo::getRelExpr(uint32_t Type,
11411144
}
11421145
}
11431146

1147+
RelExpr AArch64TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
1148+
RelExpr Expr) const {
1149+
if (Expr == R_RELAX_TLS_GD_TO_IE) {
1150+
if (Type == R_AARCH64_TLSDESC_ADR_PAGE21)
1151+
return R_RELAX_TLS_GD_TO_IE_PAGE_PC;
1152+
return R_RELAX_TLS_GD_TO_IE_ABS;
1153+
}
1154+
return Expr;
1155+
}
1156+
11441157
bool AArch64TargetInfo::usesOnlyLowPageBits(uint32_t Type) const {
11451158
switch (Type) {
11461159
default:
@@ -1320,6 +1333,7 @@ void AArch64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
13201333
// ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12_NC]
13211334
// add x0, x0, :tlsdesc_los:v [_AARCH64_TLSDESC_ADD_LO12_NC]
13221335
// .tlsdesccall [R_AARCH64_TLSDESC_CALL]
1336+
// blr x1
13231337
// And it can optimized to:
13241338
// movz x0, #0x0, lsl #16
13251339
// movk x0, #0x10
@@ -1348,6 +1362,38 @@ void AArch64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
13481362
write32le(Loc, NewInst);
13491363
}
13501364

1365+
void AArch64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
1366+
uint64_t Val) const {
1367+
// TLSDESC Global-Dynamic relocation are in the form:
1368+
// adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
1369+
// ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12_NC]
1370+
// add x0, x0, :tlsdesc_los:v [_AARCH64_TLSDESC_ADD_LO12_NC]
1371+
// .tlsdesccall [R_AARCH64_TLSDESC_CALL]
1372+
// blr x1
1373+
// And it can optimized to:
1374+
// adrp x0, :gottprel:v
1375+
// ldr x0, [x0, :gottprel_lo12:v]
1376+
// nop
1377+
// nop
1378+
1379+
switch (Type) {
1380+
case R_AARCH64_TLSDESC_ADD_LO12_NC:
1381+
case R_AARCH64_TLSDESC_CALL:
1382+
write32le(Loc, 0xd503201f); // nop
1383+
break;
1384+
case R_AARCH64_TLSDESC_ADR_PAGE21:
1385+
write32le(Loc, 0x90000000); // adrp
1386+
relocateOne(Loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, Val);
1387+
break;
1388+
case R_AARCH64_TLSDESC_LD64_LO12_NC:
1389+
write32le(Loc, 0xf9400000); // ldr
1390+
relocateOne(Loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, Val);
1391+
break;
1392+
default:
1393+
llvm_unreachable("unsupported Relocation for TLS GD to LE relax");
1394+
}
1395+
}
1396+
13511397
void AArch64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
13521398
uint64_t Val) const {
13531399
checkUInt<32>(Val, Type);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.section .tdata,"awT",@progbits
2+
.globl a
3+
a:
4+
.word 42

lld/test/ELF/aarch64-tls-gdie.s

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// REQUIRES: aarch64
2+
// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux
3+
// RUN: llvm-mc %p/Inputs/aarch64-tls-gdie.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux
4+
// RUN: ld.lld %t2.o -o %t2.so -shared
5+
// RUN: ld.lld %t.o %t2.so -o %t
6+
// RUN: llvm-readobj -s %t | FileCheck --check-prefix=SEC %s
7+
// RUN: llvm-objdump -d %t | FileCheck %s
8+
9+
.globl _start
10+
_start:
11+
nop
12+
adrp x0, :tlsdesc:a
13+
ldr x1, [x0, :tlsdesc_lo12:a]
14+
add x0, x0, :tlsdesc_lo12:a
15+
.tlsdesccall a
16+
blr x1
17+
18+
// SEC: Name: .got
19+
// SEC-NEXT: Type: SHT_PROGBITS
20+
// SEC-NEXT: Flags [
21+
// SEC-NEXT: SHF_ALLOC
22+
// SEC-NEXT: SHF_WRITE
23+
// SEC-NEXT: ]
24+
// SEC-NEXT: Address: 0x120B0
25+
26+
// page(0x120B0) - page(0x11004) = 4096
27+
// 0x0B0 = 176
28+
29+
// CHECK: _start:
30+
// CHECK-NEXT: 11000: {{.*}} nop
31+
// CHECK-NEXT: 11004: {{.*}} adrp x0, #4096
32+
// CHECK-NEXT: 11008: {{.*}} ldr x0, [x0, #176]
33+
// CHECK-NEXT: 1100c: {{.*}} nop
34+
// CHECK-NEXT: 11010: {{.*}} nop

0 commit comments

Comments
 (0)