diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-09-23 18:07:56 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-09-23 18:07:56 +0000 |
commit | a2002b08f7bd0e165a14a91322acf917bb6c52ea (patch) | |
tree | 4c769bbd2e49b5618af12131e59539102908680a /llvm/lib/Transforms/Instrumentation | |
parent | b14ecd34f73d8d5414dd6705d0d365eb873889ab (diff) | |
download | bcm5719-llvm-a2002b08f7bd0e165a14a91322acf917bb6c52ea.tar.gz bcm5719-llvm-a2002b08f7bd0e165a14a91322acf917bb6c52ea.zip |
Android support for SafeStack.
Add two new ways of accessing the unsafe stack pointer:
* At a fixed offset from the thread TLS base. This is very similar to
StackProtector cookies, but we plan to extend it to other backends
(ARM in particular) soon. Bionic-side implementation here:
https://android-review.googlesource.com/170988.
* Via a function call, as a fallback for platforms that provide
neither a fixed TLS slot, nor a reasonable TLS implementation (i.e.
not emutls).
This is a re-commit of a change in r248357 that was reverted in
r248358.
llvm-svn: 248405
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/SafeStack.cpp | 112 |
1 files changed, 71 insertions, 41 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/SafeStack.cpp b/llvm/lib/Transforms/Instrumentation/SafeStack.cpp index fdf96cc130a..b28ae8fc4a9 100644 --- a/llvm/lib/Transforms/Instrumentation/SafeStack.cpp +++ b/llvm/lib/Transforms/Instrumentation/SafeStack.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -36,6 +37,8 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_os_ostream.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -43,6 +46,9 @@ using namespace llvm; #define DEBUG_TYPE "safestack" +static const char *const kUnsafeStackPtrVar = "__safestack_unsafe_stack_ptr"; +static const char *const kUnsafeStackPtrAddrFn = "__safestack_pointer_address"; + namespace llvm { STATISTIC(NumFunctions, "Total number of functions"); @@ -157,6 +163,8 @@ bool IsSafeStackAlloca(const AllocaInst *AI) { /// (as determined statically), and the unsafe stack, which contains all /// local variables that are accessed in unsafe ways. class SafeStack : public FunctionPass { + const TargetMachine *TM; + const TargetLoweringBase *TLI; const DataLayout *DL; Type *StackPtrTy; @@ -164,7 +172,7 @@ class SafeStack : public FunctionPass { Type *Int32Ty; Type *Int8Ty; - Constant *UnsafeStackPtr = nullptr; + Value *UnsafeStackPtr = nullptr; /// Unsafe stack alignment. Each stack frame must ensure that the stack is /// aligned to this value. We need to re-align the unsafe stack if the @@ -176,7 +184,7 @@ class SafeStack : public FunctionPass { /// \brief Build a constant representing a pointer to the unsafe stack /// pointer. - Constant *getOrCreateUnsafeStackPtr(Module &M); + Value *getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F); /// \brief Find all static allocas, dynamic allocas, return instructions and /// stack restore points (exception unwind blocks and setjmp calls) in the @@ -192,7 +200,7 @@ class SafeStack : public FunctionPass { /// /// \returns A pointer to the top of the unsafe stack after all unsafe static /// allocas are allocated. - Value *moveStaticAllocasToUnsafeStack(Function &F, + Value *moveStaticAllocasToUnsafeStack(IRBuilder<> &IRB, Function &F, ArrayRef<AllocaInst *> StaticAllocas, ArrayRef<ReturnInst *> Returns); @@ -215,9 +223,11 @@ class SafeStack : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid. - SafeStack() : FunctionPass(ID), DL(nullptr) { + SafeStack(const TargetMachine *TM) + : FunctionPass(ID), TM(TM), TLI(nullptr), DL(nullptr) { initializeSafeStackPass(*PassRegistry::getPassRegistry()); } + SafeStack() : SafeStack(nullptr) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<AAResultsWrapperPass>(); @@ -237,35 +247,52 @@ public: bool runOnFunction(Function &F) override; }; // class SafeStack -Constant *SafeStack::getOrCreateUnsafeStackPtr(Module &M) { - // The unsafe stack pointer is stored in a global variable with a magic name. - const char *kUnsafeStackPtrVar = "__safestack_unsafe_stack_ptr"; - - auto UnsafeStackPtr = - dyn_cast_or_null<GlobalVariable>(M.getNamedValue(kUnsafeStackPtrVar)); - - if (!UnsafeStackPtr) { - // The global variable is not defined yet, define it ourselves. - // We use the initial-exec TLS model because we do not support the variable - // living anywhere other than in the main executable. - UnsafeStackPtr = new GlobalVariable( - /*Module=*/M, /*Type=*/StackPtrTy, - /*isConstant=*/false, /*Linkage=*/GlobalValue::ExternalLinkage, - /*Initializer=*/0, /*Name=*/kUnsafeStackPtrVar, - /*InsertBefore=*/nullptr, - /*ThreadLocalMode=*/GlobalValue::InitialExecTLSModel); +Value *SafeStack::getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F) { + Module &M = *F.getParent(); + Triple TargetTriple(M.getTargetTriple()); + + unsigned Offset; + unsigned AddressSpace; + // Check if the target keeps the unsafe stack pointer at a fixed offset. + if (TLI && TLI->getSafeStackPointerLocation(Offset, AddressSpace)) { + Constant *OffsetVal = + ConstantInt::get(Type::getInt32Ty(F.getContext()), Offset); + return ConstantExpr::getIntToPtr(OffsetVal, + StackPtrTy->getPointerTo(AddressSpace)); + } + + // Android provides a libc function that returns the stack pointer address. + if (TargetTriple.getEnvironment() == llvm::Triple::Android) { + Value *Fn = M.getOrInsertFunction(kUnsafeStackPtrAddrFn, + StackPtrTy->getPointerTo(0), nullptr); + return IRB.CreateCall(Fn); } else { - // The variable exists, check its type and attributes. - if (UnsafeStackPtr->getValueType() != StackPtrTy) { - report_fatal_error(Twine(kUnsafeStackPtrVar) + " must have void* type"); - } + // Otherwise, declare a thread-local variable with a magic name. + auto UnsafeStackPtr = + dyn_cast_or_null<GlobalVariable>(M.getNamedValue(kUnsafeStackPtrVar)); + + if (!UnsafeStackPtr) { + // The global variable is not defined yet, define it ourselves. + // We use the initial-exec TLS model because we do not support the + // variable living anywhere other than in the main executable. + UnsafeStackPtr = new GlobalVariable( + /*Module=*/M, /*Type=*/StackPtrTy, + /*isConstant=*/false, /*Linkage=*/GlobalValue::ExternalLinkage, + /*Initializer=*/0, /*Name=*/kUnsafeStackPtrVar, + /*InsertBefore=*/nullptr, + /*ThreadLocalMode=*/GlobalValue::InitialExecTLSModel); + } else { + // The variable exists, check its type and attributes. + if (UnsafeStackPtr->getValueType() != StackPtrTy) { + report_fatal_error(Twine(kUnsafeStackPtrVar) + " must have void* type"); + } - if (!UnsafeStackPtr->isThreadLocal()) { - report_fatal_error(Twine(kUnsafeStackPtrVar) + " must be thread-local"); + if (!UnsafeStackPtr->isThreadLocal()) { + report_fatal_error(Twine(kUnsafeStackPtrVar) + " must be thread-local"); + } } + return UnsafeStackPtr; } - - return UnsafeStackPtr; } void SafeStack::findInsts(Function &F, @@ -349,13 +376,12 @@ SafeStack::createStackRestorePoints(Function &F, } Value * -SafeStack::moveStaticAllocasToUnsafeStack(Function &F, +SafeStack::moveStaticAllocasToUnsafeStack(IRBuilder<> &IRB, Function &F, ArrayRef<AllocaInst *> StaticAllocas, ArrayRef<ReturnInst *> Returns) { if (StaticAllocas.empty()) return nullptr; - IRBuilder<> IRB(F.getEntryBlock().getFirstInsertionPt()); DIBuilder DIB(*F.getParent()); // We explicitly compute and set the unsafe stack layout for all unsafe @@ -511,8 +537,6 @@ void SafeStack::moveDynamicAllocasToUnsafeStack( } bool SafeStack::runOnFunction(Function &F) { - auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); - DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n"); if (!F.hasFnAttribute(Attribute::SafeStack)) { @@ -527,6 +551,10 @@ bool SafeStack::runOnFunction(Function &F) { return false; } + auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); + + TLI = TM ? TM->getSubtargetImpl(F)->getTargetLowering() : nullptr; + { // Make sure the regular stack protector won't run on this function // (safestack attribute takes precedence). @@ -572,11 +600,11 @@ bool SafeStack::runOnFunction(Function &F) { if (!StackRestorePoints.empty()) ++NumUnsafeStackRestorePointsFunctions; - if (!UnsafeStackPtr) - UnsafeStackPtr = getOrCreateUnsafeStackPtr(*F.getParent()); + IRBuilder<> IRB(F.begin()->getFirstInsertionPt()); + UnsafeStackPtr = getOrCreateUnsafeStackPtr(IRB, F); // The top of the unsafe stack after all unsafe static allocas are allocated. - Value *StaticTop = moveStaticAllocasToUnsafeStack(F, StaticAllocas, Returns); + Value *StaticTop = moveStaticAllocasToUnsafeStack(IRB, F, StaticAllocas, Returns); // Safe stack object that stores the current unsafe stack top. It is updated // as unsafe dynamic (non-constant-sized) allocas are allocated and freed. @@ -598,9 +626,11 @@ bool SafeStack::runOnFunction(Function &F) { } // end anonymous namespace char SafeStack::ID = 0; -INITIALIZE_PASS_BEGIN(SafeStack, "safe-stack", - "Safe Stack instrumentation pass", false, false) -INITIALIZE_PASS_END(SafeStack, "safe-stack", "Safe Stack instrumentation pass", - false, false) +INITIALIZE_TM_PASS_BEGIN(SafeStack, "safe-stack", + "Safe Stack instrumentation pass", false, false) +INITIALIZE_TM_PASS_END(SafeStack, "safe-stack", + "Safe Stack instrumentation pass", false, false) -FunctionPass *llvm::createSafeStackPass() { return new SafeStack(); } +FunctionPass *llvm::createSafeStackPass(const llvm::TargetMachine *TM) { + return new SafeStack(TM); +} |