Skip to content

Commit 48a2a0d

Browse files
committed
[PAC][lld][AArch64][ELF] Support signed TLSDESC
Support `R_AARCH64_AUTH_TLSDESC_ADR_PAGE21`, `R_AARCH64_AUTH_TLSDESC_LD64_LO12` and `R_AARCH64_AUTH_TLSDESC_LD64_LO12` static TLSDESC relocations.
1 parent 0d23449 commit 48a2a0d

File tree

7 files changed

+190
-2
lines changed

7 files changed

+190
-2
lines changed

lld/ELF/Arch/AArch64.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,14 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
157157
return R_AARCH64_AUTH;
158158
case R_AARCH64_TLSDESC_ADR_PAGE21:
159159
return R_AARCH64_TLSDESC_PAGE;
160+
case R_AARCH64_AUTH_TLSDESC_ADR_PAGE21:
161+
return R_AARCH64_AUTH_TLSDESC_PAGE;
160162
case R_AARCH64_TLSDESC_LD64_LO12:
161163
case R_AARCH64_TLSDESC_ADD_LO12:
162164
return R_TLSDESC;
165+
case R_AARCH64_AUTH_TLSDESC_LD64_LO12:
166+
case R_AARCH64_AUTH_TLSDESC_ADD_LO12:
167+
return RelExpr::R_AARCH64_AUTH_TLSDESC;
163168
case R_AARCH64_TLSDESC_CALL:
164169
return R_TLSDESC_CALL;
165170
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
@@ -543,6 +548,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
543548
case R_AARCH64_ADR_PREL_PG_HI21:
544549
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
545550
case R_AARCH64_TLSDESC_ADR_PAGE21:
551+
case R_AARCH64_AUTH_TLSDESC_ADR_PAGE21:
546552
checkInt(ctx, loc, val, 33, rel);
547553
[[fallthrough]];
548554
case R_AARCH64_ADR_PREL_PG_HI21_NC:
@@ -593,6 +599,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
593599
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
594600
case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
595601
case R_AARCH64_TLSDESC_LD64_LO12:
602+
case R_AARCH64_AUTH_TLSDESC_LD64_LO12:
596603
checkAlignment(ctx, loc, val, 8, rel);
597604
write32Imm12(loc, getBits(val, 3, 11));
598605
break;
@@ -667,6 +674,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
667674
break;
668675
case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
669676
case R_AARCH64_TLSDESC_ADD_LO12:
677+
case R_AARCH64_AUTH_TLSDESC_ADD_LO12:
670678
write32Imm12(loc, val);
671679
break;
672680
case R_AARCH64_TLSDESC:

lld/ELF/InputSection.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,12 +935,14 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
935935
case R_SIZE:
936936
return r.sym->getSize() + a;
937937
case R_TLSDESC:
938+
case RelExpr::R_AARCH64_AUTH_TLSDESC:
938939
return ctx.in.got->getTlsDescAddr(*r.sym) + a;
939940
case R_TLSDESC_PC:
940941
return ctx.in.got->getTlsDescAddr(*r.sym) + a - p;
941942
case R_TLSDESC_GOTPLT:
942943
return ctx.in.got->getTlsDescAddr(*r.sym) + a - ctx.in.gotPlt->getVA();
943944
case R_AARCH64_TLSDESC_PAGE:
945+
case R_AARCH64_AUTH_TLSDESC_PAGE:
944946
return getAArch64Page(ctx.in.got->getTlsDescAddr(*r.sym) + a) -
945947
getAArch64Page(p);
946948
case R_LOONGARCH_TLSDESC_PAGE_PC:

lld/ELF/Relocations.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,36 @@ unsigned RelocationScanner::handleTlsRelocation(RelExpr expr, RelType type,
13551355
return 1;
13561356
}
13571357

1358+
auto fatalBothAuthAndNonAuth = [&sym]() {
1359+
fatal("both AUTH and non-AUTH TLSDESC entries for '" + sym.getName() +
1360+
"' requested, but only one type of TLSDESC entry per symbol is "
1361+
"supported");
1362+
};
1363+
1364+
// Do not optimize signed TLSDESC as described in pauthabielf64 to LE/IE.
1365+
// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#general-restrictions
1366+
// > PAUTHELF64 only supports the descriptor based TLS (TLSDESC).
1367+
if (oneof<R_AARCH64_AUTH_TLSDESC_PAGE, RelExpr::R_AARCH64_AUTH_TLSDESC>(
1368+
expr)) {
1369+
assert(ctx.arg.emachine == EM_AARCH64);
1370+
if (!sym.hasFlag(NEEDS_TLSDESC))
1371+
sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_AUTH);
1372+
else if (!sym.hasFlag(NEEDS_TLSDESC_AUTH))
1373+
fatalBothAuthAndNonAuth();
1374+
sec->addReloc({expr, type, offset, addend, &sym});
1375+
return 1;
1376+
}
1377+
1378+
if (sym.hasFlag(NEEDS_TLSDESC_AUTH)) {
1379+
assert(ctx.arg.emachine == EM_AARCH64);
1380+
// TLSDESC_CALL hint relocation probably should not be emitted by compiler
1381+
// with signed TLSDESC enabled since it does not give any value, but leave a
1382+
// check against that just in case someone uses it.
1383+
if (expr != R_TLSDESC_CALL)
1384+
fatalBothAuthAndNonAuth();
1385+
return 1;
1386+
}
1387+
13581388
bool isRISCV = ctx.arg.emachine == EM_RISCV;
13591389

