Skip to content

Commit 4ab0d7c

Browse files
committed
Inline stack guard check on Windows
1 parent 76b6a78 commit 4ab0d7c

File tree

6 files changed

+228
-95
lines changed

6 files changed

+228
-95
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,33 +3059,6 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
30593059
if (TLI.useStackGuardXorFP())
30603060
GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl);
30613061

3062-
// Retrieve guard check function, nullptr if instrumentation is inlined.
3063-
if (const Function *GuardCheckFn = TLI.getSSPStackGuardCheck(M)) {
3064-
// The target provides a guard check function to validate the guard value.
3065-
// Generate a call to that function with the content of the guard slot as
3066-
// argument.
3067-
FunctionType *FnTy = GuardCheckFn->getFunctionType();
3068-
assert(FnTy->getNumParams() == 1 && "Invalid function signature");
3069-
3070-
TargetLowering::ArgListTy Args;
3071-
TargetLowering::ArgListEntry Entry;
3072-
Entry.Node = GuardVal;
3073-
Entry.Ty = FnTy->getParamType(0);
3074-
if (GuardCheckFn->hasParamAttribute(0, Attribute::AttrKind::InReg))
3075-
Entry.IsInReg = true;
3076-
Args.push_back(Entry);
3077-
3078-
TargetLowering::CallLoweringInfo CLI(DAG);
3079-
CLI.setDebugLoc(getCurSDLoc())
3080-
.setChain(DAG.getEntryNode())
3081-
.setCallee(GuardCheckFn->getCallingConv(), FnTy->getReturnType(),
3082-
getValue(GuardCheckFn), std::move(Args));
3083-
3084-
std::pair<SDValue, SDValue> Result = TLI.LowerCallTo(CLI);
3085-
DAG.setRoot(Result.second);
3086-
return;
3087-
}
3088-
30893062
// If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD.
30903063
// Otherwise, emit a volatile load to retrieve the stack guard value.
30913064
SDValue Chain = DAG.getEntryNode();
@@ -3126,14 +3099,66 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
31263099
/// For a high level explanation of how this fits into the stack protector
31273100
/// generation see the comment on the declaration of class
31283101
/// StackProtectorDescriptor.
3129-
void
3130-
SelectionDAGBuilder::visitSPDescriptorFailure(StackProtectorDescriptor &SPD) {
3102+
void SelectionDAGBuilder::visitSPDescriptorFailure(
3103+
StackProtectorDescriptor &SPD) {
3104+
31313105
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
3132-
TargetLowering::MakeLibCallOptions CallOptions;
3133-
CallOptions.setDiscardResult(true);
3134-
SDValue Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL,
3135-
MVT::isVoid, {}, CallOptions, getCurSDLoc())
3136-
.second;
3106+
MachineBasicBlock *ParentBB = SPD.getParentMBB();
3107+
const Module &M = *ParentBB->getParent()->getFunction().getParent();
3108+
SDValue Chain;
3109+
3110+
// Retrieve guard check function, nullptr if instrumentation is inlined.
3111+
if (const Function *GuardCheckFn = TLI.getSSPStackGuardCheck(M)) {
3112+
3113+
// First create the loads to the guard/stack slot for the comparison.
3114+
EVT PtrTy = TLI.getPointerTy(DAG.getDataLayout());
3115+
EVT PtrMemTy = TLI.getPointerMemTy(DAG.getDataLayout());
3116+
3117+
MachineFrameInfo &MFI = ParentBB->getParent()->getFrameInfo();
3118+
int FI = MFI.getStackProtectorIndex();
3119+
3120+
SDLoc dl = getCurSDLoc();
3121+
SDValue StackSlotPtr = DAG.getFrameIndex(FI, PtrTy);
3122+
Align Align = DAG.getDataLayout().getPrefTypeAlign(
3123+
PointerType::get(M.getContext(), 0));
3124+
3125+
// Generate code to load the content of the guard slot.
3126+
SDValue GuardVal = DAG.getLoad(
3127+
PtrMemTy, dl, DAG.getEntryNode(), StackSlotPtr,
3128+
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align,
3129+
MachineMemOperand::MOVolatile);
3130+
3131+
if (TLI.useStackGuardXorFP())
3132+
GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl);
3133+
3134+
// The target provides a guard check function to validate the guard value.
3135+
// Generate a call to that function with the content of the guard slot as
3136+
// argument.
3137+
FunctionType *FnTy = GuardCheckFn->getFunctionType();
3138+
assert(FnTy->getNumParams() == 1 && "Invalid function signature");
3139+
3140+
TargetLowering::ArgListTy Args;
3141+
TargetLowering::ArgListEntry Entry;
3142+
Entry.Node = GuardVal;
3143+
Entry.Ty = FnTy->getParamType(0);
3144+
if (GuardCheckFn->hasParamAttribute(0, Attribute::AttrKind::InReg))
3145+
Entry.IsInReg = true;
3146+
Args.push_back(Entry);
3147+
3148+
TargetLowering::CallLoweringInfo CLI(DAG);
3149+
CLI.setDebugLoc(getCurSDLoc())
3150+
.setChain(DAG.getEntryNode())
3151+
.setCallee(GuardCheckFn->getCallingConv(), FnTy->getReturnType(),
3152+
getValue(GuardCheckFn), std::move(Args));
3153+
3154+
Chain = TLI.LowerCallTo(CLI).second;
3155+
} else {
3156+
TargetLowering::MakeLibCallOptions CallOptions;
3157+
CallOptions.setDiscardResult(true);
3158+
Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL, MVT::isVoid,
3159+
{}, CallOptions, getCurSDLoc())
3160+
.second;
3161+
}
31373162

