[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