Skip to content

Commit 18960a9

Browse files
[AArch64] Stack probing for dynamic allocas in GlobalISel
This adds a stack probing instruction sequence for dynamic stack allocations, to protect against stack clash attacks. The instruction sequence used is the same one used for unknown-size allocations in function prologues. Change-Id: Iba5f94462d18bcf62d09bb9b4f0d7563f680c19c Co-authored-by: Oliver Stannard <oliver.stannard@linaro.org>
1 parent e9c6f3f commit 18960a9

File tree

7 files changed

+286
-72
lines changed

7 files changed

+286
-72
lines changed

Diff for: llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

+2
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ class LegalizerHelper {
410410
LegalizeResult lowerUnmergeValues(MachineInstr &MI);
411411
LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI);
412412
LegalizeResult lowerShuffleVector(MachineInstr &MI);
413+
Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize,
414+
Align Alignment, LLT PtrTy);
413415
LegalizeResult lowerDynStackAlloc(MachineInstr &MI);
414416
LegalizeResult lowerStackSave(MachineInstr &MI);
415417
LegalizeResult lowerStackRestore(MachineInstr &MI);

Diff for: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

+23-14
Original file line numberDiff line numberDiff line change
@@ -7042,21 +7042,12 @@ LegalizerHelper::lowerShuffleVector(MachineInstr &MI) {
70427042
return Legalized;
70437043
}
70447044

7045-
LegalizerHelper::LegalizeResult
7046-
LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) {
7047-
const auto &MF = *MI.getMF();
7048-
const auto &TFI = *MF.getSubtarget().getFrameLowering();
7049-
if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp)
7050-
return UnableToLegalize;
7051-
7052-
Register Dst = MI.getOperand(0).getReg();
7053-
Register AllocSize = MI.getOperand(1).getReg();
7054-
Align Alignment = assumeAligned(MI.getOperand(2).getImm());
7055-
7056-
LLT PtrTy = MRI.getType(Dst);
7045+
Register LegalizerHelper::getDynStackAllocTargetPtr(Register SPReg,
7046+
Register AllocSize,
7047+
Align Alignment,
7048+
LLT PtrTy) {
70577049
LLT IntPtrTy = LLT::scalar(PtrTy.getSizeInBits());
70587050

7059-
Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
70607051
auto SPTmp = MIRBuilder.buildCopy(PtrTy, SPReg);
70617052
SPTmp = MIRBuilder.buildCast(IntPtrTy, SPTmp);
70627053

@@ -7071,7 +7062,25 @@ LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) {
70717062
Alloc = MIRBuilder.buildAnd(IntPtrTy, Alloc, AlignCst);
70727063
}
70737064

7074-
SPTmp = MIRBuilder.buildCast(PtrTy, Alloc);
7065+
return MIRBuilder.buildCast(PtrTy, Alloc).getReg(0);
7066+
}
7067+
7068+
LegalizerHelper::LegalizeResult
7069+
LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) {
7070+
const auto &MF = *MI.getMF();
7071+
const auto &TFI = *MF.getSubtarget().getFrameLowering();
7072+
if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp)
7073+
return UnableToLegalize;
7074+
7075+
Register Dst = MI.getOperand(0).getReg();
7076+
Register AllocSize = MI.getOperand(1).getReg();
7077+
Align Alignment = assumeAligned(MI.getOperand(2).getImm());
7078+
7079+
LLT PtrTy = MRI.getType(Dst);
7080+
Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
7081+
Register SPTmp =
7082+
getDynStackAllocTargetPtr(SPReg, AllocSize, Alignment, PtrTy);
7083+
70757084
MIRBuilder.buildCopy(SPReg, SPTmp);
70767085
MIRBuilder.buildCopy(Dst, SPTmp);
70777086

Diff for: llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

+44-3
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
934934

935935
getActionDefinitionsBuilder(G_BRJT).legalFor({{p0, s64}});
936936

