Skip to content

Commit da878f7

Browse files
committed
StackProtector: ensure protection does not interfere with tail call frame.
We didn't recognize that ADJCALLFRAME instructions could be part of the terminal sequence of a tail call. In this case because such call frames cannot be nested in LLVM the stack protection code must skip over the whole sequence (or risk clobbering argument registers). On the other hand, the ADJCALLFRAME could be part of a different call, in which case the correct split point is right after it.
1 parent 23eeb5a commit da878f7

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,16 +1691,35 @@ static bool MIIsInTerminatorSequence(const MachineInstr &MI) {
16911691
/// terminator, but additionally the copies that move the vregs into the
16921692
/// physical registers.
16931693
static MachineBasicBlock::iterator
1694-
FindSplitPointForStackProtector(MachineBasicBlock *BB) {
1694+
FindSplitPointForStackProtector(MachineBasicBlock *BB,
1695+
const TargetInstrInfo &TII) {
16951696
MachineBasicBlock::iterator SplitPoint = BB->getFirstTerminator();
1696-
//
16971697
if (SplitPoint == BB->begin())
16981698
return SplitPoint;
16991699

17001700
MachineBasicBlock::iterator Start = BB->begin();
17011701
MachineBasicBlock::iterator Previous = SplitPoint;
17021702
--Previous;
17031703

1704+
if (TII.isTailCall(*SplitPoint) &&
1705+
Previous->getOpcode() == TII.getCallFrameDestroyOpcode()) {
1706+
// Call frames cannot be nested, so if this frame is describing the tail
1707+
// call itself then we must insert before the sequence even starts. On the
1708+
// other hand, it could be an unrelated call in which case this tail call
1709+
// has to register moves of its own and should be the split point.
1710+
bool DifferentCall = false;
1711+
MachineBasicBlock::iterator I = Previous;
1712+
do {
1713+
--I;
1714+
if (I->isCall()) {
1715+
DifferentCall = true;
1716+
break;
1717+
}
1718+
} while(I->getOpcode() != TII.getCallFrameSetupOpcode());
1719+
1720+
return DifferentCall ? SplitPoint : I;
1721+
}
1722+
17041723
while (MIIsInTerminatorSequence(*Previous)) {
17051724
SplitPoint = Previous;
17061725
if (Previous == Start)
@@ -1740,7 +1759,7 @@ SelectionDAGISel::FinishBasicBlock() {
17401759
// Add load and check to the basicblock.
17411760
FuncInfo->MBB = ParentMBB;
17421761
FuncInfo->InsertPt =
1743-
FindSplitPointForStackProtector(ParentMBB);
1762+
FindSplitPointForStackProtector(ParentMBB, *TII);
17441763
SDB->visitSPDescriptorParent(SDB->SPDescriptor, ParentMBB);
17451764
CurDAG->setRoot(SDB->getRoot());
17461765
SDB->clear();
@@ -1759,7 +1778,7 @@ SelectionDAGISel::FinishBasicBlock() {
17591778
// register allocation issues caused by us splitting the parent mbb. The
17601779
// register allocator will clean up said virtual copies later on.
17611780
MachineBasicBlock::iterator SplitPoint =
1762-
FindSplitPointForStackProtector(ParentMBB);
1781+
FindSplitPointForStackProtector(ParentMBB, *TII);
17631782

17641783
// Splice the terminator of ParentMBB into SuccessMBB.
17651784
SuccessMBB->splice(SuccessMBB->end(), ParentMBB,

llvm/test/CodeGen/X86/tailcc-ssp.ll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: llc -mtriple=x86_64-windows-msvc %s -o - -verify-machineinstrs | FileCheck %s
2+
3+
declare void @h(i8*, i64, i8*)
4+
5+
define tailcc void @tailcall_frame(i8* %0, i64 %1) sspreq {
6+
; CHECK-LABEL: tailcall_frame:
7+
; CHECK: callq __security_check_cookie
8+
; CHECK: xorl %ecx, %ecx
9+
; CHECK: jmp h
10+
11+
tail call tailcc void @h(i8* null, i64 0, i8* null)
12+
ret void
13+
}
14+
15+
declare void @bar()
16+
define void @tailcall_unrelated_frame() sspreq {
17+
; CHECK-LABEL: tailcall_unrelated_frame:
18+
; CHECK: subq [[STACK:\$.*]], %rsp
19+
; CHECK: callq bar
20+
; CHECK: callq __security_check_cookie
21+
; CHECK: addq [[STACK]], %rsp
22+
; CHECK: jmp bar
23+
call void @bar()
24+
tail call void @bar()
25+
ret void
26+
}

0 commit comments

Comments
 (0)