forked from OSchip/llvm-project
[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
This commit is contained in:
parent
918f6f581d
commit
bd3fa31887
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue