Skip to content
11 changes: 11 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ExpandHardenedPseudos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ bool AArch64ExpandHardenedPseudos::expandPtrAuthPseudo(MachineInstr &MI) {
if (MI.getOpcode() == AArch64::LOADauthptrgot) {
LLVM_DEBUG(dbgs() << "Expanding: " << MI << "\n");

if (!STI.hasPAuth())
report_fatal_error("pac instructions require ptrauth target feature");

const TargetMachine &TM = MF.getTarget();
MachineModuleInfo &MMI = MF.getMMI();

Expand Down Expand Up @@ -223,6 +226,9 @@ bool AArch64ExpandHardenedPseudos::expandPtrAuthPseudo(MachineInstr &MI) {

LLVM_DEBUG(dbgs() << "Expanding: " << MI << "\n");

if (!STI.hasPAuth())
report_fatal_error("pac instructions require ptrauth target feature");

const bool IsGOTLoad = MI.getOpcode() == AArch64::LOADgotPAC;
MachineOperand GAOp = MI.getOperand(0);
auto Key = (AArch64PACKey::ID)MI.getOperand(1).getImm();
Expand Down Expand Up @@ -332,6 +338,11 @@ bool AArch64ExpandHardenedPseudos::expandAuthLoad(MachineInstr &MI) {

LLVM_DEBUG(dbgs() << "Expanding: " << MI << "\n");

// LDRA and LDRApre preudos are emitted in AArch64DAGToDAGISel::tryAuthLoad
// and AArch64InstructionSelector::selectAuthLoad with prior checks against
// ptrauth subtarget feature
assert(STI.hasPAuth());

bool IsPre = MI.getOpcode() == AArch64::LDRApre;

MachineOperand DstOp = MI.getOperand(0);
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
// If we're saving LR, sign it first.
if (shouldAuthenticateLR(MF)) {
if (LLVM_UNLIKELY(!Subtarget.hasPAuth()))
report_fatal_error("arm64e LR authentication requires ptrauth");
report_fatal_error(
StringRef(Subtarget.isTargetMachO() ? "arm64e" : "aarch64") +
" LR authentication requires ptrauth");
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
if (Info.getReg() != AArch64::LR)
continue;
Expand Down Expand Up @@ -2051,7 +2053,9 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
auto InsertAuthLROnExit = make_scope_exit([&]() {
if (shouldAuthenticateLR(MF)) {
if (LLVM_UNLIKELY(!Subtarget.hasPAuth()))
report_fatal_error("arm64e LR authentication requires ptrauth");
report_fatal_error(
StringRef(Subtarget.isTargetMachO() ? "arm64e" : "aarch64") +
" LR authentication requires ptrauth");
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
if (Info.getReg() != AArch64::LR)
continue;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,9 @@ bool AArch64DAGToDAGISel::tryAuthLoad(SDNode *N) {
return false;
}

if (!Subtarget->hasPAuth())
report_fatal_error("pac instructions require ptrauth target feature");

// We have 2 main isel alternatives:
// - LDRAA/LDRAB, writeback or indexed. Zero disc, small offsets, D key.
// - LDRA/LDRApre. Pointer needs to be in X16.
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2856,6 +2856,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {

case AArch64::G_LDRA:
case AArch64::G_LDRApre:
// TODO: implement a test case for this error
if (!STI.hasPAuth())
report_fatal_error("pac instructions require ptrauth target feature");
return selectAuthLoad(I, MRI);

case TargetOpcode::G_ZEXTLOAD:
Expand Down
60 changes: 60 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err-debug.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
; REQUIRES: asserts
; RUN: split-file %s %t && cd %t

;--- MOVaddrPAC.ll

; RUN: not --crash llc -debug-only=aarch64-expand-hardened-pseudos -mtriple aarch64-elf MOVaddrPAC.ll 2>&1 | \
; RUN: FileCheck MOVaddrPAC.ll

; CHECK: Expanding: MOVaddrPAC @foo
; CHECK-NEXT: {{^$}}
; CHECK-NEXT: LLVM ERROR: pac instructions require ptrauth target feature

@foo.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @foo, i32 0, i64 0, i64 0 }, section "llvm.ptrauth", align 8

define ptr @bar() #0 {
ret ptr @foo.ptrauth
}

define private void @foo() {
ret void
}

attributes #0 = { "ptrauth-calls" "target-cpu"="generic" }

;--- LOADgotPAC.ll

; RUN: not --crash llc -debug-only=aarch64-expand-hardened-pseudos -mtriple aarch64-elf LOADgotPAC.ll 2>&1 | \
; RUN: FileCheck LOADgotPAC.ll

; CHECK: Expanding: LOADgotPAC @foo
; CHECK-NEXT: {{^$}}
; CHECK-NEXT: LLVM ERROR: pac instructions require ptrauth target feature

@foo.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @foo, i32 0, i64 0, i64 0 }, section "llvm.ptrauth", align 8

define ptr @bar() #0 {
ret ptr @foo.ptrauth
}

declare void @foo()

attributes #0 = { "ptrauth-calls" "target-cpu"="generic" }

;--- LOADauthptrgot.ll

; RUN: not --crash llc -debug-only=aarch64-expand-hardened-pseudos -mtriple aarch64-elf LOADauthptrgot.ll 2>&1 | \
; RUN: FileCheck LOADauthptrgot.ll

; CHECK: Expanding: {{.*}}LOADauthptrgot @g_weak
; CHECK-NEXT: {{^$}}
; CHECK-NEXT: LLVM ERROR: pac instructions require ptrauth target feature

define ptr @foo() #0 {
ret ptr @g_weak.ptrauth
}

@g_weak = extern_weak global i32
@g_weak.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @g_weak, i32 0, i64 0, i64 0 }, section "llvm.ptrauth"

attributes #0 = { "ptrauth-calls" "target-cpu"="generic" }
102 changes: 102 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
; RUN: split-file %s %t && cd %t

;--- MOVaddrPAC.ll

; RUN: not --crash llc -mtriple aarch64-elf MOVaddrPAC.ll 2>&1 | \
; RUN: FileCheck MOVaddrPAC.ll

; CHECK: LLVM ERROR: pac instructions require ptrauth target feature

@foo.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @foo, i32 0, i64 0, i64 0 }, section "llvm.ptrauth", align 8

define ptr @bar() #0 {
ret ptr @foo.ptrauth
}

define private void @foo() {
ret void
}

attributes #0 = { "ptrauth-calls" "target-cpu"="generic" }

;--- LOADgotPAC.ll

; RUN: not --crash llc -mtriple aarch64-elf LOADgotPAC.ll 2>&1 | \
; RUN: FileCheck LOADgotPAC.ll

; CHECK: LLVM ERROR: pac instructions require ptrauth target feature

@foo.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @foo, i32 0, i64 0, i64 0 }, section "llvm.ptrauth", align 8