13601390
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
@@ -1855,9 +1885,13 @@ void elf::postScanRelocations(Ctx &ctx) {
18551885

18561886
if (flags & NEEDS_TLSDESC) {
18571887
got->addTlsDescEntry(sym);
1888+
RelType tlsDescRel = ctx.target->tlsDescRel;
1889+
if (flags & NEEDS_TLSDESC_AUTH) {
1890+
assert(ctx.arg.emachine == EM_AARCH64);
1891+
tlsDescRel = ELF::R_AARCH64_AUTH_TLSDESC;
1892+
}
18581893
ctx.mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
1859-
ctx.target->tlsDescRel, *got, got->getTlsDescOffset(sym), sym,
1860-
ctx.target->tlsDescRel);
1894+
tlsDescRel, *got, got->getTlsDescOffset(sym), sym, tlsDescRel);
18611895
}
18621896
if (flags & NEEDS_TLSGD) {
18631897
got->addDynTlsEntry(sym);

lld/ELF/Relocations.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ enum RelExpr {
9292
R_AARCH64_PAGE_PC,
9393
R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC,
9494
R_AARCH64_TLSDESC_PAGE,
95+
R_AARCH64_AUTH_TLSDESC_PAGE,
96+
// TODO: maybe it's better to rename this expression
97+
// to avoid name conflict with dynamic reloc
98+
R_AARCH64_AUTH_TLSDESC,
9599
R_AARCH64_AUTH,
96100
R_ARM_PCA,
97101
R_ARM_SBREL,

lld/ELF/Symbols.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ enum {
5555
NEEDS_GOT_DTPREL = 1 << 7,
5656
NEEDS_TLSIE = 1 << 8,
5757
NEEDS_GOT_AUTH = 1 << 9,
58+
NEEDS_TLSDESC_AUTH = 1 << 10,
5859
};
5960

6061
// The base class for real symbol classes.

lld/ELF/SyntheticSections.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,11 @@ bool GotSection::addTlsDescEntry(const Symbol &sym) {
672672
assert(sym.auxIdx == ctx.symAux.size() - 1);
673673
ctx.symAux.back().tlsDescIdx = numEntries;
674674
numEntries += 2;
675+
if (sym.hasFlag(NEEDS_TLSDESC_AUTH)) {
676+
assert(ctx.arg.emachine == EM_AARCH64);
677+
authEntries.push_back({(numEntries - 2) * ctx.arg.wordsize, true});
678+
authEntries.push_back({(numEntries - 1) * ctx.arg.wordsize, false});
679+
}
675680
return true;
676681
}
677682

lld/test/ELF/aarch64-tlsdesc-pauth.s

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// REQUIRES: aarch64
2+
// RUN: rm -rf %t && split-file %s %t && cd %t
3+
4+
//--- a.s
5+
6+
.section .tbss,"awT",@nobits
7+
.global a
8+
a:
9+
.xword 0
10+
11+
//--- ok.s
12+
13+
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth ok.s -o ok.o
14+
// RUN: ld.lld -shared ok.o -o ok.so
15+
// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn ok.so | \
16+
// RUN: FileCheck -DP=20 -DA=896 -DB=912 -DC=928 %s
17+
// RUN: llvm-readobj -r -x .got ok.so | FileCheck --check-prefix=REL \
18+
// RUN: -DP1=20 -DA1=380 -DB1=390 -DC1=3A0 -DP2=020 -DA2=380 -DB2=390 -DC2=3a0 %s
19+
20+
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth a.s -o a.so.o
21+
// RUN: ld.lld -shared a.so.o -soname=so -o a.so
22+
// RUN: ld.lld ok.o a.so -o ok
23+
// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn ok | \
24+
// RUN: FileCheck -DP=220 -DA=936 -DB=952 -DC=968 %s
25+
// RUN: llvm-readobj -r -x .got ok | FileCheck --check-prefix=REL \
26+
// RUN: -DP1=220 -DA1=3A8 -DB1=3B8 -DC1=3C8 -DP2=220 -DA2=3a8 -DB2=3b8 -DC2=3c8 %s
27+
28+
.text
29+
adrp x0, :tlsdesc_auth:a
30+
ldr x16, [x0, :tlsdesc_auth_lo12:a]
31+
add x0, x0, :tlsdesc_auth_lo12:a
32+
.tlsdesccall a
33+
blraa x16, x0
34+
35+
// CHECK: adrp x0, 0x[[P]]000
36+
// CHECK-NEXT: ldr x16, [x0, #[[A]]]
37+
// CHECK-NEXT: add x0, x0, #[[A]]
38+
// CHECK-NEXT: blraa x16, x0
39+
40+
// Create relocation against local TLS symbols where linker should
41+
// create target specific dynamic TLSDESC relocation where addend is
42+
// the symbol VMA in tls block.
43+
44+
adrp x0, :tlsdesc_auth:local1
45+
ldr x16, [x0, :tlsdesc_auth_lo12:local1]
46+
add x0, x0, :tlsdesc_auth_lo12:local1
47+
.tlsdesccall local1
48+
blraa x16, x0
49+
50+
// CHECK: adrp x0, 0x[[P]]000
51+
// CHECK-NEXT: ldr x16, [x0, #[[B]]]
52+
// CHECK-NEXT: add x0, x0, #[[B]]
53+
// CHECK-NEXT: blraa x16, x0
54+
55+
adrp x0, :tlsdesc_auth:local2
56+
ldr x16, [x0, :tlsdesc_auth_lo12:local2]
57+
add x0, x0, :tlsdesc_auth_lo12:local2
58+
.tlsdesccall local2
59+
blraa x16, x0
60+
61+
// CHECK: adrp x0, 0x[[P]]000
62+
// CHECK-NEXT: ldr x16, [x0, #[[C]]]
63+
// CHECK-NEXT: add x0, x0, #[[C]]
64+
// CHECK-NEXT: blraa x16, x0
65+
66+
.section .tbss,"awT",@nobits
67+
.type local1,@object
68+
.p2align 2
69+
local1:
70+
.word 0
71+
.size local1, 4
72+
73+
.type local2,@object
74+
.p2align 3
75+
local2:
76+
.xword 0
77+
.size local2, 8
78+
79+
80+
// R_AARCH64_AUTH_TLSDESC - 0x0 -> start of tls block
81+
// R_AARCH64_AUTH_TLSDESC - 0x8 -> align (sizeof (local1), 8)
82+
83+
// REL: Relocations [
84+
// REL-NEXT: Section (5) .rela.dyn {
85+
// REL-NEXT: 0x[[P1]][[B1]] R_AARCH64_AUTH_TLSDESC - 0x0
86+
// REL-NEXT: 0x[[P1]][[C1]] R_AARCH64_AUTH_TLSDESC - 0x8
87+
// REL-NEXT: 0x[[P1]][[A1]] R_AARCH64_AUTH_TLSDESC a 0x0
88+
// REL-NEXT: }
89+
// REL-NEXT: ]
90+
91+
// REL: Hex dump of section '.got':
92+
// REL-NEXT: 0x00[[P2]][[A2]] 00000000 00000080 00000000 000000a0
93+
// REL-NEXT: 0x00[[P2]][[B2]] 00000000 00000080 00000000 000000a0
94+
// REL-NEXT: 0x00[[P2]][[C2]] 00000000 00000080 00000000 000000a0
95+
// ^^
96+
// 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA
97+
// ^^
98+
// 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA
99+
100+
//--- err1.s
101+
102+
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth err1.s -o err1.o
103+
// RUN: not ld.lld -shared err1.o -o err1.so 2>&1 | FileCheck --check-prefix=ERR1 %s
104+
// ERR1: error: both AUTH and non-AUTH TLSDESC entries for 'a' requested, but only one type of TLSDESC entry per symbol is supported
105+
.text
106+
adrp x0, :tlsdesc_auth:a
107+
ldr x16, [x0, :tlsdesc_auth_lo12:a]
108+
add x0, x0, :tlsdesc_auth_lo12:a
109+
.tlsdesccall a
110+
blraa x16, x0
111+
112+
adrp x0, :tlsdesc:a
113+
ldr x1, [x0, :tlsdesc_lo12:a]
114+
add x0, x0, :tlsdesc_lo12:a
115+
.tlsdesccall a
116+
blr x1
117+
118+
//--- err2.s
119+
120+
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth err2.s -o err2.o
121+
// RUN: not ld.lld -shared err2.o -o err2.so 2>&1 | FileCheck --check-prefix=ERR2 %s
122+
// ERR2: error: both AUTH and non-AUTH TLSDESC entries for 'a' requested, but only one type of TLSDESC entry per symbol is supported
123+
.text
124+
adrp x0, :tlsdesc:a
125+
ldr x1, [x0, :tlsdesc_lo12:a]
126+
add x0, x0, :tlsdesc_lo12:a
127+
.tlsdesccall a
128+
blr x1
129+
130+
adrp x0, :tlsdesc_auth:a
131+
ldr x16, [x0, :tlsdesc_auth_lo12:a]
132+
add x0, x0, :tlsdesc_auth_lo12:a
133+
.tlsdesccall a
134+
blraa x16, x0

0 commit comments

Comments
 (0)