-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[PAC][CodeGen][ELF][AArch64] Support signed GOT with tiny code model #113812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This re-applies #96164 after revert in #102434. Support the following relocations and assembly operators: - `R_AARCH64_AUTH_ADR_GOT_PAGE` (`:got_auth:` for `adrp`) - `R_AARCH64_AUTH_LD64_GOT_LO12_NC` (`:got_auth_lo12:` for `ldr`) - `R_AARCH64_AUTH_GOT_ADD_LO12_NC` (`:got_auth_lo12:` for `add`) `LOADgotAUTH` pseudo-instruction is introduced which is later expanded to actual instruction sequence like the following. ``` adrp x16, :got_auth:sym add x16, x16, :got_auth_lo12:sym ldr x0, [x16] autia x0, x16 ``` If a resign is requested, like below, `LOADgotPAC` pseudo is used, and GOT load is lowered similarly to `LOADgotAUTH`. ``` @var = global i32 0 define ptr @resign_globalvar() { ret ptr ptrauth (ptr @var, i32 3, i64 43) } ``` If FPAC bit is not set and resign is requested, a check+trap sequence similar to one used for `AUT` pseudo is emitted. Both SelectionDAG and GlobalISel are suppported. For FastISel, we fall back to SelectionDAG. Tests starting with 'ptrauth-' have corresponding variants w/o this prefix. See also specification https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#appendix-signed-got
Before executing auth instruction on a signed address from a GOT slot, we must ensure that the address is not zero since zero addresses are not signed to preserve zero-checks working as expected. A GOT slot might be filled with zero when we have an undefined weak symbol.
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.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
@llvm/pr-subscribers-mc @llvm/pr-subscribers-backend-aarch64 Author: Daniil Kovalev (kovdan01) ChangesSupport the following relocations and assembly operators:
If FPAC bit is not set, a check+trap sequence similar to one used for Both SelectionDAG and GlobalISel are suppported. For FastISel, we fall Tests starting with 'ptrauth-' have corresponding variants w/o this prefix. Patch is 21.19 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113812.diff 8 Files Affected:
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index e79457f925db66..c2a7450ffb9132 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2277,28 +2277,40 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
const MachineOperand &GAMO = MI.getOperand(1);
assert(GAMO.getOffset() == 0);
- MachineOperand GAHiOp(GAMO);
- MachineOperand GALoOp(GAMO);
- GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
- GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+ if (MI.getParent()->getParent()->getTarget().getCodeModel() ==
+ CodeModel::Tiny) {
+ MCOperand GAMC;
+ MCInstLowering.lowerOperand(GAMO, GAMC);
+ EmitToStreamer(
+ MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addOperand(GAMC));
+ EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
+ .addReg(AuthResultReg)
+ .addReg(AArch64::X17)
+ .addImm(0));
+ } else {
+ MachineOperand GAHiOp(GAMO);
+ MachineOperand GALoOp(GAMO);
+ GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
+ GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
- MCOperand GAMCHi, GAMCLo;
- MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
- MCInstLowering.lowerOperand(GALoOp, GAMCLo);
+ MCOperand GAMCHi, GAMCLo;
+ MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
+ MCInstLowering.lowerOperand(GALoOp, GAMCLo);
- EmitToStreamer(
- MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi));
+ EmitToStreamer(
+ MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi));
- EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
- .addReg(AArch64::X17)
- .addReg(AArch64::X17)
- .addOperand(GAMCLo)
- .addImm(0));
+ EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
+ .addReg(AArch64::X17)
+ .addReg(AArch64::X17)
+ .addOperand(GAMCLo)
+ .addImm(0));
- EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
- .addReg(AuthResultReg)
- .addReg(AArch64::X17)
- .addImm(0));
+ EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
+ .addReg(AuthResultReg)
+ .addReg(AArch64::X17)
+ .addImm(0));
+ }
assert(GAMO.isGlobal());
MCSymbol *UndefWeakSym;
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index b83ca3f7e52db4..de8e0a4731e419 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -3353,7 +3353,13 @@ ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
// No modifier was specified at all; this is the syntax for an ELF basic
// ADR relocation (unfortunately).
Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
- } else {
+ } else if (ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE) {
+ // For tiny code model, we use :got_auth: operator to fill 21-bit imm of
+ // adr. It's not actually GOT entry page address but the GOT address
+ // itself - we just share the same variant kind with :got_auth: operator
+ // applied for adrp.
+ // TODO: can we somehow get current TargetMachine object to call
+ // getCodeModel() on it to ensure we are using tiny code model?
return Error(S, "unexpected adr label");
}
}
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index b5f5a58d96288e..04f90e21bb3b1f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -147,6 +147,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
}
return ELF::R_AARCH64_PREL64;
case AArch64::fixup_aarch64_pcrel_adr_imm21:
+ if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) {
+ if (IsILP32) {
+ Ctx.reportError(Fixup.getLoc(),
+ "ILP32 ADR AUTH relocation not supported "
+ "(LP64 eqv: AUTH_GOT_ADR_PREL_LO21)");
+ return ELF::R_AARCH64_NONE;
+ }
+ return ELF::R_AARCH64_AUTH_GOT_ADR_PREL_LO21;
+ }
if (SymLoc != AArch64MCExpr::VK_ABS)
Ctx.reportError(Fixup.getLoc(),
"invalid symbol kind for ADR relocation");
@@ -190,6 +199,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
return R_CLS(TLSIE_LD_GOTTPREL_PREL19);
if (SymLoc == AArch64MCExpr::VK_GOT)
return R_CLS(GOT_LD_PREL19);
+ if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) {
+ if (IsILP32) {
+ Ctx.reportError(Fixup.getLoc(),
+ "ILP32 LDR AUTH relocation not supported "
+ "(LP64 eqv: AUTH_GOT_LD_PREL19)");
+ return ELF::R_AARCH64_NONE;
+ }
+ return ELF::R_AARCH64_AUTH_GOT_LD_PREL19;
+ }
return R_CLS(LD_PREL_LO19);
case AArch64::fixup_aarch64_pcrel_branch14:
return R_CLS(TSTBR14);
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
index 5d0a3f556c4c2e..141af917fa3e2c 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
@@ -13,6 +13,11 @@
; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic \
; RUN: -mattr=+pauth -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=tiny -mattr=+pauth -mattr=+fpac -o - %s | \
+; RUN: FileCheck --check-prefixes=CHECK-TINY,NOTRAP-TINY %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=tiny -mattr=+pauth -o - %s | \
+; RUN: FileCheck --check-prefixes=CHECK-TINY,TRAP-TINY %s
+
;; Note: for FastISel, we fall back to SelectionDAG
declare extern_weak dso_local i32 @var()
@@ -41,6 +46,24 @@ define ptr @foo() {
; TRAP-NEXT: .Lauth_success_0:
; TRAP-NEXT: mov x0, x16
; CHECK-NEXT: ret
+
+; CHECK-TINY-LABEL: foo:
+; CHECK-TINY: adr x17, :got_auth:var
+; NOTRAP-TINY-NEXT: ldr x0, [x17]
+; NOTRAP-TINY-NEXT: cbz x0, .Lundef_weak0
+; NOTRAP-TINY-NEXT: autia x0, x17
+; TRAP-TINY-NEXT: ldr x16, [x17]
+; TRAP-TINY-NEXT: cbz x16, .Lundef_weak0
+; TRAP-TINY-NEXT: autia x16, x17
+; CHECK-TINY-NEXT: .Lundef_weak0:
+; TRAP-TINY-NEXT: mov x17, x16
+; TRAP-TINY-NEXT: xpaci x17
+; TRAP-TINY-NEXT: cmp x16, x17
+; TRAP-TINY-NEXT: b.eq .Lauth_success_0
+; TRAP-TINY-NEXT: brk #0xc470
+; TRAP-TINY-NEXT: .Lauth_success_0:
+; TRAP-TINY-NEXT: mov x0, x16
+; CHECK-TINY-NEXT: ret
}
@arr_var = extern_weak global [10 x i32]
@@ -68,6 +91,25 @@ define ptr @bar() {
; TRAP-NEXT: mov x8, x16
; CHECK-NEXT: add x0, x8, #20
; CHECK-NEXT: ret
+
+; CHECK-TINY-LABEL: bar:
+; CHECK-TINY: adr x17, :got_auth:arr_var
+; NOTRAP-TINY-NEXT: ldr x8, [x17]
+; NOTRAP-TINY-NEXT: cbz x8, .Lundef_weak1
+; NOTRAP-TINY-NEXT: autda x8, x17
+; TRAP-TINY-NEXT: ldr x16, [x17]
+; TRAP-TINY-NEXT: cbz x16, .Lundef_weak1
+; TRAP-TINY-NEXT: autda x16, x17
+; CHECK-TINY-NEXT: .Lundef_weak1:
+; TRAP-TINY-NEXT: mov x17, x16
+; TRAP-TINY-NEXT: xpacd x17
+; TRAP-TINY-NEXT: cmp x16, x17
+; TRAP-TINY-NEXT: b.eq .Lauth_success_1
+; TRAP-TINY-NEXT: brk #0xc472
+; TRAP-TINY-NEXT: .Lauth_success_1:
+; TRAP-TINY-NEXT: mov x8, x16
+; CHECK-TINY-NEXT: add x0, x8, #20
+; CHECK-TINY-NEXT: ret
}
!llvm.module.flags = !{!0}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
new file mode 100644
index 00000000000000..93b21c93418a64
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
@@ -0,0 +1,182 @@
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
+; RUN: -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \
+; RUN: -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
+; RUN: -relocation-model=pic -fast-isel < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \
+; RUN: -relocation-model=pic -fast-isel < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
+; RUN: -relocation-model=pic -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -code-model=tiny \
+; RUN: -relocation-model=pic -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; Note: fast-isel tests here will fall back to isel
+
+@src = external local_unnamed_addr global [65536 x i8], align 1
+@dst = external global [65536 x i8], align 1
+@ptr = external local_unnamed_addr global ptr, align 8
+
+define dso_preemptable void @foo1() {
+; CHECK-LABEL: foo1:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:src
+; NOTRAP-NEXT: ldr x8, [x17]
+; NOTRAP-NEXT: autda x8, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_0
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_0:
+; TRAP-NEXT: mov x8, x16
+; CHECK-NEXT: ldrb w8, [x8]
+; CHECK-NEXT: adr x17, :got_auth:dst
+; NOTRAP-NEXT: ldr x9, [x17]
+; NOTRAP-NEXT: autda x9, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_1
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_1:
+; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: strb w8, [x9]
+; CHECK-NEXT: ret
+
+entry:
+ %0 = load i8, ptr @src, align 1
+ store i8 %0, ptr @dst, align 1
+ ret void
+}
+
+define dso_preemptable void @foo2() {
+; CHECK-LABEL: foo2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:ptr
+; NOTRAP-NEXT: ldr x8, [x17]
+; NOTRAP-NEXT: autda x8, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_2
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_2:
+; TRAP-NEXT: mov x8, x16
+; CHECK-NEXT: adr x17, :got_auth:dst
+; NOTRAP-NEXT: ldr x9, [x17]
+; NOTRAP-NEXT: autda x9, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_3
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_3:
+; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: str x9, [x8]
+; CHECK-NEXT: ret
+
+entry:
+ store ptr @dst, ptr @ptr, align 8
+ ret void
+}
+
+define dso_preemptable void @foo3() {
+; CHECK-LABEL: foo3:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:src
+; NOTRAP-NEXT: ldr x8, [x17]
+; NOTRAP-NEXT: autda x8, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_4
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_4:
+; TRAP-NEXT: mov x8, x16
+; CHECK-NEXT: ldrb w8, [x8]
+; CHECK-NEXT: adr x17, :got_auth:ptr
+; NOTRAP-NEXT: ldr x9, [x17]
+; NOTRAP-NEXT: autda x9, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_5
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_5:
+; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: ldr x9, [x9]
+; CHECK-NEXT: strb w8, [x9]
+; CHECK-NEXT: ret
+
+entry:
+ %0 = load i8, ptr @src, align 1
+ %1 = load ptr, ptr @ptr, align 8
+ store i8 %0, ptr %1, align 1
+ ret void
+}
+
+@lsrc = internal global i8 0, align 4
+@ldst = internal global i8 0, align 4
+@lptr = internal global ptr null, align 8
+
+declare void @func(...)
+
+define dso_preemptable ptr @externfuncaddr() {
+; CHECK-LABEL: externfuncaddr:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:func
+; NOTRAP-NEXT: ldr x0, [x17]
+; NOTRAP-NEXT: autia x0, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autia x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpaci x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_6
+; TRAP-NEXT: brk #0xc470
+; TRAP-NEXT: .Lauth_success_6:
+; TRAP-NEXT: mov x0, x16
+; CHECK-NEXT: ret
+
+entry:
+ ret ptr @func
+}
+
+define dso_preemptable ptr @localfuncaddr() {
+; CHECK-LABEL: localfuncaddr:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:externfuncaddr
+; NOTRAP-NEXT: ldr x0, [x17]
+; NOTRAP-NEXT: autia x0, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autia x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpaci x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_7
+; TRAP-NEXT: brk #0xc470
+; TRAP-NEXT: .Lauth_success_7:
+; TRAP-NEXT: mov x0, x16
+; CHECK-NEXT: ret
+
+entry:
+ ret ptr @externfuncaddr
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll
new file mode 100644
index 00000000000000..2d098b70accccc
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll
@@ -0,0 +1,157 @@
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -mattr=+fpac \
+; RUN: -code-model=tiny < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \
+; RUN: -code-model=tiny < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -mattr=+fpac \
+; RUN: -code-model=tiny -fast-isel < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \
+; RUN: -code-model=tiny -fast-isel < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -mattr=+fpac \
+; RUN: -code-model=tiny -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \
+; RUN: -code-model=tiny -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; Note fast-isel tests here will fall back to isel
+
+@src = external local_unnamed_addr global [65536 x i8], align 1
+@dst = external global [65536 x i8], align 1
+@ptr = external local_unnamed_addr global ptr, align 8
+
+define dso_local void @foo1() {
+; CHECK-LABEL: foo1:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:src
+; NOTRAP-NEXT: ldr x8, [x17]
+; NOTRAP-NEXT: autda x8, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_0
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_0:
+; TRAP-NEXT: mov x8, x16
+; CHECK-NEXT: ldrb w8, [x8]
+; CHECK-NEXT: adr x17, :got_auth:dst
+; NOTRAP-NEXT: ldr x9, [x17]
+; NOTRAP-NEXT: autda x9, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_1
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_1:
+; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: strb w8, [x9]
+; CHECK-NEXT: ret
+
+entry:
+ %0 = load i8, ptr @src, align 1
+ store i8 %0, ptr @dst, align 1
+ ret void
+}
+
+define dso_local void @foo2() {
+; CHECK-LABEL: foo2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:ptr
+; NOTRAP-NEXT: ldr x8, [x17]
+; NOTRAP-NEXT: autda x8, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_2
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_2:
+; TRAP-NEXT: mov x8, x16
+; CHECK-NEXT: adr x17, :got_auth:dst
+; NOTRAP-NEXT: ldr x9, [x17]
+; NOTRAP-NEXT: autda x9, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_3
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_3:
+; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: str x9, [x8]
+; CHECK-NEXT: ret
+
+entry:
+ store ptr @dst, ptr @ptr, align 8
+ ret void
+}
+
+define dso_local void @foo3() {
+; CHECK-LABEL: foo3:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:src
+; NOTRAP-NEXT: ldr x8, [x17]
+; NOTRAP-NEXT: autda x8, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_4
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_4:
+; TRAP-NEXT: mov x8, x16
+; CHECK-NEXT: ldrb w8, [x8]
+; CHECK-NEXT: adr x17, :got_auth:ptr
+; NOTRAP-NEXT: ldr x9, [x17]
+; NOTRAP-NEXT: autda x9, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autda x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpacd x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_5
+; TRAP-NEXT: brk #0xc472
+; TRAP-NEXT: .Lauth_success_5:
+; TRAP-NEXT: mov x9, x16
+; CHECK-NEXT: ldr x9, [x9]
+; CHECK-NEXT: strb w8, [x9]
+; CHECK-NEXT: ret
+
+entry:
+ %0 = load i8, ptr @src, align 1
+ %1 = load ptr, ptr @ptr, align 8
+ store i8 %0, ptr %1, align 1
+ ret void
+}
+
+declare void @func(...)
+
+define dso_local ptr @externfuncaddr() {
+; CHECK-LABEL: externfuncaddr:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: adr x17, :got_auth:func
+; NOTRAP-NEXT: ldr x0, [x17]
+; NOTRAP-NEXT: autia x0, x17
+; TRAP-NEXT: ldr x16, [x17]
+; TRAP-NEXT: autia x16, x17
+; TRAP-NEXT: mov x17, x16
+; TRAP-NEXT: xpaci x17
+; TRAP-NEXT: cmp x16, x17
+; TRAP-NEXT: b.eq .Lauth_success_6
+; TRAP-NEXT: brk #0xc470
+; TRAP-NEXT: .Lauth_success_6:
+; TRAP-NEXT: mov x0, x16
+; CHECK-NEXT: ret
+
+entry:
+ ret ptr @func
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s
index f679bb4c82827b..5c04e899a7b22e 100644
--- a/llvm/test/MC/AArch64/arm64-elf-relocs.s
+++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s
@@ -331,6 +331,19 @@ trickQuestion:
// CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym
// CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym
+ adr x24, #:got_auth:sym
+ adr x24, :got_auth:sym
+ ldr x24, #:got_auth:sym
+ ldr x24, :got_auth:sym
+// CHEC...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, this seems fine as a translation of the spec. I still need to take another pass over the tests to be sure, but they seem appropriate so far.
All that said, I'm far from an expert on Aarch64 minutiae, so a more experienced reviewer here will have to provide any final approval.
if (MI.getParent()->getParent()->getTarget().getCodeModel() == | ||
CodeModel::Tiny) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (MI.getParent()->getParent()->getTarget().getCodeModel() == | |
CodeModel::Tiny) { | |
if (MI.getMF()->getTarget().getCodeModel() == CodeModel::Tiny) { |
Not sure if there's an easier way to get to the target from MI off the top of my head, but you can get the MachineFunction w/o going through getParent
a127c7e
to
c2ffa88
Compare
Sorry, I've accidentally pushed a wrong merge commit which cluttered the PR and triggered a lot of reviewers. Please ignore this PR, it'll be re-opened. |
Support the following relocations and assembly operators:
R_AARCH64_AUTH_GOT_ADR_PREL_LO21
(:got_auth:
foradr
)R_AARCH64_AUTH_GOT_LD_PREL19
(:got_auth:
forldr
)LOADgotAUTH
pseudo-instruction is expanded to actual instructionsequence like the following.
If FPAC bit is not set, a check+trap sequence similar to one used for
AUT
pseudo is emitted to ensure auth success.
Both SelectionDAG and GlobalISel are suppported. For FastISel, we fall
back to SelectionDAG.
Tests starting with 'ptrauth-' have corresponding variants w/o this prefix.