Skip to content

Commit c2ffa88

Browse files
committed
[PAC][CodeGen][ELF][AArch64] Support signed GOT with tiny code model
Support the following relocations and assembly operators: - `R_AARCH64_AUTH_GOT_ADR_PREL_LO21` (`:got_auth:` for `adr`) - `R_AARCH64_AUTH_GOT_LD_PREL19` (`:got_auth:` for `ldr`) `LOADgotAUTH` pseudo-instruction is expanded to actual instruction sequence like the following. ``` adr x16, :got_auth:sym ldr x0, [x16] autia x0, x16 ``` Both SelectionDAG and GlobalISel are suppported. For FastISel, we fall back to SelectionDAG. Tests starting with 'ptrauth-' have corresponding variants w/o this prefix.
1 parent a5688e5 commit c2ffa88

File tree

8 files changed

+455
-19
lines changed

8 files changed

+455
-19
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,28 +2277,40 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
22772277
const MachineOperand &GAMO = MI.getOperand(1);
22782278
assert(GAMO.getOffset() == 0);
22792279

2280-
MachineOperand GAHiOp(GAMO);
2281-
MachineOperand GALoOp(GAMO);
2282-
GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
2283-
GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
2280+
if (MI.getParent()->getParent()->getTarget().getCodeModel() ==
2281+
CodeModel::Tiny) {
2282+
MCOperand GAMC;
2283+
MCInstLowering.lowerOperand(GAMO, GAMC);
2284+
EmitToStreamer(
2285+
MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addOperand(GAMC));
2286+
EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2287+
.addReg(AuthResultReg)
2288+
.addReg(AArch64::X17)
2289+
.addImm(0));
2290+
} else {
2291+
MachineOperand GAHiOp(GAMO);
2292+
MachineOperand GALoOp(GAMO);
2293+
GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
2294+
GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
22842295

2285-
MCOperand GAMCHi, GAMCLo;
2286-
MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
2287-
MCInstLowering.lowerOperand(GALoOp, GAMCLo);
2296+
MCOperand GAMCHi, GAMCLo;
2297+
MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
2298+
MCInstLowering.lowerOperand(GALoOp, GAMCLo);
22882299

2289-
EmitToStreamer(
2290-
MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi));
2300+
EmitToStreamer(
2301+
MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi));
22912302

2292-
EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2293-
.addReg(AArch64::X17)
2294-
.addReg(AArch64::X17)
2295-
.addOperand(GAMCLo)
2296-
.addImm(0));
2303+
EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2304+
.addReg(AArch64::X17)
2305+
.addReg(AArch64::X17)
2306+
.addOperand(GAMCLo)
2307+
.addImm(0));
22972308

2298-
EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2299-
.addReg(AuthResultReg)
2300-
.addReg(AArch64::X17)
2301-
.addImm(0));
2309+
EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2310+
.addReg(AuthResultReg)
2311+
.addReg(AArch64::X17)
2312+
.addImm(0));
2313+
}
23022314

23032315
assert(GAMO.isGlobal());
23042316
MCSymbol *UndefWeakSym;

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3353,7 +3353,13 @@ ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
33533353
// No modifier was specified at all; this is the syntax for an ELF basic
33543354
// ADR relocation (unfortunately).
33553355
Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
3356-
} else {
3356+
} else if (ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE) {
3357+
// For tiny code model, we use :got_auth: operator to fill 21-bit imm of
3358+
// adr. It's not actually GOT entry page address but the GOT address
3359+
// itself - we just share the same variant kind with :got_auth: operator
3360+
// applied for adrp.
3361+
// TODO: can we somehow get current TargetMachine object to call
3362+
// getCodeModel() on it to ensure we are using tiny code model?
33573363
return Error(S, "unexpected adr label");
33583364
}
33593365
}

llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
147147
}
148148
return ELF::R_AARCH64_PREL64;
149149
case AArch64::fixup_aarch64_pcrel_adr_imm21:
150+
if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) {
151+
if (IsILP32) {
152+
Ctx.reportError(Fixup.getLoc(),
153+
"ILP32 ADR AUTH relocation not supported "
154+
"(LP64 eqv: AUTH_GOT_ADR_PREL_LO21)");
155+
return ELF::R_AARCH64_NONE;
156+
}
157+
return ELF::R_AARCH64_AUTH_GOT_ADR_PREL_LO21;
158+
}
150159
if (SymLoc != AArch64MCExpr::VK_ABS)
151160
Ctx.reportError(Fixup.getLoc(),
152161
"invalid symbol kind for ADR relocation");
@@ -190,6 +199,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
190199
return R_CLS(TLSIE_LD_GOTTPREL_PREL19);
191200
if (SymLoc == AArch64MCExpr::VK_GOT)
192201
return R_CLS(GOT_LD_PREL19);
202+
if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) {
203+
if (IsILP32) {
204+
Ctx.reportError(Fixup.getLoc(),
205+
"ILP32 LDR AUTH relocation not supported "
206+
"(LP64 eqv: AUTH_GOT_LD_PREL19)");
207+
return ELF::R_AARCH64_NONE;
208+
}
209+
return ELF::R_AARCH64_AUTH_GOT_LD_PREL19;
210+
}
193211
return R_CLS(LD_PREL_LO19);
194212
case AArch64::fixup_aarch64_pcrel_branch14:
195213
return R_CLS(TSTBR14);

llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic \
1414
; RUN: -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
1515

16+
; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=tiny -mattr=+pauth -mattr=+fpac -o - %s | \
17+
; RUN: FileCheck --check-prefixes=CHECK-TINY,NOTRAP-TINY %s
18+
; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=tiny -mattr=+pauth -o - %s | \
19+
; RUN: FileCheck --check-prefixes=CHECK-TINY,TRAP-TINY %s
20+
1621
;; Note: for FastISel, we fall back to SelectionDAG
1722

1823
declare extern_weak dso_local i32 @var()
@@ -41,6 +46,24 @@ define ptr @foo() {
4146
; TRAP-NEXT: .Lauth_success_0:
4247
; TRAP-NEXT: mov x0, x16
4348
; CHECK-NEXT: ret
49+
50+
; CHECK-TINY-LABEL: foo:
51+
; CHECK-TINY: adr x17, :got_auth:var
52+
; NOTRAP-TINY-NEXT: ldr x0, [x17]
53+
; NOTRAP-TINY-NEXT: cbz x0, .Lundef_weak0
54+
; NOTRAP-TINY-NEXT: autia x0, x17
55+
; TRAP-TINY-NEXT: ldr x16, [x17]
56+
; TRAP-TINY-NEXT: cbz x16, .Lundef_weak0
57+
; TRAP-TINY-NEXT: autia x16, x17
58+
; CHECK-TINY-NEXT: .Lundef_weak0:
59+
; TRAP-TINY-NEXT: mov x17, x16
60+
; TRAP-TINY-NEXT: xpaci x17
61+
; TRAP-TINY-NEXT: cmp x16, x17
62+
; TRAP-TINY-NEXT: b.eq .Lauth_success_0
63+
; TRAP-TINY-NEXT: brk #0xc470
64+
; TRAP-TINY-NEXT: .Lauth_success_0:
65+
; TRAP-TINY-NEXT: mov x0, x16
66+
; CHECK-TINY-NEXT: ret
4467
}
4568

4669
@arr_var = extern_weak global [10 x i32]
@@ -68,6 +91,25 @@ define ptr @bar() {
6891
; TRAP-NEXT: mov x8, x16
6992
; CHECK-NEXT: add x0, x8, #20
7093
; CHECK-NEXT: ret
94+
95+
; CHECK-TINY-LABEL: bar:
96+
; CHECK-TINY: adr x17, :got_auth:arr_var
97+
; NOTRAP-TINY-NEXT: ldr x8, [x17]
98+
; NOTRAP-TINY-NEXT: cbz x8, .Lundef_weak1
99+
; NOTRAP-TINY-NEXT: autda x8, x17
100+
; TRAP-TINY-NEXT: ldr x16, [x17]
101+
; TRAP-TINY-NEXT: cbz x16, .Lundef_weak1
102+
; TRAP-TINY-NEXT: autda x16, x17
103+
; CHECK-TINY-NEXT: .Lundef_weak1:
104+
; TRAP-TINY-NEXT: mov x17, x16
105+
; TRAP-TINY-NEXT: xpacd x17
106+
; TRAP-TINY-NEXT: cmp x16, x17
107+
; TRAP-TINY-NEXT: b.eq .Lauth_success_1
108+
; TRAP-TINY-NEXT: brk #0xc472
109+
; TRAP-TINY-NEXT: .Lauth_success_1:
110+
; TRAP-TINY-NEXT: mov x8, x16
111+
; CHECK-TINY-NEXT: add x0, x8, #20
112+
; CHECK-TINY-NEXT: ret
71113
}
72114

