[llvm] bd3fa31 - [AArch64] Generate SEH info for PAC instructions
Martin Storsjö via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 12 12:22:12 PDT 2022
Author: Martin Storsjö
Date: 2022-10-12T22:21:03+03:00
New Revision: bd3fa318878a5f709d4324fbf74e10314012368f
URL: https://github.com/llvm/llvm-project/commit/bd3fa318878a5f709d4324fbf74e10314012368f
DIFF: https://github.com/llvm/llvm-project/commit/bd3fa318878a5f709d4324fbf74e10314012368f.diff
LOG: [AArch64] Generate SEH info for PAC instructions
Without this, unwinding through functions that does use PAC
would fail, if PAC actually was active.
Differential Revision: https://reviews.llvm.org/D135103
Added:
llvm/test/CodeGen/AArch64/wineh-pac.ll
Modified:
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 6a065871107e..3c50020dd1da 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -1661,6 +1661,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
case AArch64::SEH_EpilogEnd:
TS->emitARM64WinCFIEpilogEnd();
return;
+
+ case AArch64::SEH_PACSignLR:
+ TS->emitARM64WinCFIPACSignLR();
+ return;
}
// Finally, do the automated lowerings for everything else.
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index e89ddf3d0b4a..9247056ea7e1 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -1409,6 +1409,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
if (MFnI.shouldSignWithBKey()) {
BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITBKEY))
.setMIFlag(MachineInstr::FrameSetup);
+ // No SEH opcode for this one; it doesn't materialize into an
+ // instruction on Windows.
PACI = Subtarget.hasPAuth() ? AArch64::PACIB : AArch64::PACIBSP;
} else {
PACI = Subtarget.hasPAuth() ? AArch64::PACIA : AArch64::PACIASP;
@@ -1426,6 +1428,10 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameSetup);
+ } else if (NeedsWinCFI) {
+ HasWinCFI = true;
+ BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PACSignLR))
+ .setMIFlag(MachineInstr::FrameSetup);
}
}
if (EmitCFI && MFnI.isMTETagged()) {
@@ -1853,8 +1859,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
}
}
-static void InsertReturnAddressAuth(MachineFunction &MF,
- MachineBasicBlock &MBB) {
+static void InsertReturnAddressAuth(MachineFunction &MF, MachineBasicBlock &MBB,
+ bool NeedsWinCFI, bool *HasWinCFI) {
const auto &MFI = *MF.getInfo<AArch64FunctionInfo>();
if (!MFI.shouldSignReturnAddress())
return;
@@ -1873,7 +1879,8 @@ static void InsertReturnAddressAuth(MachineFunction &MF,
// DW_CFA_AARCH64_negate_ra_state can't be emitted.
if (Subtarget.hasPAuth() &&
!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack) &&
- MBBI != MBB.end() && MBBI->getOpcode() == AArch64::RET_ReallyLR) {
+ MBBI != MBB.end() && MBBI->getOpcode() == AArch64::RET_ReallyLR &&
+ !NeedsWinCFI) {
BuildMI(MBB, MBBI, DL,
TII->get(MFI.shouldSignWithBKey() ? AArch64::RETAB : AArch64::RETAA))
.copyImplicitOps(*MBBI);
@@ -1889,6 +1896,11 @@ static void InsertReturnAddressAuth(MachineFunction &MF,
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameDestroy);
+ if (NeedsWinCFI) {
+ *HasWinCFI = true;
+ BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PACSignLR))
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
}
}
@@ -1921,11 +1933,15 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
}
auto FinishingTouches = make_scope_exit([&]() {
- InsertReturnAddressAuth(MF, MBB);
+ InsertReturnAddressAuth(MF, MBB, NeedsWinCFI, &HasWinCFI);
if (needsShadowCallStackPrologueEpilogue(MF))
emitShadowCallStackEpilogue(*TII, MF, MBB, MBB.getFirstTerminator(), DL);
if (EmitCFI)
emitCalleeSavedGPRRestores(MBB, MBB.getFirstTerminator());
+ if (HasWinCFI)
+ BuildMI(MBB, MBB.getFirstTerminator(), DL,
+ TII->get(AArch64::SEH_EpilogEnd))
+ .setMIFlag(MachineInstr::FrameDestroy);
});
int64_t NumBytes = IsFunclet ? getWinEHFuncletFrameSize(MF)
@@ -2073,10 +2089,6 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
StackOffset::getFixed(NumBytes + (int64_t)AfterCSRPopSize),
TII, MachineInstr::FrameDestroy, false, NeedsWinCFI,
&HasWinCFI, EmitCFI, StackOffset::getFixed(NumBytes));
- if (HasWinCFI)
- BuildMI(MBB, MBB.getFirstTerminator(), DL,
- TII->get(AArch64::SEH_EpilogEnd))
- .setMIFlag(MachineInstr::FrameDestroy);
return;
}
@@ -2169,11 +2181,6 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
// If we were able to combine the local stack pop with the argument pop,
// then we're done.
if (NoCalleeSaveRestore || AfterCSRPopSize == 0) {
- if (HasWinCFI) {
- BuildMI(MBB, MBB.getFirstTerminator(), DL,
- TII->get(AArch64::SEH_EpilogEnd))
- .setMIFlag(MachineInstr::FrameDestroy);
- }
return;
}
@@ -2218,9 +2225,6 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
false, NeedsWinCFI, &HasWinCFI, EmitCFI,
StackOffset::getFixed(CombineAfterCSRBump ? PrologueSaveSize : 0));
}
- if (HasWinCFI)
- BuildMI(MBB, MBB.getFirstTerminator(), DL, TII->get(AArch64::SEH_EpilogEnd))
- .setMIFlag(MachineInstr::FrameDestroy);
}
/// getFrameIndexReference - Provide a base+offset reference to an FI slot for
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 171182050d2a..b224d063bd0e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -1016,6 +1016,7 @@ bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
case AArch64::SEH_PrologEnd:
case AArch64::SEH_EpilogStart:
case AArch64::SEH_EpilogEnd:
+ case AArch64::SEH_PACSignLR:
return true;
}
}
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index affa34d593de..e7da8238db05 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -4255,6 +4255,7 @@ let isPseudo = 1 in {
def SEH_PrologEnd : Pseudo<(outs), (ins), []>, Sched<[]>;
def SEH_EpilogStart : Pseudo<(outs), (ins), []>, Sched<[]>;
def SEH_EpilogEnd : Pseudo<(outs), (ins), []>, Sched<[]>;
+ def SEH_PACSignLR : Pseudo<(outs), (ins), []>, Sched<[]>;
}
// Pseudo instructions for Windows EH
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
index a2ab2b855d80..469e1448602c 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
@@ -66,11 +66,13 @@ static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
return {true, false};
}
-static bool ShouldSignWithBKey(const Function &F) {
+static bool ShouldSignWithBKey(const Function &F, const MachineFunction &MF) {
if (!F.hasFnAttribute("sign-return-address-key")) {
if (const auto *BKey = mdconst::extract_or_null<ConstantInt>(
F.getParent()->getModuleFlag("sign-return-address-with-bkey")))
return BKey->getZExtValue();
+ if (MF.getTarget().getTargetTriple().isOSWindows())
+ return true;
return false;
}
@@ -88,7 +90,7 @@ AArch64FunctionInfo::AArch64FunctionInfo(MachineFunction &MF_) : MF(&MF_) {
const Function &F = MF->getFunction();
std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
- SignWithBKey = ShouldSignWithBKey(F);
+ SignWithBKey = ShouldSignWithBKey(F, *MF);
// TODO: skip functions that have no instrumented allocas for optimization
IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag);
diff --git a/llvm/test/CodeGen/AArch64/wineh-pac.ll b/llvm/test/CodeGen/AArch64/wineh-pac.ll
new file mode 100644
index 000000000000..cca204a12902
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/wineh-pac.ll
@@ -0,0 +1,66 @@
+; RUN: llc < %s -mtriple=aarch64-windows | FileCheck %s
+
+define dso_local i32 @func(ptr %g, i32 %a) {
+entry:
+ tail call void %g() #2
+ ret i32 %a
+}
+
+define dso_local i32 @func2(ptr %g, i32 %a) "target-features"="+v8.3a" {
+entry:
+ tail call void %g() #2
+ ret i32 %a
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 8, !"sign-return-address", i32 1}
+
+; CHECK-LABEL: func:
+; CHECK-NEXT: .seh_proc func
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: hint #27
+; CHECK-NEXT: .seh_pac_sign_lr
+; CHECK-NEXT: str x19, [sp, #-16]!
+; CHECK-NEXT: .seh_save_reg_x x19, 16
+; CHECK-NEXT: str x30, [sp, #8]
+; CHECK-NEXT: .seh_save_reg x30, 8
+; CHECK-NEXT: .seh_endprologue
+
+; CHECK: .seh_startepilogue
+; CHECK-NEXT: ldr x30, [sp, #8]
+; CHECK-NEXT: .seh_save_reg x30, 8
+; CHECK-NEXT: ldr x19, [sp], #16
+; CHECK-NEXT: .seh_save_reg_x x19, 16
+; CHECK-NEXT: hint #31
+; CHECK-NEXT: .seh_pac_sign_lr
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: ret
+; CHECK-NEXT: .seh_endfunclet
+; CHECK-NEXT: .seh_endproc
+
+;; For func2, check that the potentially folded autibsp+ret -> retab
+;; is handled correctly - currently we inhibit producing retab here.
+
+; CHECK-LABEL: func2:
+; CHECK-NEXT: .seh_proc func2
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: pacib x30, sp
+; CHECK-NEXT: .seh_pac_sign_lr
+; CHECK-NEXT: str x19, [sp, #-16]!
+; CHECK-NEXT: .seh_save_reg_x x19, 16
+; CHECK-NEXT: str x30, [sp, #8]
+; CHECK-NEXT: .seh_save_reg x30, 8
+; CHECK-NEXT: .seh_endprologue
+
+; CHECK: .seh_startepilogue
+; CHECK-NEXT: ldr x30, [sp, #8]
+; CHECK-NEXT: .seh_save_reg x30, 8
+; CHECK-NEXT: ldr x19, [sp], #16
+; CHECK-NEXT: .seh_save_reg_x x19, 16
+; CHECK-NEXT: autibsp
+; CHECK-NEXT: .seh_pac_sign_lr
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: ret
+; CHECK-NEXT: .seh_endfunclet
+; CHECK-NEXT: .seh_endproc
More information about the llvm-commits
mailing list