Update in response to feedback from Chris:

- Use enums instead of magic numbers.

- Rework algorithm to use the bytes size from the target to determine when to
  emit stack protectors.

- Get rid of "propolice" in any comments.

- Renamed an option to its expanded form.

- Other miscellanenous changes.

More changes will come after this.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58723 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling
2008-11-04 21:53:09 +00:00
parent ba10fe04e7
commit 80a320d974
3 changed files with 61 additions and 34 deletions

View File

@@ -23,8 +23,19 @@ namespace llvm {
class FunctionPass; class FunctionPass;
class PassInfo; class PassInfo;
class TargetMachine; class TargetMachine;
class TargetLowering;
class RegisterCoalescer; class RegisterCoalescer;
/// StackProtectorLevel - An enumeration for when to determin when to turn
/// stack smashing protection (SSP) on.
namespace SSP {
enum StackProtectorLevel {
OFF, // Stack protectors are off.
SOME, // Stack protectors on only for functions that require them.
ALL // Stack protectors on for all functions.
};
} // end SSP namespace
/// createUnreachableBlockEliminationPass - The LLVM code generator does not /// createUnreachableBlockEliminationPass - The LLVM code generator does not
/// work well with unreachable basic blocks (what live ranges make sense for a /// work well with unreachable basic blocks (what live ranges make sense for a
/// block that cannot be reached?). As such, a code generator should either /// block that cannot be reached?). As such, a code generator should either
@@ -193,7 +204,8 @@ namespace llvm {
FunctionPass *createStackSlotColoringPass(); FunctionPass *createStackSlotColoringPass();
/// createStackProtectorPass - This pass adds stack protectors to functions. /// createStackProtectorPass - This pass adds stack protectors to functions.
FunctionPass *createStackProtectorPass(int Level); FunctionPass *createStackProtectorPass(SSP::StackProtectorLevel lvl,
const TargetLowering *tli);
} // End llvm namespace } // End llvm namespace

View File

@@ -61,9 +61,17 @@ EnableFastISelOption("fast-isel", cl::Hidden,
cl::desc("Enable the experimental \"fast\" instruction selector")); cl::desc("Enable the experimental \"fast\" instruction selector"));
// Enable stack protectors. // Enable stack protectors.
static cl::opt<int> static cl::opt<SSP::StackProtectorLevel>
EnableStackProtector("enable-stack-protector", cl::init(0), EnableStackProtector("enable-stack-protector",
cl::desc("Use ProPolice as a stack protection method.")); cl::desc("Stack canary protection level: (default: off)"),
cl::init(SSP::OFF),
cl::values(clEnumValN(SSP::ALL, "all",
"All functions get stack protectors."),
clEnumValN(SSP::SOME, "some",
"Only functions requiring stack protectors get them."),
clEnumValN(SSP::OFF, "off",
"No functions get stack protectors."),
clEnumValEnd));
FileModel::Model FileModel::Model
LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
@@ -170,7 +178,8 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, bool Fast) {
if (!Fast) if (!Fast)
PM.add(createCodeGenPreparePass(getTargetLowering())); PM.add(createCodeGenPreparePass(getTargetLowering()));
PM.add(createStackProtectorPass(EnableStackProtector)); if (EnableStackProtector != SSP::OFF)
PM.add(createStackProtectorPass(EnableStackProtector, getTargetLowering()));
if (PrintISelInput) if (PrintISelInput)
PM.add(createPrintFunctionPass("\n\n" PM.add(createPrintFunctionPass("\n\n"

View File

@@ -7,10 +7,9 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This pass inserts stack protectors into functions which need them. The stack // This pass inserts stack protectors into functions which need them. A variable
// protectors this uses are the type that ProPolice used. A variable with a // with a random value in it is stored onto the stack before the local variables
// random value in it is stored onto the stack before the local variables are // are allocated. Upon exiting the block, the stored value is checked. If it's
// allocated. Upon exitting the block, the stored value is checked. If it's
// changed, then there was some sort of violation and the program aborts. // changed, then there was some sort of violation and the program aborts.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@@ -25,20 +24,24 @@
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/ADT/APInt.h" #include "llvm/ADT/APInt.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
using namespace llvm; using namespace llvm;
// Enable stack protectors. // Enable stack protectors.
static cl::opt<unsigned> static cl::opt<unsigned>
SSPBufferSize("ssp-buffer-size", cl::init(8), SSPBufferSize("stack-protector-buffer-size", cl::init(8),
cl::desc("The lower bound for a buffer to be considered for " cl::desc("The lower bound for a buffer to be considered for "
"stack smashing protection.")); "stack smashing protection."));
namespace { namespace {
class VISIBILITY_HIDDEN StackProtector : public FunctionPass { class VISIBILITY_HIDDEN StackProtector : public FunctionPass {
// Level == 0 -- Stack protectors are off. /// Level - The level of stack protection.
// Level == 1 -- Stack protectors are on only for some functions. SSP::StackProtectorLevel Level;
// Level == 2 -- Stack protectors are on for all functions.
int Level; /// TLI - Keep a pointer of a TargetLowering to consult for determining
/// target type sizes.
const TargetLowering *TLI;
/// FailBB - Holds the basic block to jump to when the stack protector check /// FailBB - Holds the basic block to jump to when the stack protector check
/// fails. /// fails.
@@ -70,10 +73,12 @@ namespace {
/// RequiresStackProtector - Check whether or not this function needs a /// RequiresStackProtector - Check whether or not this function needs a
/// stack protector based upon the stack protector level. /// stack protector based upon the stack protector level.
bool RequiresStackProtector(); bool RequiresStackProtector() const;
public: public:
static char ID; // Pass identification, replacement for typeid. static char ID; // Pass identification, replacement for typeid.
StackProtector(int lvl = 0) : FunctionPass(&ID), Level(lvl), FailBB(0) {} StackProtector() : FunctionPass(&ID), Level(SSP::OFF), TLI(0), FailBB(0) {}
StackProtector(SSP::StackProtectorLevel lvl, const TargetLowering *tli)
: FunctionPass(&ID), Level(lvl), TLI(tli), FailBB(0) {}
virtual bool runOnFunction(Function &Fn); virtual bool runOnFunction(Function &Fn);
}; };
@@ -83,8 +88,9 @@ char StackProtector::ID = 0;
static RegisterPass<StackProtector> static RegisterPass<StackProtector>
X("stack-protector", "Insert stack protectors"); X("stack-protector", "Insert stack protectors");
FunctionPass *llvm::createStackProtectorPass(int lvl) { FunctionPass *llvm::createStackProtectorPass(SSP::StackProtectorLevel lvl,
return new StackProtector(lvl); const TargetLowering *tli) {
return new StackProtector(lvl, tli);
} }
bool StackProtector::runOnFunction(Function &Fn) { bool StackProtector::runOnFunction(Function &Fn) {
@@ -119,8 +125,8 @@ void StackProtector::InsertStackProtectorPrologue() {
StackProtFrameSlot = new AllocaInst(PointerType::getUnqual(Type::Int8Ty), StackProtFrameSlot = new AllocaInst(PointerType::getUnqual(Type::Int8Ty),
"StackProt_Frame", &InsertPt); "StackProt_Frame", &InsertPt);
LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", true, &InsertPt); LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, &InsertPt);
new StoreInst(LI, StackProtFrameSlot, true, &InsertPt); new StoreInst(LI, StackProtFrameSlot, false, &InsertPt);
} }
/// InsertStackProtectorEpilogue - Insert code before the return instructions /// InsertStackProtectorEpilogue - Insert code before the return instructions
@@ -135,7 +141,7 @@ void StackProtector::InsertStackProtectorEpilogue() {
ReturnBBs.reserve(F->size()); ReturnBBs.reserve(F->size());
for (; I != E; ++I) for (; I != E; ++I)
if (isa<ReturnInst>((*I).getTerminator())) if (isa<ReturnInst>(I->getTerminator()))
ReturnBBs.push_back(I); ReturnBBs.push_back(I);
if (ReturnBBs.empty()) return; // Odd, but could happen. . . if (ReturnBBs.empty()) return; // Odd, but could happen. . .
@@ -188,41 +194,41 @@ void StackProtector::CreateFailBB() {
FailBB = BasicBlock::Create("CallStackCheckFailBlk", F); FailBB = BasicBlock::Create("CallStackCheckFailBlk", F);
std::vector<const Type*> Params; std::vector<const Type*> Params;
Constant *StackChkFail = Constant *StackChkFail =
M->getOrInsertFunction("__stack_chk_fail", M->getOrInsertFunction("__stack_chk_fail", Type::VoidTy, NULL);
FunctionType::get(Type::VoidTy, Params, false));
CallInst::Create(StackChkFail, "", FailBB); CallInst::Create(StackChkFail, "", FailBB);
new UnreachableInst(FailBB); new UnreachableInst(FailBB);
} }
/// RequiresStackProtector - Check whether or not this function needs a stack /// RequiresStackProtector - Check whether or not this function needs a stack
/// protector based upon the stack protector level. /// protector based upon the stack protector level.
bool StackProtector::RequiresStackProtector() { bool StackProtector::RequiresStackProtector() const {
switch (Level) { switch (Level) {
default: return false; default: return false;
case 2: return true; case SSP::ALL: return true;
case 1: { case SSP::SOME: {
// If the size of the local variables allocated on the stack is greater than // If the size of the local variables allocated on the stack is greater than
// SSPBufferSize, then we require a stack protector. // SSPBufferSize, then we require a stack protector.
uint64_t StackSize = 0; uint64_t StackSize = 0;
const TargetData *TD = TLI->getTargetData();
for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
BasicBlock *BB = I; BasicBlock *BB = I;
for (BasicBlock::iterator for (BasicBlock::iterator
II = BB->begin(), IE = BB->end(); II != IE; ++II) II = BB->begin(), IE = BB->end(); II != IE; ++II)
if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(AI->getArraySize())) { if (ConstantInt *CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
uint64_t Bytes = TD->getTypeSizeInBits(AI->getAllocatedType()) / 8;
const APInt &Size = CI->getValue(); const APInt &Size = CI->getValue();
StackSize += Size.getZExtValue() * 8; StackSize += Bytes * Size.getZExtValue();
}
}
if (SSPBufferSize <= StackSize) if (SSPBufferSize <= StackSize)
return true; return true;
}
}
}
return false; return false;
} }
} }
} }
// [EOF] StackProtector.cpp