diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2578,6 +2578,9 @@ def : Pat<(AArch64call_bti GPR64:$Rn), (BLR_BTI GPR64:$Rn)>, Requires<[NoSLSBLRMitigation]>; +def : Pat<(AArch64call_bti GPR64noip:$Rn), + (BLR_BTI GPR64noip:$Rn)>, + Requires<[SLSBLRMitigation]>; let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { def BR : BranchReg<0b0000, "br", [(brind GPR64:$Rn)]>; diff --git a/llvm/lib/Target/AArch64/AArch64SLSHardening.cpp b/llvm/lib/Target/AArch64/AArch64SLSHardening.cpp --- a/llvm/lib/Target/AArch64/AArch64SLSHardening.cpp +++ b/llvm/lib/Target/AArch64/AArch64SLSHardening.cpp @@ -60,7 +60,7 @@ bool hardenReturnsAndBRs(MachineBasicBlock &MBB) const; bool hardenBLRs(MachineBasicBlock &MBB) const; MachineBasicBlock &ConvertBLRToBL(MachineBasicBlock &MBB, - MachineBasicBlock::iterator) const; + MachineBasicBlock::instr_iterator) const; }; } // end anonymous namespace @@ -245,9 +245,8 @@ Entry->end(), DebugLoc(), true /*AlwaysUseISBDSB*/); } -MachineBasicBlock & -AArch64SLSHardening::ConvertBLRToBL(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI) const { +MachineBasicBlock &AArch64SLSHardening::ConvertBLRToBL( + MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator MBBI) const { // Transform a BLR to a BL as follows: // Before: // |-----------------------------| @@ -382,8 +381,9 @@ if (!ST->hardenSlsBlr()) return false; bool Modified = false; - MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); - MachineBasicBlock::iterator NextMBBI; + MachineBasicBlock::instr_iterator MBBI = MBB.instr_begin(), + E = MBB.instr_end(); + MachineBasicBlock::instr_iterator NextMBBI; for (; MBBI != E; MBBI = NextMBBI) { MachineInstr &MI = *MBBI; NextMBBI = std::next(MBBI); diff --git a/llvm/test/CodeGen/AArch64/setjmp-bti.ll b/llvm/test/CodeGen/AArch64/setjmp-bti.ll --- a/llvm/test/CodeGen/AArch64/setjmp-bti.ll +++ b/llvm/test/CodeGen/AArch64/setjmp-bti.ll @@ -1,6 +1,9 @@ ; RUN: llc -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefix=BTI ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel < %s | FileCheck %s --check-prefix=BTI ; RUN: llc -mtriple=aarch64-none-linux-gnu -fast-isel < %s | FileCheck %s --check-prefix=BTI +; RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+harden-sls-blr< %s | FileCheck %s --check-prefix=BTISLS +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -mattr=+harden-sls-blr< %s | FileCheck %s --check-prefix=BTISLS +; RUN: llc -mtriple=aarch64-none-linux-gnu -fast-isel -mattr=+harden-sls-blr< %s | FileCheck %s --check-prefix=BTISLS ; RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+no-bti-at-return-twice < %s | \ ; RUN: FileCheck %s --check-prefix=NOBTI ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -mattr=+no-bti-at-return-twice < %s | \ @@ -29,6 +32,14 @@ ; BTI: bl notsetjmp ; BTI-NOT: hint #36 +; BTISLS-LABEL: bbb: +; BTISLS: bl setjmp +; BTISLS-NEXT: hint #36 +; BTISLS: bl __llvm_slsblr_thunk_x{{[0-9]+}} +; BTISLS-NEXT: hint #36 +; BTISLS: bl notsetjmp +; BTISLS-NOT: hint #36 + ; NOBTI-LABEL: bbb: ; NOBTI: bl setjmp ; NOBTI-NOT: hint #36 diff --git a/llvm/test/CodeGen/AArch64/speculation-hardening-sls-blr-bti.mir b/llvm/test/CodeGen/AArch64/speculation-hardening-sls-blr-bti.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/speculation-hardening-sls-blr-bti.mir @@ -0,0 +1,88 @@ +# RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu \ +# RUN: -start-before aarch64-sls-hardening \ +# RUN: -stop-after aarch64-sls-hardening -o - %s \ +# RUN: | FileCheck %s --check-prefixes=CHECK + +# Check when the BLR SLS hardening encounters a BLR/BTI bundle, the BTI +# instruction remains after the BLR is replaced with a BL. +# These BLR/BTI bundles are produced when calling a returns_twice function +# (like setjmp) indirectly. +--- | + $__llvm_slsblr_thunk_x8 = comdat any + + define dso_local void @fn() #0 { + entry: + %fnptr = alloca ptr, align 8 + store ptr @setjmp, ptr %fnptr, align 8 + %0 = load ptr, ptr %fnptr, align 8 + %call1 = call i32 %0(ptr noundef null) #1 + ret void + } + + ; Function Attrs: returns_twice + declare i32 @setjmp(ptr noundef) #1 + + ; Function Attrs: naked nounwind + define linkonce_odr hidden void @__llvm_slsblr_thunk_x8() #2 comdat { + entry: + ret void + } + + attributes #0 = { "target-features"="+harden-sls-blr" } + attributes #1 = { returns_twice } + attributes #2 = { naked nounwind } + + !llvm.module.flags = !{!0} + !0 = !{i32 8, !"branch-target-enforcement", i32 1} +... +--- +name: fn +exposesReturnsTwice: true +tracksRegLiveness: true +fixedStack: [] +stack: + - { id: 0, name: fnptr, type: default, offset: -8, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -8, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, + stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + hasRedZone: false +body: | + bb.0.entry: + liveins: $lr + + early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.1) + frame-setup CFI_INSTRUCTION def_cfa_offset 16 + frame-setup CFI_INSTRUCTION offset $w30, -16 + $x8 = ADRP target-flags(aarch64-page, aarch64-got) @setjmp + renamable $x8 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @setjmp + STRXui renamable $x8, $sp, 1 :: (store (s64) into %ir.fnptr) + $x0 = ORRXrs $xzr, $xzr, 0 + BUNDLE implicit-def $lr, implicit-def $w30, implicit killed $x8, implicit $sp { + BLR killed renamable $x8, implicit-def $lr, implicit $sp + HINT 36 + } + ; CHECK: BUNDLE implicit-def $lr, implicit-def $w30, implicit killed $x8, implicit $sp { + ; CHECK-NEXT: BL , implicit-def $lr, implicit $sp, implicit killed $x8 + ; CHECK-NEXT: HINT 36 + ; CHECK-NEXT: } + early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.1) + RET undef $lr +... +--- +name: __llvm_slsblr_thunk_x8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x8 + + $x16 = ORRXrs $xzr, $x8, 0 + BR $x16 + SpeculationBarrierISBDSBEndBB +...