13ca95b02SDimitry Andric //===-- SafeStack.cpp - Safe Stack Insertion ------------------------------===// 23ca95b02SDimitry Andric // 33ca95b02SDimitry Andric // The LLVM Compiler Infrastructure 43ca95b02SDimitry Andric // 53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source 63ca95b02SDimitry Andric // License. See LICENSE.TXT for details. 73ca95b02SDimitry Andric // 83ca95b02SDimitry Andric //===----------------------------------------------------------------------===// 93ca95b02SDimitry Andric // 103ca95b02SDimitry Andric // This pass splits the stack into the safe stack (kept as-is for LLVM backend) 113ca95b02SDimitry Andric // and the unsafe stack (explicitly allocated and managed through the runtime 123ca95b02SDimitry Andric // support library). 133ca95b02SDimitry Andric // 143ca95b02SDimitry Andric // http://clang.llvm.org/docs/SafeStack.html 153ca95b02SDimitry Andric // 163ca95b02SDimitry Andric //===----------------------------------------------------------------------===// 173ca95b02SDimitry Andric 183ca95b02SDimitry Andric #include "SafeStackColoring.h" 193ca95b02SDimitry Andric #include "SafeStackLayout.h" 203ca95b02SDimitry Andric #include "llvm/ADT/Statistic.h" 213ca95b02SDimitry Andric #include "llvm/ADT/Triple.h" 223ca95b02SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h" 233ca95b02SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h" 243ca95b02SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h" 253ca95b02SDimitry Andric #include "llvm/CodeGen/Passes.h" 263ca95b02SDimitry Andric #include "llvm/IR/Constants.h" 273ca95b02SDimitry Andric #include "llvm/IR/DIBuilder.h" 283ca95b02SDimitry Andric #include "llvm/IR/DataLayout.h" 293ca95b02SDimitry Andric #include "llvm/IR/DerivedTypes.h" 303ca95b02SDimitry Andric #include "llvm/IR/Function.h" 313ca95b02SDimitry Andric #include "llvm/IR/IRBuilder.h" 323ca95b02SDimitry Andric #include "llvm/IR/InstIterator.h" 333ca95b02SDimitry Andric #include "llvm/IR/Instructions.h" 343ca95b02SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 353ca95b02SDimitry Andric #include "llvm/IR/Intrinsics.h" 363ca95b02SDimitry Andric #include "llvm/IR/MDBuilder.h" 373ca95b02SDimitry Andric #include "llvm/IR/Module.h" 383ca95b02SDimitry Andric #include "llvm/Pass.h" 393ca95b02SDimitry Andric #include "llvm/Support/CommandLine.h" 403ca95b02SDimitry Andric #include "llvm/Support/Debug.h" 413ca95b02SDimitry Andric #include "llvm/Support/Format.h" 423ca95b02SDimitry Andric #include "llvm/Support/MathExtras.h" 433ca95b02SDimitry Andric #include "llvm/Support/raw_os_ostream.h" 443ca95b02SDimitry Andric #include "llvm/Target/TargetLowering.h" 453ca95b02SDimitry Andric #include "llvm/Target/TargetSubtargetInfo.h" 463ca95b02SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 473ca95b02SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 483ca95b02SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 493ca95b02SDimitry Andric 503ca95b02SDimitry Andric using namespace llvm; 513ca95b02SDimitry Andric using namespace llvm::safestack; 523ca95b02SDimitry Andric 533ca95b02SDimitry Andric #define DEBUG_TYPE "safestack" 543ca95b02SDimitry Andric 553ca95b02SDimitry Andric namespace llvm { 563ca95b02SDimitry Andric 573ca95b02SDimitry Andric STATISTIC(NumFunctions, "Total number of functions"); 583ca95b02SDimitry Andric STATISTIC(NumUnsafeStackFunctions, "Number of functions with unsafe stack"); 593ca95b02SDimitry Andric STATISTIC(NumUnsafeStackRestorePointsFunctions, 603ca95b02SDimitry Andric "Number of functions that use setjmp or exceptions"); 613ca95b02SDimitry Andric 623ca95b02SDimitry Andric STATISTIC(NumAllocas, "Total number of allocas"); 633ca95b02SDimitry Andric STATISTIC(NumUnsafeStaticAllocas, "Number of unsafe static allocas"); 643ca95b02SDimitry Andric STATISTIC(NumUnsafeDynamicAllocas, "Number of unsafe dynamic allocas"); 653ca95b02SDimitry Andric STATISTIC(NumUnsafeByValArguments, "Number of unsafe byval arguments"); 663ca95b02SDimitry Andric STATISTIC(NumUnsafeStackRestorePoints, "Number of setjmps and landingpads"); 673ca95b02SDimitry Andric 683ca95b02SDimitry Andric } // namespace llvm 693ca95b02SDimitry Andric 703ca95b02SDimitry Andric namespace { 713ca95b02SDimitry Andric 723ca95b02SDimitry Andric /// Rewrite an SCEV expression for a memory access address to an expression that 733ca95b02SDimitry Andric /// represents offset from the given alloca. 743ca95b02SDimitry Andric /// 753ca95b02SDimitry Andric /// The implementation simply replaces all mentions of the alloca with zero. 763ca95b02SDimitry Andric class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> { 773ca95b02SDimitry Andric const Value *AllocaPtr; 783ca95b02SDimitry Andric 793ca95b02SDimitry Andric public: 803ca95b02SDimitry Andric AllocaOffsetRewriter(ScalarEvolution &SE, const Value *AllocaPtr) 813ca95b02SDimitry Andric : SCEVRewriteVisitor(SE), AllocaPtr(AllocaPtr) {} 823ca95b02SDimitry Andric 833ca95b02SDimitry Andric const SCEV *visitUnknown(const SCEVUnknown *Expr) { 843ca95b02SDimitry Andric if (Expr->getValue() == AllocaPtr) 853ca95b02SDimitry Andric return SE.getZero(Expr->getType()); 863ca95b02SDimitry Andric return Expr; 873ca95b02SDimitry Andric } 883ca95b02SDimitry Andric }; 893ca95b02SDimitry Andric 903ca95b02SDimitry Andric /// The SafeStack pass splits the stack of each function into the safe 913ca95b02SDimitry Andric /// stack, which is only accessed through memory safe dereferences (as 923ca95b02SDimitry Andric /// determined statically), and the unsafe stack, which contains all 933ca95b02SDimitry Andric /// local variables that are accessed in ways that we can't prove to 943ca95b02SDimitry Andric /// be safe. 953ca95b02SDimitry Andric class SafeStack : public FunctionPass { 963ca95b02SDimitry Andric const TargetMachine *TM; 973ca95b02SDimitry Andric const TargetLoweringBase *TL; 983ca95b02SDimitry Andric const DataLayout *DL; 993ca95b02SDimitry Andric ScalarEvolution *SE; 1003ca95b02SDimitry Andric 1013ca95b02SDimitry Andric Type *StackPtrTy; 1023ca95b02SDimitry Andric Type *IntPtrTy; 1033ca95b02SDimitry Andric Type *Int32Ty; 1043ca95b02SDimitry Andric Type *Int8Ty; 1053ca95b02SDimitry Andric 1063ca95b02SDimitry Andric Value *UnsafeStackPtr = nullptr; 1073ca95b02SDimitry Andric 1083ca95b02SDimitry Andric /// Unsafe stack alignment. Each stack frame must ensure that the stack is 1093ca95b02SDimitry Andric /// aligned to this value. We need to re-align the unsafe stack if the 1103ca95b02SDimitry Andric /// alignment of any object on the stack exceeds this value. 1113ca95b02SDimitry Andric /// 1123ca95b02SDimitry Andric /// 16 seems like a reasonable upper bound on the alignment of objects that we 1133ca95b02SDimitry Andric /// might expect to appear on the stack on most common targets. 1143ca95b02SDimitry Andric enum { StackAlignment = 16 }; 1153ca95b02SDimitry Andric 1163ca95b02SDimitry Andric /// \brief Return the value of the stack canary. 1173ca95b02SDimitry Andric Value *getStackGuard(IRBuilder<> &IRB, Function &F); 1183ca95b02SDimitry Andric 1193ca95b02SDimitry Andric /// \brief Load stack guard from the frame and check if it has changed. 1203ca95b02SDimitry Andric void checkStackGuard(IRBuilder<> &IRB, Function &F, ReturnInst &RI, 1213ca95b02SDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard); 1223ca95b02SDimitry Andric 1233ca95b02SDimitry Andric /// \brief Find all static allocas, dynamic allocas, return instructions and 1243ca95b02SDimitry Andric /// stack restore points (exception unwind blocks and setjmp calls) in the 1253ca95b02SDimitry Andric /// given function and append them to the respective vectors. 1263ca95b02SDimitry Andric void findInsts(Function &F, SmallVectorImpl<AllocaInst *> &StaticAllocas, 1273ca95b02SDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas, 1283ca95b02SDimitry Andric SmallVectorImpl<Argument *> &ByValArguments, 1293ca95b02SDimitry Andric SmallVectorImpl<ReturnInst *> &Returns, 1303ca95b02SDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints); 1313ca95b02SDimitry Andric 1323ca95b02SDimitry Andric /// \brief Calculate the allocation size of a given alloca. Returns 0 if the 1333ca95b02SDimitry Andric /// size can not be statically determined. 1343ca95b02SDimitry Andric uint64_t getStaticAllocaAllocationSize(const AllocaInst* AI); 1353ca95b02SDimitry Andric 1363ca95b02SDimitry Andric /// \brief Allocate space for all static allocas in \p StaticAllocas, 1373ca95b02SDimitry Andric /// replace allocas with pointers into the unsafe stack and generate code to 1383ca95b02SDimitry Andric /// restore the stack pointer before all return instructions in \p Returns. 1393ca95b02SDimitry Andric /// 1403ca95b02SDimitry Andric /// \returns A pointer to the top of the unsafe stack after all unsafe static 1413ca95b02SDimitry Andric /// allocas are allocated. 1423ca95b02SDimitry Andric Value *moveStaticAllocasToUnsafeStack(IRBuilder<> &IRB, Function &F, 1433ca95b02SDimitry Andric ArrayRef<AllocaInst *> StaticAllocas, 1443ca95b02SDimitry Andric ArrayRef<Argument *> ByValArguments, 1453ca95b02SDimitry Andric ArrayRef<ReturnInst *> Returns, 1463ca95b02SDimitry Andric Instruction *BasePointer, 1473ca95b02SDimitry Andric AllocaInst *StackGuardSlot); 1483ca95b02SDimitry Andric 1493ca95b02SDimitry Andric /// \brief Generate code to restore the stack after all stack restore points 1503ca95b02SDimitry Andric /// in \p StackRestorePoints. 1513ca95b02SDimitry Andric /// 1523ca95b02SDimitry Andric /// \returns A local variable in which to maintain the dynamic top of the 1533ca95b02SDimitry Andric /// unsafe stack if needed. 1543ca95b02SDimitry Andric AllocaInst * 1553ca95b02SDimitry Andric createStackRestorePoints(IRBuilder<> &IRB, Function &F, 1563ca95b02SDimitry Andric ArrayRef<Instruction *> StackRestorePoints, 1573ca95b02SDimitry Andric Value *StaticTop, bool NeedDynamicTop); 1583ca95b02SDimitry Andric 1593ca95b02SDimitry Andric /// \brief Replace all allocas in \p DynamicAllocas with code to allocate 1603ca95b02SDimitry Andric /// space dynamically on the unsafe stack and store the dynamic unsafe stack 1613ca95b02SDimitry Andric /// top to \p DynamicTop if non-null. 1623ca95b02SDimitry Andric void moveDynamicAllocasToUnsafeStack(Function &F, Value *UnsafeStackPtr, 1633ca95b02SDimitry Andric AllocaInst *DynamicTop, 1643ca95b02SDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas); 1653ca95b02SDimitry Andric 1663ca95b02SDimitry Andric bool IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize); 1673ca95b02SDimitry Andric 1683ca95b02SDimitry Andric bool IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, 1693ca95b02SDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize); 1703ca95b02SDimitry Andric bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr, 1713ca95b02SDimitry Andric uint64_t AllocaSize); 1723ca95b02SDimitry Andric 1733ca95b02SDimitry Andric public: 1743ca95b02SDimitry Andric static char ID; // Pass identification, replacement for typeid. 1753ca95b02SDimitry Andric SafeStack(const TargetMachine *TM) 1763ca95b02SDimitry Andric : FunctionPass(ID), TM(TM), TL(nullptr), DL(nullptr) { 1773ca95b02SDimitry Andric initializeSafeStackPass(*PassRegistry::getPassRegistry()); 1783ca95b02SDimitry Andric } 1793ca95b02SDimitry Andric SafeStack() : SafeStack(nullptr) {} 1803ca95b02SDimitry Andric 1813ca95b02SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 1823ca95b02SDimitry Andric AU.addRequired<ScalarEvolutionWrapperPass>(); 1833ca95b02SDimitry Andric } 1843ca95b02SDimitry Andric 1853ca95b02SDimitry Andric bool doInitialization(Module &M) override { 1863ca95b02SDimitry Andric DL = &M.getDataLayout(); 1873ca95b02SDimitry Andric 1883ca95b02SDimitry Andric StackPtrTy = Type::getInt8PtrTy(M.getContext()); 1893ca95b02SDimitry Andric IntPtrTy = DL->getIntPtrType(M.getContext()); 1903ca95b02SDimitry Andric Int32Ty = Type::getInt32Ty(M.getContext()); 1913ca95b02SDimitry Andric Int8Ty = Type::getInt8Ty(M.getContext()); 1923ca95b02SDimitry Andric 1933ca95b02SDimitry Andric return false; 1943ca95b02SDimitry Andric } 1953ca95b02SDimitry Andric 1963ca95b02SDimitry Andric bool runOnFunction(Function &F) override; 1973ca95b02SDimitry Andric }; // class SafeStack 1983ca95b02SDimitry Andric 1993ca95b02SDimitry Andric uint64_t SafeStack::getStaticAllocaAllocationSize(const AllocaInst* AI) { 2003ca95b02SDimitry Andric uint64_t Size = DL->getTypeAllocSize(AI->getAllocatedType()); 2013ca95b02SDimitry Andric if (AI->isArrayAllocation()) { 2023ca95b02SDimitry Andric auto C = dyn_cast<ConstantInt>(AI->getArraySize()); 2033ca95b02SDimitry Andric if (!C) 2043ca95b02SDimitry Andric return 0; 2053ca95b02SDimitry Andric Size *= C->getZExtValue(); 2063ca95b02SDimitry Andric } 2073ca95b02SDimitry Andric return Size; 2083ca95b02SDimitry Andric } 2093ca95b02SDimitry Andric 2103ca95b02SDimitry Andric bool SafeStack::IsAccessSafe(Value *Addr, uint64_t AccessSize, 2113ca95b02SDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize) { 2123ca95b02SDimitry Andric AllocaOffsetRewriter Rewriter(*SE, AllocaPtr); 2133ca95b02SDimitry Andric const SCEV *Expr = Rewriter.visit(SE->getSCEV(Addr)); 2143ca95b02SDimitry Andric 2153ca95b02SDimitry Andric uint64_t BitWidth = SE->getTypeSizeInBits(Expr->getType()); 2163ca95b02SDimitry Andric ConstantRange AccessStartRange = SE->getUnsignedRange(Expr); 2173ca95b02SDimitry Andric ConstantRange SizeRange = 2183ca95b02SDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AccessSize)); 2193ca95b02SDimitry Andric ConstantRange AccessRange = AccessStartRange.add(SizeRange); 2203ca95b02SDimitry Andric ConstantRange AllocaRange = 2213ca95b02SDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AllocaSize)); 2223ca95b02SDimitry Andric bool Safe = AllocaRange.contains(AccessRange); 2233ca95b02SDimitry Andric 2243ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] " 2253ca95b02SDimitry Andric << (isa<AllocaInst>(AllocaPtr) ? "Alloca " : "ByValArgument ") 2263ca95b02SDimitry Andric << *AllocaPtr << "\n" 2273ca95b02SDimitry Andric << " Access " << *Addr << "\n" 2283ca95b02SDimitry Andric << " SCEV " << *Expr 2293ca95b02SDimitry Andric << " U: " << SE->getUnsignedRange(Expr) 2303ca95b02SDimitry Andric << ", S: " << SE->getSignedRange(Expr) << "\n" 2313ca95b02SDimitry Andric << " Range " << AccessRange << "\n" 2323ca95b02SDimitry Andric << " AllocaRange " << AllocaRange << "\n" 2333ca95b02SDimitry Andric << " " << (Safe ? "safe" : "unsafe") << "\n"); 2343ca95b02SDimitry Andric 2353ca95b02SDimitry Andric return Safe; 2363ca95b02SDimitry Andric } 2373ca95b02SDimitry Andric 2383ca95b02SDimitry Andric bool SafeStack::IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, 2393ca95b02SDimitry Andric const Value *AllocaPtr, 2403ca95b02SDimitry Andric uint64_t AllocaSize) { 2413ca95b02SDimitry Andric // All MemIntrinsics have destination address in Arg0 and size in Arg2. 2423ca95b02SDimitry Andric if (MI->getRawDest() != U) return true; 2433ca95b02SDimitry Andric const auto *Len = dyn_cast<ConstantInt>(MI->getLength()); 2443ca95b02SDimitry Andric // Non-constant size => unsafe. FIXME: try SCEV getRange. 2453ca95b02SDimitry Andric if (!Len) return false; 2463ca95b02SDimitry Andric return IsAccessSafe(U, Len->getZExtValue(), AllocaPtr, AllocaSize); 2473ca95b02SDimitry Andric } 2483ca95b02SDimitry Andric 2493ca95b02SDimitry Andric /// Check whether a given allocation must be put on the safe 2503ca95b02SDimitry Andric /// stack or not. The function analyzes all uses of AI and checks whether it is 2513ca95b02SDimitry Andric /// only accessed in a memory safe way (as decided statically). 2523ca95b02SDimitry Andric bool SafeStack::IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize) { 2533ca95b02SDimitry Andric // Go through all uses of this alloca and check whether all accesses to the 2543ca95b02SDimitry Andric // allocated object are statically known to be memory safe and, hence, the 2553ca95b02SDimitry Andric // object can be placed on the safe stack. 2563ca95b02SDimitry Andric SmallPtrSet<const Value *, 16> Visited; 2573ca95b02SDimitry Andric SmallVector<const Value *, 8> WorkList; 2583ca95b02SDimitry Andric WorkList.push_back(AllocaPtr); 2593ca95b02SDimitry Andric 2603ca95b02SDimitry Andric // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc. 2613ca95b02SDimitry Andric while (!WorkList.empty()) { 2623ca95b02SDimitry Andric const Value *V = WorkList.pop_back_val(); 2633ca95b02SDimitry Andric for (const Use &UI : V->uses()) { 2643ca95b02SDimitry Andric auto I = cast<const Instruction>(UI.getUser()); 2653ca95b02SDimitry Andric assert(V == UI.get()); 2663ca95b02SDimitry Andric 2673ca95b02SDimitry Andric switch (I->getOpcode()) { 2683ca95b02SDimitry Andric case Instruction::Load: { 2693ca95b02SDimitry Andric if (!IsAccessSafe(UI, DL->getTypeStoreSize(I->getType()), AllocaPtr, 2703ca95b02SDimitry Andric AllocaSize)) 2713ca95b02SDimitry Andric return false; 2723ca95b02SDimitry Andric break; 2733ca95b02SDimitry Andric } 2743ca95b02SDimitry Andric case Instruction::VAArg: 2753ca95b02SDimitry Andric // "va-arg" from a pointer is safe. 2763ca95b02SDimitry Andric break; 2773ca95b02SDimitry Andric case Instruction::Store: { 2783ca95b02SDimitry Andric if (V == I->getOperand(0)) { 2793ca95b02SDimitry Andric // Stored the pointer - conservatively assume it may be unsafe. 2803ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr 2813ca95b02SDimitry Andric << "\n store of address: " << *I << "\n"); 2823ca95b02SDimitry Andric return false; 2833ca95b02SDimitry Andric } 2843ca95b02SDimitry Andric 2853ca95b02SDimitry Andric if (!IsAccessSafe(UI, DL->getTypeStoreSize(I->getOperand(0)->getType()), 2863ca95b02SDimitry Andric AllocaPtr, AllocaSize)) 2873ca95b02SDimitry Andric return false; 2883ca95b02SDimitry Andric break; 2893ca95b02SDimitry Andric } 2903ca95b02SDimitry Andric case Instruction::Ret: { 2913ca95b02SDimitry Andric // Information leak. 2923ca95b02SDimitry Andric return false; 2933ca95b02SDimitry Andric } 2943ca95b02SDimitry Andric 2953ca95b02SDimitry Andric case Instruction::Call: 2963ca95b02SDimitry Andric case Instruction::Invoke: { 2973ca95b02SDimitry Andric ImmutableCallSite CS(I); 2983ca95b02SDimitry Andric 2993ca95b02SDimitry Andric if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { 3003ca95b02SDimitry Andric if (II->getIntrinsicID() == Intrinsic::lifetime_start || 3013ca95b02SDimitry Andric II->getIntrinsicID() == Intrinsic::lifetime_end) 3023ca95b02SDimitry Andric continue; 3033ca95b02SDimitry Andric } 3043ca95b02SDimitry Andric 3053ca95b02SDimitry Andric if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { 3063ca95b02SDimitry Andric if (!IsMemIntrinsicSafe(MI, UI, AllocaPtr, AllocaSize)) { 3073ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr 3083ca95b02SDimitry Andric << "\n unsafe memintrinsic: " << *I 3093ca95b02SDimitry Andric << "\n"); 3103ca95b02SDimitry Andric return false; 3113ca95b02SDimitry Andric } 3123ca95b02SDimitry Andric continue; 3133ca95b02SDimitry Andric } 3143ca95b02SDimitry Andric 3153ca95b02SDimitry Andric // LLVM 'nocapture' attribute is only set for arguments whose address 3163ca95b02SDimitry Andric // is not stored, passed around, or used in any other non-trivial way. 3173ca95b02SDimitry Andric // We assume that passing a pointer to an object as a 'nocapture 3183ca95b02SDimitry Andric // readnone' argument is safe. 3193ca95b02SDimitry Andric // FIXME: a more precise solution would require an interprocedural 3203ca95b02SDimitry Andric // analysis here, which would look at all uses of an argument inside 3213ca95b02SDimitry Andric // the function being called. 3223ca95b02SDimitry Andric ImmutableCallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end(); 3233ca95b02SDimitry Andric for (ImmutableCallSite::arg_iterator A = B; A != E; ++A) 3243ca95b02SDimitry Andric if (A->get() == V) 3253ca95b02SDimitry Andric if (!(CS.doesNotCapture(A - B) && (CS.doesNotAccessMemory(A - B) || 3263ca95b02SDimitry Andric CS.doesNotAccessMemory()))) { 3273ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr 3283ca95b02SDimitry Andric << "\n unsafe call: " << *I << "\n"); 3293ca95b02SDimitry Andric return false; 3303ca95b02SDimitry Andric } 3313ca95b02SDimitry Andric continue; 3323ca95b02SDimitry Andric } 3333ca95b02SDimitry Andric 3343ca95b02SDimitry Andric default: 3353ca95b02SDimitry Andric if (Visited.insert(I).second) 3363ca95b02SDimitry Andric WorkList.push_back(cast<const Instruction>(I)); 3373ca95b02SDimitry Andric } 3383ca95b02SDimitry Andric } 3393ca95b02SDimitry Andric } 3403ca95b02SDimitry Andric 3413ca95b02SDimitry Andric // All uses of the alloca are safe, we can place it on the safe stack. 3423ca95b02SDimitry Andric return true; 3433ca95b02SDimitry Andric } 3443ca95b02SDimitry Andric 3453ca95b02SDimitry Andric Value *SafeStack::getStackGuard(IRBuilder<> &IRB, Function &F) { 346d88c1a5aSDimitry Andric Value *StackGuardVar = TL->getIRStackGuard(IRB); 3473ca95b02SDimitry Andric if (!StackGuardVar) 3483ca95b02SDimitry Andric StackGuardVar = 3493ca95b02SDimitry Andric F.getParent()->getOrInsertGlobal("__stack_chk_guard", StackPtrTy); 3503ca95b02SDimitry Andric return IRB.CreateLoad(StackGuardVar, "StackGuard"); 3513ca95b02SDimitry Andric } 3523ca95b02SDimitry Andric 3533ca95b02SDimitry Andric void SafeStack::findInsts(Function &F, 3543ca95b02SDimitry Andric SmallVectorImpl<AllocaInst *> &StaticAllocas, 3553ca95b02SDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas, 3563ca95b02SDimitry Andric SmallVectorImpl<Argument *> &ByValArguments, 3573ca95b02SDimitry Andric SmallVectorImpl<ReturnInst *> &Returns, 3583ca95b02SDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints) { 3593ca95b02SDimitry Andric for (Instruction &I : instructions(&F)) { 3603ca95b02SDimitry Andric if (auto AI = dyn_cast<AllocaInst>(&I)) { 3613ca95b02SDimitry Andric ++NumAllocas; 3623ca95b02SDimitry Andric 3633ca95b02SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 3643ca95b02SDimitry Andric if (IsSafeStackAlloca(AI, Size)) 3653ca95b02SDimitry Andric continue; 3663ca95b02SDimitry Andric 3673ca95b02SDimitry Andric if (AI->isStaticAlloca()) { 3683ca95b02SDimitry Andric ++NumUnsafeStaticAllocas; 3693ca95b02SDimitry Andric StaticAllocas.push_back(AI); 3703ca95b02SDimitry Andric } else { 3713ca95b02SDimitry Andric ++NumUnsafeDynamicAllocas; 3723ca95b02SDimitry Andric DynamicAllocas.push_back(AI); 3733ca95b02SDimitry Andric } 3743ca95b02SDimitry Andric } else if (auto RI = dyn_cast<ReturnInst>(&I)) { 3753ca95b02SDimitry Andric Returns.push_back(RI); 3763ca95b02SDimitry Andric } else if (auto CI = dyn_cast<CallInst>(&I)) { 3773ca95b02SDimitry Andric // setjmps require stack restore. 3783ca95b02SDimitry Andric if (CI->getCalledFunction() && CI->canReturnTwice()) 3793ca95b02SDimitry Andric StackRestorePoints.push_back(CI); 3803ca95b02SDimitry Andric } else if (auto LP = dyn_cast<LandingPadInst>(&I)) { 3813ca95b02SDimitry Andric // Exception landing pads require stack restore. 3823ca95b02SDimitry Andric StackRestorePoints.push_back(LP); 3833ca95b02SDimitry Andric } else if (auto II = dyn_cast<IntrinsicInst>(&I)) { 3843ca95b02SDimitry Andric if (II->getIntrinsicID() == Intrinsic::gcroot) 3853ca95b02SDimitry Andric llvm::report_fatal_error( 3863ca95b02SDimitry Andric "gcroot intrinsic not compatible with safestack attribute"); 3873ca95b02SDimitry Andric } 3883ca95b02SDimitry Andric } 3893ca95b02SDimitry Andric for (Argument &Arg : F.args()) { 3903ca95b02SDimitry Andric if (!Arg.hasByValAttr()) 3913ca95b02SDimitry Andric continue; 3923ca95b02SDimitry Andric uint64_t Size = 3933ca95b02SDimitry Andric DL->getTypeStoreSize(Arg.getType()->getPointerElementType()); 3943ca95b02SDimitry Andric if (IsSafeStackAlloca(&Arg, Size)) 3953ca95b02SDimitry Andric continue; 3963ca95b02SDimitry Andric 3973ca95b02SDimitry Andric ++NumUnsafeByValArguments; 3983ca95b02SDimitry Andric ByValArguments.push_back(&Arg); 3993ca95b02SDimitry Andric } 4003ca95b02SDimitry Andric } 4013ca95b02SDimitry Andric 4023ca95b02SDimitry Andric AllocaInst * 4033ca95b02SDimitry Andric SafeStack::createStackRestorePoints(IRBuilder<> &IRB, Function &F, 4043ca95b02SDimitry Andric ArrayRef<Instruction *> StackRestorePoints, 4053ca95b02SDimitry Andric Value *StaticTop, bool NeedDynamicTop) { 4063ca95b02SDimitry Andric assert(StaticTop && "The stack top isn't set."); 4073ca95b02SDimitry Andric 4083ca95b02SDimitry Andric if (StackRestorePoints.empty()) 4093ca95b02SDimitry Andric return nullptr; 4103ca95b02SDimitry Andric 4113ca95b02SDimitry Andric // We need the current value of the shadow stack pointer to restore 4123ca95b02SDimitry Andric // after longjmp or exception catching. 4133ca95b02SDimitry Andric 4143ca95b02SDimitry Andric // FIXME: On some platforms this could be handled by the longjmp/exception 4153ca95b02SDimitry Andric // runtime itself. 4163ca95b02SDimitry Andric 4173ca95b02SDimitry Andric AllocaInst *DynamicTop = nullptr; 4183ca95b02SDimitry Andric if (NeedDynamicTop) { 4193ca95b02SDimitry Andric // If we also have dynamic alloca's, the stack pointer value changes 4203ca95b02SDimitry Andric // throughout the function. For now we store it in an alloca. 4213ca95b02SDimitry Andric DynamicTop = IRB.CreateAlloca(StackPtrTy, /*ArraySize=*/nullptr, 4223ca95b02SDimitry Andric "unsafe_stack_dynamic_ptr"); 4233ca95b02SDimitry Andric IRB.CreateStore(StaticTop, DynamicTop); 4243ca95b02SDimitry Andric } 4253ca95b02SDimitry Andric 4263ca95b02SDimitry Andric // Restore current stack pointer after longjmp/exception catch. 4273ca95b02SDimitry Andric for (Instruction *I : StackRestorePoints) { 4283ca95b02SDimitry Andric ++NumUnsafeStackRestorePoints; 4293ca95b02SDimitry Andric 4303ca95b02SDimitry Andric IRB.SetInsertPoint(I->getNextNode()); 4313ca95b02SDimitry Andric Value *CurrentTop = DynamicTop ? IRB.CreateLoad(DynamicTop) : StaticTop; 4323ca95b02SDimitry Andric IRB.CreateStore(CurrentTop, UnsafeStackPtr); 4333ca95b02SDimitry Andric } 4343ca95b02SDimitry Andric 4353ca95b02SDimitry Andric return DynamicTop; 4363ca95b02SDimitry Andric } 4373ca95b02SDimitry Andric 4383ca95b02SDimitry Andric void SafeStack::checkStackGuard(IRBuilder<> &IRB, Function &F, ReturnInst &RI, 4393ca95b02SDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard) { 4403ca95b02SDimitry Andric Value *V = IRB.CreateLoad(StackGuardSlot); 4413ca95b02SDimitry Andric Value *Cmp = IRB.CreateICmpNE(StackGuard, V); 4423ca95b02SDimitry Andric 4433ca95b02SDimitry Andric auto SuccessProb = BranchProbabilityInfo::getBranchProbStackProtector(true); 4443ca95b02SDimitry Andric auto FailureProb = BranchProbabilityInfo::getBranchProbStackProtector(false); 4453ca95b02SDimitry Andric MDNode *Weights = MDBuilder(F.getContext()) 4463ca95b02SDimitry Andric .createBranchWeights(SuccessProb.getNumerator(), 4473ca95b02SDimitry Andric FailureProb.getNumerator()); 4483ca95b02SDimitry Andric Instruction *CheckTerm = 4493ca95b02SDimitry Andric SplitBlockAndInsertIfThen(Cmp, &RI, 4503ca95b02SDimitry Andric /* Unreachable */ true, Weights); 4513ca95b02SDimitry Andric IRBuilder<> IRBFail(CheckTerm); 4523ca95b02SDimitry Andric // FIXME: respect -fsanitize-trap / -ftrap-function here? 4533ca95b02SDimitry Andric Constant *StackChkFail = F.getParent()->getOrInsertFunction( 4547a7e6055SDimitry Andric "__stack_chk_fail", IRB.getVoidTy()); 4553ca95b02SDimitry Andric IRBFail.CreateCall(StackChkFail, {}); 4563ca95b02SDimitry Andric } 4573ca95b02SDimitry Andric 4583ca95b02SDimitry Andric /// We explicitly compute and set the unsafe stack layout for all unsafe 4593ca95b02SDimitry Andric /// static alloca instructions. We save the unsafe "base pointer" in the 4603ca95b02SDimitry Andric /// prologue into a local variable and restore it in the epilogue. 4613ca95b02SDimitry Andric Value *SafeStack::moveStaticAllocasToUnsafeStack( 4623ca95b02SDimitry Andric IRBuilder<> &IRB, Function &F, ArrayRef<AllocaInst *> StaticAllocas, 4633ca95b02SDimitry Andric ArrayRef<Argument *> ByValArguments, ArrayRef<ReturnInst *> Returns, 4643ca95b02SDimitry Andric Instruction *BasePointer, AllocaInst *StackGuardSlot) { 4653ca95b02SDimitry Andric if (StaticAllocas.empty() && ByValArguments.empty()) 4663ca95b02SDimitry Andric return BasePointer; 4673ca95b02SDimitry Andric 4683ca95b02SDimitry Andric DIBuilder DIB(*F.getParent()); 4693ca95b02SDimitry Andric 4703ca95b02SDimitry Andric StackColoring SSC(F, StaticAllocas); 4713ca95b02SDimitry Andric SSC.run(); 4723ca95b02SDimitry Andric SSC.removeAllMarkers(); 4733ca95b02SDimitry Andric 4743ca95b02SDimitry Andric // Unsafe stack always grows down. 4753ca95b02SDimitry Andric StackLayout SSL(StackAlignment); 4763ca95b02SDimitry Andric if (StackGuardSlot) { 4773ca95b02SDimitry Andric Type *Ty = StackGuardSlot->getAllocatedType(); 4783ca95b02SDimitry Andric unsigned Align = 4793ca95b02SDimitry Andric std::max(DL->getPrefTypeAlignment(Ty), StackGuardSlot->getAlignment()); 4803ca95b02SDimitry Andric SSL.addObject(StackGuardSlot, getStaticAllocaAllocationSize(StackGuardSlot), 4816c4bc1bdSDimitry Andric Align, SSC.getFullLiveRange()); 4823ca95b02SDimitry Andric } 4833ca95b02SDimitry Andric 4843ca95b02SDimitry Andric for (Argument *Arg : ByValArguments) { 4853ca95b02SDimitry Andric Type *Ty = Arg->getType()->getPointerElementType(); 4863ca95b02SDimitry Andric uint64_t Size = DL->getTypeStoreSize(Ty); 4873ca95b02SDimitry Andric if (Size == 0) 4883ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 4893ca95b02SDimitry Andric 4903ca95b02SDimitry Andric // Ensure the object is properly aligned. 4913ca95b02SDimitry Andric unsigned Align = std::max((unsigned)DL->getPrefTypeAlignment(Ty), 4923ca95b02SDimitry Andric Arg->getParamAlignment()); 4933ca95b02SDimitry Andric SSL.addObject(Arg, Size, Align, SSC.getFullLiveRange()); 4943ca95b02SDimitry Andric } 4953ca95b02SDimitry Andric 4963ca95b02SDimitry Andric for (AllocaInst *AI : StaticAllocas) { 4973ca95b02SDimitry Andric Type *Ty = AI->getAllocatedType(); 4983ca95b02SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 4993ca95b02SDimitry Andric if (Size == 0) 5003ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5013ca95b02SDimitry Andric 5023ca95b02SDimitry Andric // Ensure the object is properly aligned. 5033ca95b02SDimitry Andric unsigned Align = 5043ca95b02SDimitry Andric std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI->getAlignment()); 5053ca95b02SDimitry Andric 5063ca95b02SDimitry Andric SSL.addObject(AI, Size, Align, SSC.getLiveRange(AI)); 5073ca95b02SDimitry Andric } 5083ca95b02SDimitry Andric 5093ca95b02SDimitry Andric SSL.computeLayout(); 5103ca95b02SDimitry Andric unsigned FrameAlignment = SSL.getFrameAlignment(); 5113ca95b02SDimitry Andric 5123ca95b02SDimitry Andric // FIXME: tell SSL that we start at a less-then-MaxAlignment aligned location 5133ca95b02SDimitry Andric // (AlignmentSkew). 5143ca95b02SDimitry Andric if (FrameAlignment > StackAlignment) { 5153ca95b02SDimitry Andric // Re-align the base pointer according to the max requested alignment. 5163ca95b02SDimitry Andric assert(isPowerOf2_32(FrameAlignment)); 5173ca95b02SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 5183ca95b02SDimitry Andric BasePointer = cast<Instruction>(IRB.CreateIntToPtr( 5193ca95b02SDimitry Andric IRB.CreateAnd(IRB.CreatePtrToInt(BasePointer, IntPtrTy), 5203ca95b02SDimitry Andric ConstantInt::get(IntPtrTy, ~uint64_t(FrameAlignment - 1))), 5213ca95b02SDimitry Andric StackPtrTy)); 5223ca95b02SDimitry Andric } 5233ca95b02SDimitry Andric 5243ca95b02SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 5253ca95b02SDimitry Andric 5263ca95b02SDimitry Andric if (StackGuardSlot) { 5273ca95b02SDimitry Andric unsigned Offset = SSL.getObjectOffset(StackGuardSlot); 5283ca95b02SDimitry Andric Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* 5293ca95b02SDimitry Andric ConstantInt::get(Int32Ty, -Offset)); 5303ca95b02SDimitry Andric Value *NewAI = 5313ca95b02SDimitry Andric IRB.CreateBitCast(Off, StackGuardSlot->getType(), "StackGuardSlot"); 5323ca95b02SDimitry Andric 5333ca95b02SDimitry Andric // Replace alloc with the new location. 5343ca95b02SDimitry Andric StackGuardSlot->replaceAllUsesWith(NewAI); 5353ca95b02SDimitry Andric StackGuardSlot->eraseFromParent(); 5363ca95b02SDimitry Andric } 5373ca95b02SDimitry Andric 5383ca95b02SDimitry Andric for (Argument *Arg : ByValArguments) { 5393ca95b02SDimitry Andric unsigned Offset = SSL.getObjectOffset(Arg); 5403ca95b02SDimitry Andric Type *Ty = Arg->getType()->getPointerElementType(); 5413ca95b02SDimitry Andric 5423ca95b02SDimitry Andric uint64_t Size = DL->getTypeStoreSize(Ty); 5433ca95b02SDimitry Andric if (Size == 0) 5443ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5453ca95b02SDimitry Andric 5463ca95b02SDimitry Andric Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* 5473ca95b02SDimitry Andric ConstantInt::get(Int32Ty, -Offset)); 5483ca95b02SDimitry Andric Value *NewArg = IRB.CreateBitCast(Off, Arg->getType(), 5493ca95b02SDimitry Andric Arg->getName() + ".unsafe-byval"); 5503ca95b02SDimitry Andric 5513ca95b02SDimitry Andric // Replace alloc with the new location. 5523ca95b02SDimitry Andric replaceDbgDeclare(Arg, BasePointer, BasePointer->getNextNode(), DIB, 5536bc11b14SDimitry Andric /*Deref=*/false, -Offset); 5543ca95b02SDimitry Andric Arg->replaceAllUsesWith(NewArg); 5553ca95b02SDimitry Andric IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode()); 5563ca95b02SDimitry Andric IRB.CreateMemCpy(Off, Arg, Size, Arg->getParamAlignment()); 5573ca95b02SDimitry Andric } 5583ca95b02SDimitry Andric 5593ca95b02SDimitry Andric // Allocate space for every unsafe static AllocaInst on the unsafe stack. 5603ca95b02SDimitry Andric for (AllocaInst *AI : StaticAllocas) { 5613ca95b02SDimitry Andric IRB.SetInsertPoint(AI); 5623ca95b02SDimitry Andric unsigned Offset = SSL.getObjectOffset(AI); 5633ca95b02SDimitry Andric 5643ca95b02SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 5653ca95b02SDimitry Andric if (Size == 0) 5663ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5673ca95b02SDimitry Andric 5686bc11b14SDimitry Andric replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/false, -Offset); 5693ca95b02SDimitry Andric replaceDbgValueForAlloca(AI, BasePointer, DIB, -Offset); 5703ca95b02SDimitry Andric 5713ca95b02SDimitry Andric // Replace uses of the alloca with the new location. 5723ca95b02SDimitry Andric // Insert address calculation close to each use to work around PR27844. 5733ca95b02SDimitry Andric std::string Name = std::string(AI->getName()) + ".unsafe"; 5743ca95b02SDimitry Andric while (!AI->use_empty()) { 5753ca95b02SDimitry Andric Use &U = *AI->use_begin(); 5763ca95b02SDimitry Andric Instruction *User = cast<Instruction>(U.getUser()); 5773ca95b02SDimitry Andric 5783ca95b02SDimitry Andric Instruction *InsertBefore; 5793ca95b02SDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User)) 5803ca95b02SDimitry Andric InsertBefore = PHI->getIncomingBlock(U)->getTerminator(); 5813ca95b02SDimitry Andric else 5823ca95b02SDimitry Andric InsertBefore = User; 5833ca95b02SDimitry Andric 5843ca95b02SDimitry Andric IRBuilder<> IRBUser(InsertBefore); 5853ca95b02SDimitry Andric Value *Off = IRBUser.CreateGEP(BasePointer, // BasePointer is i8* 5863ca95b02SDimitry Andric ConstantInt::get(Int32Ty, -Offset)); 5873ca95b02SDimitry Andric Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name); 5883ca95b02SDimitry Andric 5893ca95b02SDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User)) { 5903ca95b02SDimitry Andric // PHI nodes may have multiple incoming edges from the same BB (why??), 5913ca95b02SDimitry Andric // all must be updated at once with the same incoming value. 5923ca95b02SDimitry Andric auto *BB = PHI->getIncomingBlock(U); 5933ca95b02SDimitry Andric for (unsigned I = 0; I < PHI->getNumIncomingValues(); ++I) 5943ca95b02SDimitry Andric if (PHI->getIncomingBlock(I) == BB) 5953ca95b02SDimitry Andric PHI->setIncomingValue(I, Replacement); 5963ca95b02SDimitry Andric } else { 5973ca95b02SDimitry Andric U.set(Replacement); 5983ca95b02SDimitry Andric } 5993ca95b02SDimitry Andric } 6003ca95b02SDimitry Andric 6013ca95b02SDimitry Andric AI->eraseFromParent(); 6023ca95b02SDimitry Andric } 6033ca95b02SDimitry Andric 6043ca95b02SDimitry Andric // Re-align BasePointer so that our callees would see it aligned as 6053ca95b02SDimitry Andric // expected. 6063ca95b02SDimitry Andric // FIXME: no need to update BasePointer in leaf functions. 6073ca95b02SDimitry Andric unsigned FrameSize = alignTo(SSL.getFrameSize(), StackAlignment); 6083ca95b02SDimitry Andric 6093ca95b02SDimitry Andric // Update shadow stack pointer in the function epilogue. 6103ca95b02SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 6113ca95b02SDimitry Andric 6123ca95b02SDimitry Andric Value *StaticTop = 6133ca95b02SDimitry Andric IRB.CreateGEP(BasePointer, ConstantInt::get(Int32Ty, -FrameSize), 6143ca95b02SDimitry Andric "unsafe_stack_static_top"); 6153ca95b02SDimitry Andric IRB.CreateStore(StaticTop, UnsafeStackPtr); 6163ca95b02SDimitry Andric return StaticTop; 6173ca95b02SDimitry Andric } 6183ca95b02SDimitry Andric 6193ca95b02SDimitry Andric void SafeStack::moveDynamicAllocasToUnsafeStack( 6203ca95b02SDimitry Andric Function &F, Value *UnsafeStackPtr, AllocaInst *DynamicTop, 6213ca95b02SDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas) { 6223ca95b02SDimitry Andric DIBuilder DIB(*F.getParent()); 6233ca95b02SDimitry Andric 6243ca95b02SDimitry Andric for (AllocaInst *AI : DynamicAllocas) { 6253ca95b02SDimitry Andric IRBuilder<> IRB(AI); 6263ca95b02SDimitry Andric 6273ca95b02SDimitry Andric // Compute the new SP value (after AI). 6283ca95b02SDimitry Andric Value *ArraySize = AI->getArraySize(); 6293ca95b02SDimitry Andric if (ArraySize->getType() != IntPtrTy) 6303ca95b02SDimitry Andric ArraySize = IRB.CreateIntCast(ArraySize, IntPtrTy, false); 6313ca95b02SDimitry Andric 6323ca95b02SDimitry Andric Type *Ty = AI->getAllocatedType(); 6333ca95b02SDimitry Andric uint64_t TySize = DL->getTypeAllocSize(Ty); 6343ca95b02SDimitry Andric Value *Size = IRB.CreateMul(ArraySize, ConstantInt::get(IntPtrTy, TySize)); 6353ca95b02SDimitry Andric 6363ca95b02SDimitry Andric Value *SP = IRB.CreatePtrToInt(IRB.CreateLoad(UnsafeStackPtr), IntPtrTy); 6373ca95b02SDimitry Andric SP = IRB.CreateSub(SP, Size); 6383ca95b02SDimitry Andric 6393ca95b02SDimitry Andric // Align the SP value to satisfy the AllocaInst, type and stack alignments. 6403ca95b02SDimitry Andric unsigned Align = std::max( 6413ca95b02SDimitry Andric std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI->getAlignment()), 6423ca95b02SDimitry Andric (unsigned)StackAlignment); 6433ca95b02SDimitry Andric 6443ca95b02SDimitry Andric assert(isPowerOf2_32(Align)); 6453ca95b02SDimitry Andric Value *NewTop = IRB.CreateIntToPtr( 6463ca95b02SDimitry Andric IRB.CreateAnd(SP, ConstantInt::get(IntPtrTy, ~uint64_t(Align - 1))), 6473ca95b02SDimitry Andric StackPtrTy); 6483ca95b02SDimitry Andric 6493ca95b02SDimitry Andric // Save the stack pointer. 6503ca95b02SDimitry Andric IRB.CreateStore(NewTop, UnsafeStackPtr); 6513ca95b02SDimitry Andric if (DynamicTop) 6523ca95b02SDimitry Andric IRB.CreateStore(NewTop, DynamicTop); 6533ca95b02SDimitry Andric 6543ca95b02SDimitry Andric Value *NewAI = IRB.CreatePointerCast(NewTop, AI->getType()); 6553ca95b02SDimitry Andric if (AI->hasName() && isa<Instruction>(NewAI)) 6563ca95b02SDimitry Andric NewAI->takeName(AI); 6573ca95b02SDimitry Andric 6586bc11b14SDimitry Andric replaceDbgDeclareForAlloca(AI, NewAI, DIB, /*Deref=*/false); 6593ca95b02SDimitry Andric AI->replaceAllUsesWith(NewAI); 6603ca95b02SDimitry Andric AI->eraseFromParent(); 6613ca95b02SDimitry Andric } 6623ca95b02SDimitry Andric 6633ca95b02SDimitry Andric if (!DynamicAllocas.empty()) { 6643ca95b02SDimitry Andric // Now go through the instructions again, replacing stacksave/stackrestore. 6653ca95b02SDimitry Andric for (inst_iterator It = inst_begin(&F), Ie = inst_end(&F); It != Ie;) { 6663ca95b02SDimitry Andric Instruction *I = &*(It++); 6673ca95b02SDimitry Andric auto II = dyn_cast<IntrinsicInst>(I); 6683ca95b02SDimitry Andric if (!II) 6693ca95b02SDimitry Andric continue; 6703ca95b02SDimitry Andric 6713ca95b02SDimitry Andric if (II->getIntrinsicID() == Intrinsic::stacksave) { 6723ca95b02SDimitry Andric IRBuilder<> IRB(II); 6733ca95b02SDimitry Andric Instruction *LI = IRB.CreateLoad(UnsafeStackPtr); 6743ca95b02SDimitry Andric LI->takeName(II); 6753ca95b02SDimitry Andric II->replaceAllUsesWith(LI); 6763ca95b02SDimitry Andric II->eraseFromParent(); 6773ca95b02SDimitry Andric } else if (II->getIntrinsicID() == Intrinsic::stackrestore) { 6783ca95b02SDimitry Andric IRBuilder<> IRB(II); 6793ca95b02SDimitry Andric Instruction *SI = IRB.CreateStore(II->getArgOperand(0), UnsafeStackPtr); 6803ca95b02SDimitry Andric SI->takeName(II); 6813ca95b02SDimitry Andric assert(II->use_empty()); 6823ca95b02SDimitry Andric II->eraseFromParent(); 6833ca95b02SDimitry Andric } 6843ca95b02SDimitry Andric } 6853ca95b02SDimitry Andric } 6863ca95b02SDimitry Andric } 6873ca95b02SDimitry Andric 6883ca95b02SDimitry Andric bool SafeStack::runOnFunction(Function &F) { 6893ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n"); 6903ca95b02SDimitry Andric 6913ca95b02SDimitry Andric if (!F.hasFnAttribute(Attribute::SafeStack)) { 6923ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] safestack is not requested" 6933ca95b02SDimitry Andric " for this function\n"); 6943ca95b02SDimitry Andric return false; 6953ca95b02SDimitry Andric } 6963ca95b02SDimitry Andric 6973ca95b02SDimitry Andric if (F.isDeclaration()) { 6983ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] function definition" 6993ca95b02SDimitry Andric " is not available\n"); 7003ca95b02SDimitry Andric return false; 7013ca95b02SDimitry Andric } 7023ca95b02SDimitry Andric 703d88c1a5aSDimitry Andric if (!TM) 704d88c1a5aSDimitry Andric report_fatal_error("Target machine is required"); 705d88c1a5aSDimitry Andric TL = TM->getSubtargetImpl(F)->getTargetLowering(); 7063ca95b02SDimitry Andric SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 7073ca95b02SDimitry Andric 7083ca95b02SDimitry Andric ++NumFunctions; 7093ca95b02SDimitry Andric 7103ca95b02SDimitry Andric SmallVector<AllocaInst *, 16> StaticAllocas; 7113ca95b02SDimitry Andric SmallVector<AllocaInst *, 4> DynamicAllocas; 7123ca95b02SDimitry Andric SmallVector<Argument *, 4> ByValArguments; 7133ca95b02SDimitry Andric SmallVector<ReturnInst *, 4> Returns; 7143ca95b02SDimitry Andric 7153ca95b02SDimitry Andric // Collect all points where stack gets unwound and needs to be restored 7163ca95b02SDimitry Andric // This is only necessary because the runtime (setjmp and unwind code) is 717d88c1a5aSDimitry Andric // not aware of the unsafe stack and won't unwind/restore it properly. 7183ca95b02SDimitry Andric // To work around this problem without changing the runtime, we insert 7193ca95b02SDimitry Andric // instrumentation to restore the unsafe stack pointer when necessary. 7203ca95b02SDimitry Andric SmallVector<Instruction *, 4> StackRestorePoints; 7213ca95b02SDimitry Andric 7223ca95b02SDimitry Andric // Find all static and dynamic alloca instructions that must be moved to the 7233ca95b02SDimitry Andric // unsafe stack, all return instructions and stack restore points. 7243ca95b02SDimitry Andric findInsts(F, StaticAllocas, DynamicAllocas, ByValArguments, Returns, 7253ca95b02SDimitry Andric StackRestorePoints); 7263ca95b02SDimitry Andric 7273ca95b02SDimitry Andric if (StaticAllocas.empty() && DynamicAllocas.empty() && 7283ca95b02SDimitry Andric ByValArguments.empty() && StackRestorePoints.empty()) 7293ca95b02SDimitry Andric return false; // Nothing to do in this function. 7303ca95b02SDimitry Andric 7313ca95b02SDimitry Andric if (!StaticAllocas.empty() || !DynamicAllocas.empty() || 7323ca95b02SDimitry Andric !ByValArguments.empty()) 7333ca95b02SDimitry Andric ++NumUnsafeStackFunctions; // This function has the unsafe stack. 7343ca95b02SDimitry Andric 7353ca95b02SDimitry Andric if (!StackRestorePoints.empty()) 7363ca95b02SDimitry Andric ++NumUnsafeStackRestorePointsFunctions; 7373ca95b02SDimitry Andric 7383ca95b02SDimitry Andric IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt()); 739d88c1a5aSDimitry Andric UnsafeStackPtr = TL->getSafeStackPointerLocation(IRB); 7403ca95b02SDimitry Andric 7413ca95b02SDimitry Andric // Load the current stack pointer (we'll also use it as a base pointer). 7423ca95b02SDimitry Andric // FIXME: use a dedicated register for it ? 7433ca95b02SDimitry Andric Instruction *BasePointer = 7443ca95b02SDimitry Andric IRB.CreateLoad(UnsafeStackPtr, false, "unsafe_stack_ptr"); 7453ca95b02SDimitry Andric assert(BasePointer->getType() == StackPtrTy); 7463ca95b02SDimitry Andric 7473ca95b02SDimitry Andric AllocaInst *StackGuardSlot = nullptr; 7483ca95b02SDimitry Andric // FIXME: implement weaker forms of stack protector. 7493ca95b02SDimitry Andric if (F.hasFnAttribute(Attribute::StackProtect) || 7503ca95b02SDimitry Andric F.hasFnAttribute(Attribute::StackProtectStrong) || 7513ca95b02SDimitry Andric F.hasFnAttribute(Attribute::StackProtectReq)) { 7523ca95b02SDimitry Andric Value *StackGuard = getStackGuard(IRB, F); 7533ca95b02SDimitry Andric StackGuardSlot = IRB.CreateAlloca(StackPtrTy, nullptr); 7543ca95b02SDimitry Andric IRB.CreateStore(StackGuard, StackGuardSlot); 7553ca95b02SDimitry Andric 7563ca95b02SDimitry Andric for (ReturnInst *RI : Returns) { 7573ca95b02SDimitry Andric IRBuilder<> IRBRet(RI); 7583ca95b02SDimitry Andric checkStackGuard(IRBRet, F, *RI, StackGuardSlot, StackGuard); 7593ca95b02SDimitry Andric } 7603ca95b02SDimitry Andric } 7613ca95b02SDimitry Andric 7623ca95b02SDimitry Andric // The top of the unsafe stack after all unsafe static allocas are 7633ca95b02SDimitry Andric // allocated. 7643ca95b02SDimitry Andric Value *StaticTop = 7653ca95b02SDimitry Andric moveStaticAllocasToUnsafeStack(IRB, F, StaticAllocas, ByValArguments, 7663ca95b02SDimitry Andric Returns, BasePointer, StackGuardSlot); 7673ca95b02SDimitry Andric 7683ca95b02SDimitry Andric // Safe stack object that stores the current unsafe stack top. It is updated 7693ca95b02SDimitry Andric // as unsafe dynamic (non-constant-sized) allocas are allocated and freed. 7703ca95b02SDimitry Andric // This is only needed if we need to restore stack pointer after longjmp 7713ca95b02SDimitry Andric // or exceptions, and we have dynamic allocations. 7723ca95b02SDimitry Andric // FIXME: a better alternative might be to store the unsafe stack pointer 7733ca95b02SDimitry Andric // before setjmp / invoke instructions. 7743ca95b02SDimitry Andric AllocaInst *DynamicTop = createStackRestorePoints( 7753ca95b02SDimitry Andric IRB, F, StackRestorePoints, StaticTop, !DynamicAllocas.empty()); 7763ca95b02SDimitry Andric 7773ca95b02SDimitry Andric // Handle dynamic allocas. 7783ca95b02SDimitry Andric moveDynamicAllocasToUnsafeStack(F, UnsafeStackPtr, DynamicTop, 7793ca95b02SDimitry Andric DynamicAllocas); 7803ca95b02SDimitry Andric 7813ca95b02SDimitry Andric // Restore the unsafe stack pointer before each return. 7823ca95b02SDimitry Andric for (ReturnInst *RI : Returns) { 7833ca95b02SDimitry Andric IRB.SetInsertPoint(RI); 7843ca95b02SDimitry Andric IRB.CreateStore(BasePointer, UnsafeStackPtr); 7853ca95b02SDimitry Andric } 7863ca95b02SDimitry Andric 7873ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] safestack applied\n"); 7883ca95b02SDimitry Andric return true; 7893ca95b02SDimitry Andric } 7903ca95b02SDimitry Andric 7913ca95b02SDimitry Andric } // anonymous namespace 7923ca95b02SDimitry Andric 7933ca95b02SDimitry Andric char SafeStack::ID = 0; 7943ca95b02SDimitry Andric INITIALIZE_TM_PASS_BEGIN(SafeStack, "safe-stack", 7953ca95b02SDimitry Andric "Safe Stack instrumentation pass", false, false) 7963ca95b02SDimitry Andric INITIALIZE_TM_PASS_END(SafeStack, "safe-stack", 7973ca95b02SDimitry Andric "Safe Stack instrumentation pass", false, false) 7983ca95b02SDimitry Andric 7993ca95b02SDimitry Andric FunctionPass *llvm::createSafeStackPass(const llvm::TargetMachine *TM) { 8003ca95b02SDimitry Andric return new SafeStack(TM); 8013ca95b02SDimitry Andric } 802