define ptr @bar() #0 {
ret ptr @foo.ptrauth
}

declare void @foo()

attributes #0 = { "ptrauth-calls" "target-cpu"="generic" }

;--- LOADauthptrgot.ll

; RUN: not --crash llc -mtriple aarch64-elf LOADauthptrgot.ll 2>&1 | \
; RUN: FileCheck LOADauthptrgot.ll

; CHECK: LLVM ERROR: pac instructions require ptrauth target feature

define ptr @foo() #0 {
ret ptr @g_weak.ptrauth
}

@g_weak = extern_weak global i32
@g_weak.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @g_weak, i32 0, i64 0, i64 0 }, section "llvm.ptrauth"

attributes #0 = { "ptrauth-calls" "target-cpu"="generic" }

;--- ptrauth-returns.ll

; RUN: not --crash llc -mtriple aarch64-elf ptrauth-returns.ll 2>&1 | \
; RUN: FileCheck ptrauth-returns.ll

; CHECK: LLVM ERROR: aarch64 LR authentication requires ptrauth

define i32 @bar() #0 {
ret i32 42
}

define i32 @foo() {
%tmp = call i32 @bar()
ret i32 %tmp
}

attributes #0 = { "ptrauth-returns" "target-cpu"="generic" }

;--- auth-call.ll

; RUN: not --crash llc -mtriple aarch64-elf auth-call.ll 2>&1 | \
; RUN: FileCheck auth-call.ll

; CHECK: LLVM ERROR: Cannot select:{{.*}}AArch64ISD::AUTH_CALL

define void @bar(ptr %foo) #0 {
call void %foo() [ "ptrauth"(i32 0, i64 0) ]
ret void
}

attributes #0 = { "ptrauth-calls" "target-cpu"="generic" }

;--- tryAuthLoad.ll

; RUN: not --crash llc -mtriple aarch64-elf tryAuthLoad.ll 2>&1 | \
; RUN: FileCheck tryAuthLoad.ll

; CHECK: LLVM ERROR: pac instructions require ptrauth target feature

define i64 @test(ptr %ptr) {
%tmp0 = ptrtoint ptr %ptr to i64
%tmp1 = call i64 @llvm.ptrauth.auth(i64 %tmp0, i32 2, i64 0)
%tmp2 = inttoptr i64 %tmp1 to ptr
%tmp3 = load i64, ptr %tmp2
ret i64 %tmp3
}

declare i64 @llvm.ptrauth.auth(i64, i32, i64)