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