mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-29 10:25:12 +00:00
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:
@@ -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
|
||||||
|
|
||||||
|
@@ -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"
|
||||||
|
@@ -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
|
|
||||||
|
Reference in New Issue
Block a user