MachineVerifier: Check stack protector is top-most in frame (#121481)
Somewhat paranoid, but mitigates potential bugs in the future that might place it elsewhere and render the mechanism useless.
This commit is contained in:
parent
6504546abc
commit
86b1b0671c
@ -353,6 +353,8 @@ struct MachineVerifier {
|
||||
LaneBitmask LaneMask = LaneBitmask::getNone());
|
||||
|
||||
void verifyStackFrame();
|
||||
// Check that the stack protector is the top-most object in the stack.
|
||||
void verifyStackProtector();
|
||||
|
||||
void verifySlotIndexes() const;
|
||||
void verifyProperties(const MachineFunction &MF);
|
||||
@ -709,8 +711,10 @@ void MachineVerifier::visitMachineFunctionBefore() {
|
||||
// Check that the register use lists are sane.
|
||||
MRI->verifyUseLists();
|
||||
|
||||
if (!MF->empty())
|
||||
if (!MF->empty()) {
|
||||
verifyStackFrame();
|
||||
verifyStackProtector();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -4038,3 +4042,49 @@ void MachineVerifier::verifyStackFrame() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MachineVerifier::verifyStackProtector() {
|
||||
const MachineFrameInfo &MFI = MF->getFrameInfo();
|
||||
if (!MFI.hasStackProtectorIndex())
|
||||
return;
|
||||
// Only applicable when the offsets of frame objects have been determined,
|
||||
// which is indicated by a non-zero stack size.
|
||||
if (!MFI.getStackSize())
|
||||
return;
|
||||
const TargetFrameLowering &TFI = *MF->getSubtarget().getFrameLowering();
|
||||
bool StackGrowsDown =
|
||||
TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown;
|
||||
// Collect the frame indices of the callee-saved registers which are spilled
|
||||
// to the stack. These are the registers that are stored above the stack
|
||||
// protector.
|
||||
SmallSet<unsigned, 4> CalleeSavedFrameIndices;
|
||||
if (MFI.isCalleeSavedInfoValid()) {
|
||||
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
|
||||
if (!Info.isSpilledToReg())
|
||||
CalleeSavedFrameIndices.insert(Info.getFrameIdx());
|
||||
}
|
||||
}
|
||||
unsigned FI = MFI.getStackProtectorIndex();
|
||||
int64_t SPStart = MFI.getObjectOffset(FI);
|
||||
int64_t SPEnd = SPStart + MFI.getObjectSize(FI);
|
||||
for (unsigned I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I) {
|
||||
if (I == FI)
|
||||
continue;
|
||||
// Variable-sized objects do not have a fixed offset.
|
||||
if (MFI.isVariableSizedObjectIndex(I))
|
||||
continue;
|
||||
if (CalleeSavedFrameIndices.contains(I))
|
||||
continue;
|
||||
int64_t ObjStart = MFI.getObjectOffset(I);
|
||||
int64_t ObjEnd = ObjStart + MFI.getObjectSize(I);
|
||||
if (SPStart < ObjEnd && ObjStart < SPEnd) {
|
||||
report("Stack protector overlaps with another stack object", MF);
|
||||
break;
|
||||
}
|
||||
if ((StackGrowsDown && SPStart <= ObjStart) ||
|
||||
(!StackGrowsDown && SPStart >= ObjStart)) {
|
||||
report("Stack protector is not the top-most object on the stack", MF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
63
llvm/test/MachineVerifier/stack-protector-offset.mir
Normal file
63
llvm/test/MachineVerifier/stack-protector-offset.mir
Normal file
@ -0,0 +1,63 @@
|
||||
# REQUIRES: aarch64-registered-target, amdgpu-registered-target
|
||||
|
||||
# RUN: split-file %s %t
|
||||
|
||||
# RUN: llc -mtriple=aarch64 -run-pass=none -o - %t/valid.mir
|
||||
# RUN: not --crash llc -mtriple=aarch64 -run-pass=none -o - %t/lower.mir 2>&1 | FileCheck %t/lower.mir
|
||||
# RUN: not --crash llc -mtriple=aarch64 -run-pass=none -o - %t/overlap.mir 2>&1 | FileCheck %t/overlap.mir
|
||||
# RUN: not --crash llc -mtriple=amdgcn -run-pass=none -o - %t/higher.mir 2>&1 | FileCheck %t/higher.mir
|
||||
|
||||
;--- valid.mir
|
||||
---
|
||||
name: valid
|
||||
frameInfo:
|
||||
stackSize: 16
|
||||
stackProtector: '%stack.1'
|
||||
stack:
|
||||
- { id: 0, offset: -24, size: 8, alignment: 8, stack-id: default }
|
||||
- { id: 1, offset: -16, size: 8, alignment: 8, stack-id: default }
|
||||
body: |
|
||||
bb.0:
|
||||
...
|
||||
|
||||
;--- lower.mir
|
||||
# CHECK: *** Bad machine code: Stack protector is not the top-most object on the stack ***
|
||||
---
|
||||
name: lower
|
||||
frameInfo:
|
||||
stackSize: 16
|
||||
stackProtector: '%stack.1'
|
||||
stack:
|
||||
- { id: 0, offset: -16, size: 8, alignment: 8, stack-id: default }
|
||||
- { id: 1, offset: -24, size: 8, alignment: 8, stack-id: default }
|
||||
body: |
|
||||
bb.0:
|
||||
...
|
||||
|
||||
;--- overlap.mir
|
||||
# CHECK: *** Bad machine code: Stack protector overlaps with another stack object ***
|
||||
---
|
||||
name: overlap
|
||||
frameInfo:
|
||||
stackSize: 16
|
||||
stackProtector: '%stack.1'
|
||||
stack:
|
||||
- { id: 0, offset: -20, size: 8, alignment: 4, stack-id: default }
|
||||
- { id: 1, offset: -16, size: 8, alignment: 8, stack-id: default }
|
||||
body: |
|
||||
bb.0:
|
||||
...
|
||||
|
||||
;--- higher.mir
|
||||
# CHECK: *** Bad machine code: Stack protector is not the top-most object on the stack ***
|
||||
---
|
||||
name: higher
|
||||
frameInfo:
|
||||
stackSize: 16
|
||||
stackProtector: '%stack.1'
|
||||
stack:
|
||||
- { id: 0, offset: 16, size: 8, alignment: 8, stack-id: default }
|
||||
- { id: 1, offset: 24, size: 8, alignment: 8, stack-id: default }
|
||||
body: |
|
||||
bb.0:
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user