73115
!llvm.module.flags = !{!0}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
2+
; RUN: -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
3+
; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \
4+
; RUN: -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,TRAP %s
5+
6+
; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
7+
; RUN: -relocation-model=pic -fast-isel < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
8+
; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \
9+
; RUN: -relocation-model=pic -fast-isel < %s | FileCheck --check-prefixes=CHECK,TRAP %s
10+
11+
; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
12+
; RUN: -relocation-model=pic -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
13+
; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \
14+
; RUN: -relocation-model=pic -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,TRAP %s
15+
16+
; Note: fast-isel tests here will fall back to isel
17+
18+
@src = external local_unnamed_addr global [65536 x i8], align 1
19+
@dst = external global [65536 x i8], align 1
20+
@ptr = external local_unnamed_addr global ptr, align 8
21+
22+
define dso_preemptable void @foo1() {
23+
; CHECK-LABEL: foo1:
24+
; CHECK: // %bb.0: // %entry
25+
; CHECK-NEXT: adr x17, :got_auth:src
26+
; NOTRAP-NEXT: ldr x8, [x17]
27+
; NOTRAP-NEXT: autda x8, x17
28+
; TRAP-NEXT: ldr x16, [x17]
29+
; TRAP-NEXT: autda x16, x17
30+
; TRAP-NEXT: mov x17, x16
31+
; TRAP-NEXT: xpacd x17
32+
; TRAP-NEXT: cmp x16, x17
33+
; TRAP-NEXT: b.eq .Lauth_success_0
34+
; TRAP-NEXT: brk #0xc472
35+
; TRAP-NEXT: .Lauth_success_0:
36+
; TRAP-NEXT: mov x8, x16
37+
; CHECK-NEXT: ldrb w8, [x8]
38+
; CHECK-NEXT: adr x17, :got_auth:dst
39+
; NOTRAP-NEXT: ldr x9, [x17]
40+
; NOTRAP-NEXT: autda x9, x17
41+
; TRAP-NEXT: ldr x16, [x17]
42+
; TRAP-NEXT: autda x16, x17
43+
; TRAP-NEXT: mov x17, x16
44+
; TRAP-NEXT: xpacd x17
45+
; TRAP-NEXT: cmp x16, x17
46+
; TRAP-NEXT: b.eq .Lauth_success_1
47+
; TRAP-NEXT: brk #0xc472
48+
; TRAP-NEXT: .Lauth_success_1:
49+
; TRAP-NEXT: mov x9, x16
50+
; CHECK-NEXT: strb w8, [x9]
51+
; CHECK-NEXT: ret
52+
53+
entry:
54+
%0 = load i8, ptr @src, align 1
55+
store i8 %0, ptr @dst, align 1
56+
ret void
57+
}
58+
59+
define dso_preemptable void @foo2() {
60+
; CHECK-LABEL: foo2:
61+
; CHECK: // %bb.0: // %entry
62+
; CHECK-NEXT: adr x17, :got_auth:ptr
63+
; NOTRAP-NEXT: ldr x8, [x17]
64+
; NOTRAP-NEXT: autda x8, x17
65+
; TRAP-NEXT: ldr x16, [x17]
66+
; TRAP-NEXT: autda x16, x17
67+
; TRAP-NEXT: mov x17, x16
68+
; TRAP-NEXT: xpacd x17
69+
; TRAP-NEXT: cmp x16, x17
70+
; TRAP-NEXT: b.eq .Lauth_success_2
71+
; TRAP-NEXT: brk #0xc472
72+
; TRAP-NEXT: .Lauth_success_2:
73+
; TRAP-NEXT: mov x8, x16
74+
; CHECK-NEXT: adr x17, :got_auth:dst
75+
; NOTRAP-NEXT: ldr x9, [x17]
76+
; NOTRAP-NEXT: autda x9, x17
77+
; TRAP-NEXT: ldr x16, [x17]
78+
; TRAP-NEXT: autda x16, x17
79+
; TRAP-NEXT: mov x17, x16
80+
; TRAP-NEXT: xpacd x17
81+
; TRAP-NEXT: cmp x16, x17
82+
; TRAP-NEXT: b.eq .Lauth_success_3
83+
; TRAP-NEXT: brk #0xc472
84+
; TRAP-NEXT: .Lauth_success_3:
85+
; TRAP-NEXT: mov x9, x16
86+
; CHECK-NEXT: str x9, [x8]
87+
; CHECK-NEXT: ret
88+
89+
entry:
90+
store ptr @dst, ptr @ptr, align 8
91+
ret void
92+
}
93+
94+
define dso_preemptable void @foo3() {
95+
; CHECK-LABEL: foo3:
96+
; CHECK: // %bb.0: // %entry
97+
; CHECK-NEXT: adr x17, :got_auth:src
98+
; NOTRAP-NEXT: ldr x8, [x17]
99+
; NOTRAP-NEXT: autda x8, x17
100+
; TRAP-NEXT: ldr x16, [x17]
101+
; TRAP-NEXT: autda x16, x17
102+
; TRAP-NEXT: mov x17, x16
103+
; TRAP-NEXT: xpacd x17
104+
; TRAP-NEXT: cmp x16, x17
105+
; TRAP-NEXT: b.eq .Lauth_success_4
106+
; TRAP-NEXT: brk #0xc472
107+
; TRAP-NEXT: .Lauth_success_4:
108+
; TRAP-NEXT: mov x8, x16
109+
; CHECK-NEXT: ldrb w8, [x8]
110+
; CHECK-NEXT: adr x17, :got_auth:ptr
111+
; NOTRAP-NEXT: ldr x9, [x17]
112+
; NOTRAP-NEXT: autda x9, x17
113+
; TRAP-NEXT: ldr x16, [x17]
114+
; TRAP-NEXT: autda x16, x17
115+
; TRAP-NEXT: mov x17, x16
116+
; TRAP-NEXT: xpacd x17
117+
; TRAP-NEXT: cmp x16, x17
118+
; TRAP-NEXT: b.eq .Lauth_success_5
119+
; TRAP-NEXT: brk #0xc472
120+
; TRAP-NEXT: .Lauth_success_5:
121+
; TRAP-NEXT: mov x9, x16
122+
; CHECK-NEXT: ldr x9, [x9]
123+
; CHECK-NEXT: strb w8, [x9]
124+
; CHECK-NEXT: ret
125+
126+
entry:
127+
%0 = load i8, ptr @src, align 1
128+
%1 = load ptr, ptr @ptr, align 8
129+
store i8 %0, ptr %1, align 1
130+
ret void
131+
}
132+
133+
@lsrc = internal global i8 0, align 4
134+
@ldst = internal global i8 0, align 4
135+
@lptr = internal global ptr null, align 8
136+
137+
declare void @func(...)
138+
139+
define dso_preemptable ptr @externfuncaddr() {
140+
; CHECK-LABEL: externfuncaddr:
141+
; CHECK: // %bb.0: // %entry
142+
; CHECK-NEXT: adr x17, :got_auth:func
143+
; NOTRAP-NEXT: ldr x0, [x17]
144+
; NOTRAP-NEXT: autia x0, x17
145+
; TRAP-NEXT: ldr x16, [x17]
146+
; TRAP-NEXT: autia x16, x17
147+
; TRAP-NEXT: mov x17, x16
148+
; TRAP-NEXT: xpaci x17
149+
; TRAP-NEXT: cmp x16, x17
150+
; TRAP-NEXT: b.eq .Lauth_success_6
151+
; TRAP-NEXT: brk #0xc470
152+
; TRAP-NEXT: .Lauth_success_6:
153+
; TRAP-NEXT: mov x0, x16
154+
; CHECK-NEXT: ret
155+
156+
entry:
157+
ret ptr @func
158+
}
159+
160+
define dso_preemptable ptr @localfuncaddr() {
161+
; CHECK-LABEL: localfuncaddr:
162+
; CHECK: // %bb.0: // %entry
163+
; CHECK-NEXT: adr x17, :got_auth:externfuncaddr
164+
; NOTRAP-NEXT: ldr x0, [x17]
165+
; NOTRAP-NEXT: autia x0, x17
166+
; TRAP-NEXT: ldr x16, [x17]
167+
; TRAP-NEXT: autia x16, x17
168+
; TRAP-NEXT: mov x17, x16
169+
; TRAP-NEXT: xpaci x17
170+
; TRAP-NEXT: cmp x16, x17
171+
; TRAP-NEXT: b.eq .Lauth_success_7
172+
; TRAP-NEXT: brk #0xc470
173+
; TRAP-NEXT: .Lauth_success_7:
174+
; TRAP-NEXT: mov x0, x16
175+
; CHECK-NEXT: ret
176+
177+
entry:
178+
ret ptr @externfuncaddr
179+
}
180+
181+
!llvm.module.flags = !{!0}
182+
!0 = !{i32 8, !"ptrauth-elf-got", i32 1}

0 commit comments

Comments
 (0)