diff --git a/llvm/lib/Target/AArch64/AArch64ExpandHardenedPseudos.cpp b/llvm/lib/Target/AArch64/AArch64ExpandHardenedPseudos.cpp index 394691e0a1a2..76e1417ed206 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandHardenedPseudos.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandHardenedPseudos.cpp @@ -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(); @@ -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(); @@ -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); diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 05cf6b4c2ac5..092522ef5e1b 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -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; @@ -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; diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index 9a9426e9245d..f2c0e8df2024 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -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. diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 744bdd8543c7..3d510199128d 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -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: diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err-debug.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err-debug.ll new file mode 100644 index 000000000000..e11edbb606b9 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err-debug.ll @@ -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" } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err.ll new file mode 100644 index 000000000000..ad43910c5ad5 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-lowering-err.ll @@ -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)