937-
getActionDefinitionsBuilder({G_DYN_STACKALLOC,
938-
G_STACKSAVE,
939-
G_STACKRESTORE}).lower();
937+
getActionDefinitionsBuilder(G_DYN_STACKALLOC).custom();
938+
939+
getActionDefinitionsBuilder({G_STACKSAVE, G_STACKRESTORE}).lower();
940940

941941
if (ST.hasMOPS()) {
942942
// G_BZERO is not supported. Currently it is only emitted by
@@ -1174,6 +1174,8 @@ bool AArch64LegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
11741174
return legalizeFCopySign(MI, Helper);
11751175
case TargetOpcode::G_EXTRACT_VECTOR_ELT:
11761176
return legalizeExtractVectorElt(MI, MRI, Helper);
1177+
case TargetOpcode::G_DYN_STACKALLOC:
1178+
return legalizeDynStackAlloc(MI, Helper);
11771179
}
11781180

11791181
llvm_unreachable("expected switch to return");
@@ -1945,3 +1947,42 @@ bool AArch64LegalizerInfo::legalizeExtractVectorElt(
19451947
return Helper.lowerExtractInsertVectorElt(MI) !=
19461948
LegalizerHelper::LegalizeResult::UnableToLegalize;
19471949
}
1950+
1951+
bool AArch64LegalizerInfo::legalizeDynStackAlloc(
1952+
MachineInstr &MI, LegalizerHelper &Helper) const {
1953+
MachineFunction &MF = *MI.getParent()->getParent();
1954+
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
1955+
MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
1956+
1957+
// If stack probing is not enabled for this function, use the default
1958+
// lowering.
1959+
if (!MF.getFunction().hasFnAttribute("probe-stack") ||
1960+
MF.getFunction().getFnAttribute("probe-stack").getValueAsString() !=
1961+
"inline-asm") {
1962+
Helper.lowerDynStackAlloc(MI);
1963+
return true;
1964+
}
1965+
1966+
Register Dst = MI.getOperand(0).getReg();
1967+
Register AllocSize = MI.getOperand(1).getReg();
1968+
Align Alignment = assumeAligned(MI.getOperand(2).getImm());
1969+
1970+
assert(MRI.getType(Dst) == LLT::pointer(0, 64) &&
1971+
"Unexpected type for dynamic alloca");
1972+
assert(MRI.getType(AllocSize) == LLT::scalar(64) &&
1973+
"Unexpected type for dynamic alloca");
1974+
1975+
LLT PtrTy = MRI.getType(Dst);
1976+
Register SPReg =
1977+
Helper.getTargetLowering().getStackPointerRegisterToSaveRestore();
1978+
Register SPTmp =
1979+
Helper.getDynStackAllocTargetPtr(SPReg, AllocSize, Alignment, PtrTy);
1980+
auto NewMI =
1981+
MIRBuilder.buildInstr(AArch64::PROBED_STACKALLOC_DYN, {}, {SPTmp});
1982+
MRI.setRegClass(NewMI.getReg(0), &AArch64::GPR64commonRegClass);
1983+
MIRBuilder.setInsertPt(*NewMI->getParent(), NewMI);
1984+
MIRBuilder.buildCopy(Dst, SPTmp);
1985+
1986+
MI.eraseFromParent();
1987+
return true;
1988+
}

Diff for: llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class AArch64LegalizerInfo : public LegalizerInfo {
6363
bool legalizeFCopySign(MachineInstr &MI, LegalizerHelper &Helper) const;
6464
bool legalizeExtractVectorElt(MachineInstr &MI, MachineRegisterInfo &MRI,
6565
LegalizerHelper &Helper) const;
66+
bool legalizeDynStackAlloc(MachineInstr &MI, LegalizerHelper &Helper) const;
6667
const AArch64Subtarget *ST;
6768
};
6869
} // End llvm namespace.

0 commit comments

Comments
 (0)