31383163
// Emit a trap instruction if we are required to do so.
31393164
const TargetOptions &TargetOpts = DAG.getTarget().Options;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,12 +1875,9 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
18751875
FastIS->recomputeInsertPt();
18761876
}
18771877

1878-
if (SP->shouldEmitSDCheck(*LLVMBB)) {
1879-
bool FunctionBasedInstrumentation =
1880-
TLI->getSSPStackGuardCheck(*Fn.getParent());
1878+
if (SP->shouldEmitSDCheck(*LLVMBB))
18811879
SDB->SPDescriptor.initialize(LLVMBB, FuncInfo->getMBB(LLVMBB),
1882-
FunctionBasedInstrumentation);
1883-
}
1880+
false);
18841881

18851882
if (Begin != BI)
18861883
++NumDAGBlocks;
@@ -1942,24 +1939,7 @@ SelectionDAGISel::FinishBasicBlock() {
19421939
PHI.addReg(FuncInfo->PHINodesToUpdate[i].second).addMBB(FuncInfo->MBB);
19431940
}
19441941

1945-
// Handle stack protector.
1946-
if (SDB->SPDescriptor.shouldEmitFunctionBasedCheckStackProtector()) {
1947-
// The target provides a guard check function. There is no need to
1948-
// generate error handling code or to split current basic block.
1949-
MachineBasicBlock *ParentMBB = SDB->SPDescriptor.getParentMBB();
1950-
1951-
// Add load and check to the basicblock.
1952-
FuncInfo->MBB = ParentMBB;
1953-
FuncInfo->InsertPt =
1954-
findSplitPointForStackProtector(ParentMBB, *TII);
1955-
SDB->visitSPDescriptorParent(SDB->SPDescriptor, ParentMBB);
1956-
CurDAG->setRoot(SDB->getRoot());
1957-
SDB->clear();
1958-
CodeGenAndEmitDAG();
1959-
1960-
// Clear the Per-BB State.
1961-
SDB->SPDescriptor.resetPerBBState();
1962-
} else if (SDB->SPDescriptor.shouldEmitStackProtector()) {
1942+
if (SDB->SPDescriptor.shouldEmitStackProtector()) {
19631943
MachineBasicBlock *ParentMBB = SDB->SPDescriptor.getParentMBB();
19641944
MachineBasicBlock *SuccessMBB = SDB->SPDescriptor.getSuccessMBB();
19651945

@@ -1973,8 +1953,7 @@ SelectionDAGISel::FinishBasicBlock() {
19731953
findSplitPointForStackProtector(ParentMBB, *TII);
19741954

19751955
// Splice the terminator of ParentMBB into SuccessMBB.
1976-
SuccessMBB->splice(SuccessMBB->end(), ParentMBB,
1977-
SplitPoint,
1956+
SuccessMBB->splice(SuccessMBB->end(), ParentMBB, SplitPoint,
19781957
ParentMBB->end());
19791958

19801959
// Add compare/jump on neq/jump to the parent BB.

llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,23 @@ define void @caller() sspreq {
1717
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
1818
; CHECK-NEXT: str x8, [sp, #8]
1919
; CHECK-NEXT: bl callee
20-
; CHECK-NEXT: ldr x0, [sp, #8]
21-
; CHECK-NEXT: bl __security_check_cookie
20+
; CHECK-NEXT: adrp x8, __security_cookie
21+
; CHECK-NEXT: ldr x9, [sp, #8]
22+
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
23+
; CHECK-NEXT: cmp x8, x9
24+
; CHECK-NEXT: b.ne .LBB0_2
25+
; CHECK-NEXT: // %bb.1: // %entry
2226
; CHECK-NEXT: .seh_startepilogue
2327
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
2428
; CHECK-NEXT: .seh_save_reg x30, 16
2529
; CHECK-NEXT: add sp, sp, #32
2630
; CHECK-NEXT: .seh_stackalloc 32
2731
; CHECK-NEXT: .seh_endepilogue
2832
; CHECK-NEXT: ret
33+
; CHECK-NEXT: .LBB0_2: // %entry
34+
; CHECK-NEXT: ldr x0, [sp, #8]
35+
; CHECK-NEXT: bl __security_check_cookie
36+
; CHECK-NEXT: brk #0x1
2937
; CHECK-NEXT: .seh_endfunclet
3038
; CHECK-NEXT: .seh_endproc
3139
entry:

0 commit comments

Comments
 (0)