summaryrefslogtreecommitdiff
path: root/lib/CodeGen/StackProtector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/StackProtector.cpp')
-rw-r--r--lib/CodeGen/StackProtector.cpp87
1 files changed, 60 insertions, 27 deletions
diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp
index cb22082e4d..d2d87b2c96 100644
--- a/lib/CodeGen/StackProtector.cpp
+++ b/lib/CodeGen/StackProtector.cpp
@@ -48,12 +48,17 @@ EnableSelectionDAGSP("enable-selectiondag-sp", cl::init(true),
char StackProtector::ID = 0;
INITIALIZE_PASS(StackProtector, "stack-protector",
- "Insert stack protectors", false, false)
+ "Insert stack protectors", false, true)
FunctionPass *llvm::createStackProtectorPass(const TargetMachine *TM) {
return new StackProtector(TM);
}
+StackProtector::SSPLayoutKind StackProtector::getSSPLayout(const AllocaInst *AI)
+ const {
+ return AI ? Layout.lookup(AI) : SSPLK_None;
+}
+
bool StackProtector::runOnFunction(Function &Fn) {
F = &Fn;
M = F->getParent();
@@ -72,39 +77,51 @@ bool StackProtector::runOnFunction(Function &Fn) {
return InsertStackProtectors();
}
-/// ContainsProtectableArray - Check whether the type either is an array or
-/// contains a char array of sufficient size so that we need stack protectors
-/// for it.
-bool StackProtector::ContainsProtectableArray(Type *Ty, bool Strong,
- bool InStruct) const {
+/// \param [out] IsLarge is set to true if a protectable array is found and
+/// it is "large" ( >= ssp-buffer-size). In the case of a structure with
+/// multiple arrays, this gets set if any of them is large.
+bool StackProtector::ContainsProtectableArray(Type *Ty, bool &IsLarge,
+ bool Strong, bool InStruct)
+ const {
if (!Ty) return false;
if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
- // In strong mode any array, regardless of type and size, triggers a
- // protector
- if (Strong)
- return true;
if (!AT->getElementType()->isIntegerTy(8)) {
// If we're on a non-Darwin platform or we're inside of a structure, don't
// add stack protectors unless the array is a character array.
- if (InStruct || !Trip.isOSDarwin())
- return false;
+ // However, in strong mode any array, regardless of type and size,
+ // triggers a protector.
+ if (!Strong && (InStruct || !Trip.isOSDarwin()))
+ return false;
}
// If an array has more than SSPBufferSize bytes of allocated space, then we
// emit stack protectors.
- if (SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT))
+ if (SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT)) {
+ IsLarge = true;
+ return true;
+ }
+
+ if (Strong)
+ // Require a protector for all arrays in strong mode
return true;
}
const StructType *ST = dyn_cast<StructType>(Ty);
if (!ST) return false;
+ bool NeedsProtector = false;
for (StructType::element_iterator I = ST->element_begin(),
E = ST->element_end(); I != E; ++I)
- if (ContainsProtectableArray(*I, Strong, true))
- return true;
+ if (ContainsProtectableArray(*I, IsLarge, Strong, true)) {
+ // If the element is a protectable array and is large (>= SSPBufferSize)
+ // then we are done. If the protectable array is not large, then
+ // keep looking in case a subsequent element is a large array.
+ if (IsLarge)
+ return true;
+ NeedsProtector = true;
+ }
- return false;
+ return NeedsProtector;
}
bool StackProtector::HasAddressTaken(const Instruction *AI) {
@@ -156,11 +173,13 @@ bool StackProtector::HasAddressTaken(const Instruction *AI) {
/// address taken.
bool StackProtector::RequiresStackProtector() {
bool Strong = false;
+ bool NeedsProtector = false;
if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
- Attribute::StackProtectReq))
- return true;
- else if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
- Attribute::StackProtectStrong))
+ Attribute::StackProtectReq)) {
+ NeedsProtector = true;
+ Strong = true; // Use the same heuristic as strong to determine SSPLayout
+ } else if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::StackProtectStrong))
Strong = true;
else if (!F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
Attribute::StackProtect))
@@ -180,28 +199,42 @@ bool StackProtector::RequiresStackProtector() {
if (const ConstantInt *CI =
dyn_cast<ConstantInt>(AI->getArraySize())) {
- if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize)
+ if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {
// A call to alloca with size >= SSPBufferSize requires
// stack protectors.
- return true;
+ Layout.insert(std::make_pair(AI, SSPLK_LargeArray));
+ NeedsProtector = true;
+ } else if (Strong) {
+ // Require protectors for all alloca calls in strong mode.
+ Layout.insert(std::make_pair(AI, SSPLK_SmallArray));
+ NeedsProtector = true;
+ }
} else {
// A call to alloca with a variable size requires protectors.
- return true;
+ Layout.insert(std::make_pair(AI, SSPLK_LargeArray));
+ NeedsProtector = true;
}
+ continue;
}
- if (ContainsProtectableArray(AI->getAllocatedType(), Strong))
- return true;
+ bool IsLarge = false;
+ if (ContainsProtectableArray(AI->getAllocatedType(), IsLarge, Strong)) {
+ Layout.insert(std::make_pair(AI, IsLarge ? SSPLK_LargeArray
+ : SSPLK_SmallArray));
+ NeedsProtector = true;
+ continue;
+ }
if (Strong && HasAddressTaken(AI)) {
++NumAddrTaken;
- return true;
+ Layout.insert(std::make_pair(AI, SSPLK_AddrOf));
+ NeedsProtector = true;
}
}
}
}
- return false;
+ return NeedsProtector;
}
static bool InstructionWillNotHaveChain(const Instruction *I) {