12cab237bSDimitry 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" 202cab237bSDimitry Andric #include "llvm/ADT/APInt.h" 212cab237bSDimitry Andric #include "llvm/ADT/ArrayRef.h" 222cab237bSDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 232cab237bSDimitry Andric #include "llvm/ADT/SmallVector.h" 243ca95b02SDimitry Andric #include "llvm/ADT/Statistic.h" 255517e702SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 263ca95b02SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h" 272cab237bSDimitry Andric #include "llvm/Analysis/LoopInfo.h" 283ca95b02SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h" 293ca95b02SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h" 302cab237bSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 312cab237bSDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 32d8866befSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 332cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 342cab237bSDimitry Andric #include "llvm/IR/Argument.h" 352cab237bSDimitry Andric #include "llvm/IR/Attributes.h" 362cab237bSDimitry Andric #include "llvm/IR/CallSite.h" 372cab237bSDimitry Andric #include "llvm/IR/ConstantRange.h" 383ca95b02SDimitry Andric #include "llvm/IR/Constants.h" 393ca95b02SDimitry Andric #include "llvm/IR/DIBuilder.h" 403ca95b02SDimitry Andric #include "llvm/IR/DataLayout.h" 413ca95b02SDimitry Andric #include "llvm/IR/DerivedTypes.h" 422cab237bSDimitry Andric #include "llvm/IR/Dominators.h" 433ca95b02SDimitry Andric #include "llvm/IR/Function.h" 443ca95b02SDimitry Andric #include "llvm/IR/IRBuilder.h" 453ca95b02SDimitry Andric #include "llvm/IR/InstIterator.h" 462cab237bSDimitry Andric #include "llvm/IR/Instruction.h" 473ca95b02SDimitry Andric #include "llvm/IR/Instructions.h" 483ca95b02SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 493ca95b02SDimitry Andric #include "llvm/IR/Intrinsics.h" 503ca95b02SDimitry Andric #include "llvm/IR/MDBuilder.h" 513ca95b02SDimitry Andric #include "llvm/IR/Module.h" 522cab237bSDimitry Andric #include "llvm/IR/Type.h" 532cab237bSDimitry Andric #include "llvm/IR/Use.h" 542cab237bSDimitry Andric #include "llvm/IR/User.h" 552cab237bSDimitry Andric #include "llvm/IR/Value.h" 563ca95b02SDimitry Andric #include "llvm/Pass.h" 572cab237bSDimitry Andric #include "llvm/Support/Casting.h" 583ca95b02SDimitry Andric #include "llvm/Support/Debug.h" 592cab237bSDimitry Andric #include "llvm/Support/ErrorHandling.h" 603ca95b02SDimitry Andric #include "llvm/Support/MathExtras.h" 612cab237bSDimitry Andric #include "llvm/Support/raw_ostream.h" 622cab237bSDimitry Andric #include "llvm/Target/TargetMachine.h" 633ca95b02SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 643ca95b02SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 652cab237bSDimitry Andric #include <algorithm> 662cab237bSDimitry Andric #include <cassert> 672cab237bSDimitry Andric #include <cstdint> 682cab237bSDimitry Andric #include <string> 692cab237bSDimitry Andric #include <utility> 703ca95b02SDimitry Andric 713ca95b02SDimitry Andric using namespace llvm; 723ca95b02SDimitry Andric using namespace llvm::safestack; 733ca95b02SDimitry Andric 74302affcbSDimitry Andric #define DEBUG_TYPE "safe-stack" 753ca95b02SDimitry Andric 763ca95b02SDimitry Andric namespace llvm { 773ca95b02SDimitry Andric 783ca95b02SDimitry Andric STATISTIC(NumFunctions, "Total number of functions"); 793ca95b02SDimitry Andric STATISTIC(NumUnsafeStackFunctions, "Number of functions with unsafe stack"); 803ca95b02SDimitry Andric STATISTIC(NumUnsafeStackRestorePointsFunctions, 813ca95b02SDimitry Andric "Number of functions that use setjmp or exceptions"); 823ca95b02SDimitry Andric 833ca95b02SDimitry Andric STATISTIC(NumAllocas, "Total number of allocas"); 843ca95b02SDimitry Andric STATISTIC(NumUnsafeStaticAllocas, "Number of unsafe static allocas"); 853ca95b02SDimitry Andric STATISTIC(NumUnsafeDynamicAllocas, "Number of unsafe dynamic allocas"); 863ca95b02SDimitry Andric STATISTIC(NumUnsafeByValArguments, "Number of unsafe byval arguments"); 873ca95b02SDimitry Andric STATISTIC(NumUnsafeStackRestorePoints, "Number of setjmps and landingpads"); 883ca95b02SDimitry Andric 893ca95b02SDimitry Andric } // namespace llvm 903ca95b02SDimitry Andric 913ca95b02SDimitry Andric namespace { 923ca95b02SDimitry Andric 933ca95b02SDimitry Andric /// Rewrite an SCEV expression for a memory access address to an expression that 943ca95b02SDimitry Andric /// represents offset from the given alloca. 953ca95b02SDimitry Andric /// 963ca95b02SDimitry Andric /// The implementation simply replaces all mentions of the alloca with zero. 973ca95b02SDimitry Andric class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> { 983ca95b02SDimitry Andric const Value *AllocaPtr; 993ca95b02SDimitry Andric 1003ca95b02SDimitry Andric public: 1013ca95b02SDimitry Andric AllocaOffsetRewriter(ScalarEvolution &SE, const Value *AllocaPtr) 1023ca95b02SDimitry Andric : SCEVRewriteVisitor(SE), AllocaPtr(AllocaPtr) {} 1033ca95b02SDimitry Andric 1043ca95b02SDimitry Andric const SCEV *visitUnknown(const SCEVUnknown *Expr) { 1053ca95b02SDimitry Andric if (Expr->getValue() == AllocaPtr) 1063ca95b02SDimitry Andric return SE.getZero(Expr->getType()); 1073ca95b02SDimitry Andric return Expr; 1083ca95b02SDimitry Andric } 1093ca95b02SDimitry Andric }; 1103ca95b02SDimitry Andric 1113ca95b02SDimitry Andric /// The SafeStack pass splits the stack of each function into the safe 1123ca95b02SDimitry Andric /// stack, which is only accessed through memory safe dereferences (as 1133ca95b02SDimitry Andric /// determined statically), and the unsafe stack, which contains all 1143ca95b02SDimitry Andric /// local variables that are accessed in ways that we can't prove to 1153ca95b02SDimitry Andric /// be safe. 1165517e702SDimitry Andric class SafeStack { 1175517e702SDimitry Andric Function &F; 1185517e702SDimitry Andric const TargetLoweringBase &TL; 1195517e702SDimitry Andric const DataLayout &DL; 1205517e702SDimitry Andric ScalarEvolution &SE; 1213ca95b02SDimitry Andric 1223ca95b02SDimitry Andric Type *StackPtrTy; 1233ca95b02SDimitry Andric Type *IntPtrTy; 1243ca95b02SDimitry Andric Type *Int32Ty; 1253ca95b02SDimitry Andric Type *Int8Ty; 1263ca95b02SDimitry Andric 1273ca95b02SDimitry Andric Value *UnsafeStackPtr = nullptr; 1283ca95b02SDimitry Andric 1293ca95b02SDimitry Andric /// Unsafe stack alignment. Each stack frame must ensure that the stack is 1303ca95b02SDimitry Andric /// aligned to this value. We need to re-align the unsafe stack if the 1313ca95b02SDimitry Andric /// alignment of any object on the stack exceeds this value. 1323ca95b02SDimitry Andric /// 1333ca95b02SDimitry Andric /// 16 seems like a reasonable upper bound on the alignment of objects that we 1343ca95b02SDimitry Andric /// might expect to appear on the stack on most common targets. 1353ca95b02SDimitry Andric enum { StackAlignment = 16 }; 1363ca95b02SDimitry Andric 1373ca95b02SDimitry Andric /// \brief Return the value of the stack canary. 1383ca95b02SDimitry Andric Value *getStackGuard(IRBuilder<> &IRB, Function &F); 1393ca95b02SDimitry Andric 1403ca95b02SDimitry Andric /// \brief Load stack guard from the frame and check if it has changed. 1413ca95b02SDimitry Andric void checkStackGuard(IRBuilder<> &IRB, Function &F, ReturnInst &RI, 1423ca95b02SDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard); 1433ca95b02SDimitry Andric 1443ca95b02SDimitry Andric /// \brief Find all static allocas, dynamic allocas, return instructions and 1453ca95b02SDimitry Andric /// stack restore points (exception unwind blocks and setjmp calls) in the 1463ca95b02SDimitry Andric /// given function and append them to the respective vectors. 1473ca95b02SDimitry Andric void findInsts(Function &F, SmallVectorImpl<AllocaInst *> &StaticAllocas, 1483ca95b02SDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas, 1493ca95b02SDimitry Andric SmallVectorImpl<Argument *> &ByValArguments, 1503ca95b02SDimitry Andric SmallVectorImpl<ReturnInst *> &Returns, 1513ca95b02SDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints); 1523ca95b02SDimitry Andric 1533ca95b02SDimitry Andric /// \brief Calculate the allocation size of a given alloca. Returns 0 if the 1543ca95b02SDimitry Andric /// size can not be statically determined. 1553ca95b02SDimitry Andric uint64_t getStaticAllocaAllocationSize(const AllocaInst* AI); 1563ca95b02SDimitry Andric 1573ca95b02SDimitry Andric /// \brief Allocate space for all static allocas in \p StaticAllocas, 1583ca95b02SDimitry Andric /// replace allocas with pointers into the unsafe stack and generate code to 1593ca95b02SDimitry Andric /// restore the stack pointer before all return instructions in \p Returns. 1603ca95b02SDimitry Andric /// 1613ca95b02SDimitry Andric /// \returns A pointer to the top of the unsafe stack after all unsafe static 1623ca95b02SDimitry Andric /// allocas are allocated. 1633ca95b02SDimitry Andric Value *moveStaticAllocasToUnsafeStack(IRBuilder<> &IRB, Function &F, 1643ca95b02SDimitry Andric ArrayRef<AllocaInst *> StaticAllocas, 1653ca95b02SDimitry Andric ArrayRef<Argument *> ByValArguments, 1663ca95b02SDimitry Andric ArrayRef<ReturnInst *> Returns, 1673ca95b02SDimitry Andric Instruction *BasePointer, 1683ca95b02SDimitry Andric AllocaInst *StackGuardSlot); 1693ca95b02SDimitry Andric 1703ca95b02SDimitry Andric /// \brief Generate code to restore the stack after all stack restore points 1713ca95b02SDimitry Andric /// in \p StackRestorePoints. 1723ca95b02SDimitry Andric /// 1733ca95b02SDimitry Andric /// \returns A local variable in which to maintain the dynamic top of the 1743ca95b02SDimitry Andric /// unsafe stack if needed. 1753ca95b02SDimitry Andric AllocaInst * 1763ca95b02SDimitry Andric createStackRestorePoints(IRBuilder<> &IRB, Function &F, 1773ca95b02SDimitry Andric ArrayRef<Instruction *> StackRestorePoints, 1783ca95b02SDimitry Andric Value *StaticTop, bool NeedDynamicTop); 1793ca95b02SDimitry Andric 1803ca95b02SDimitry Andric /// \brief Replace all allocas in \p DynamicAllocas with code to allocate 1813ca95b02SDimitry Andric /// space dynamically on the unsafe stack and store the dynamic unsafe stack 1823ca95b02SDimitry Andric /// top to \p DynamicTop if non-null. 1833ca95b02SDimitry Andric void moveDynamicAllocasToUnsafeStack(Function &F, Value *UnsafeStackPtr, 1843ca95b02SDimitry Andric AllocaInst *DynamicTop, 1853ca95b02SDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas); 1863ca95b02SDimitry Andric 1873ca95b02SDimitry Andric bool IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize); 1883ca95b02SDimitry Andric 1893ca95b02SDimitry Andric bool IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, 1903ca95b02SDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize); 1913ca95b02SDimitry Andric bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr, 1923ca95b02SDimitry Andric uint64_t AllocaSize); 1933ca95b02SDimitry Andric 1943ca95b02SDimitry Andric public: 1955517e702SDimitry Andric SafeStack(Function &F, const TargetLoweringBase &TL, const DataLayout &DL, 1965517e702SDimitry Andric ScalarEvolution &SE) 1975517e702SDimitry Andric : F(F), TL(TL), DL(DL), SE(SE), 1985517e702SDimitry Andric StackPtrTy(Type::getInt8PtrTy(F.getContext())), 1995517e702SDimitry Andric IntPtrTy(DL.getIntPtrType(F.getContext())), 2005517e702SDimitry Andric Int32Ty(Type::getInt32Ty(F.getContext())), 2015517e702SDimitry Andric Int8Ty(Type::getInt8Ty(F.getContext())) {} 2023ca95b02SDimitry Andric 2035517e702SDimitry Andric // Run the transformation on the associated function. 2045517e702SDimitry Andric // Returns whether the function was changed. 2055517e702SDimitry Andric bool run(); 2065517e702SDimitry Andric }; 2073ca95b02SDimitry Andric 2083ca95b02SDimitry Andric uint64_t SafeStack::getStaticAllocaAllocationSize(const AllocaInst* AI) { 2095517e702SDimitry Andric uint64_t Size = DL.getTypeAllocSize(AI->getAllocatedType()); 2103ca95b02SDimitry Andric if (AI->isArrayAllocation()) { 2113ca95b02SDimitry Andric auto C = dyn_cast<ConstantInt>(AI->getArraySize()); 2123ca95b02SDimitry Andric if (!C) 2133ca95b02SDimitry Andric return 0; 2143ca95b02SDimitry Andric Size *= C->getZExtValue(); 2153ca95b02SDimitry Andric } 2163ca95b02SDimitry Andric return Size; 2173ca95b02SDimitry Andric } 2183ca95b02SDimitry Andric 2193ca95b02SDimitry Andric bool SafeStack::IsAccessSafe(Value *Addr, uint64_t AccessSize, 2203ca95b02SDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize) { 2215517e702SDimitry Andric AllocaOffsetRewriter Rewriter(SE, AllocaPtr); 2225517e702SDimitry Andric const SCEV *Expr = Rewriter.visit(SE.getSCEV(Addr)); 2233ca95b02SDimitry Andric 2245517e702SDimitry Andric uint64_t BitWidth = SE.getTypeSizeInBits(Expr->getType()); 2255517e702SDimitry Andric ConstantRange AccessStartRange = SE.getUnsignedRange(Expr); 2263ca95b02SDimitry Andric ConstantRange SizeRange = 2273ca95b02SDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AccessSize)); 2283ca95b02SDimitry Andric ConstantRange AccessRange = AccessStartRange.add(SizeRange); 2293ca95b02SDimitry Andric ConstantRange AllocaRange = 2303ca95b02SDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AllocaSize)); 2313ca95b02SDimitry Andric bool Safe = AllocaRange.contains(AccessRange); 2323ca95b02SDimitry Andric 2333ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] " 2343ca95b02SDimitry Andric << (isa<AllocaInst>(AllocaPtr) ? "Alloca " : "ByValArgument ") 2353ca95b02SDimitry Andric << *AllocaPtr << "\n" 2363ca95b02SDimitry Andric << " Access " << *Addr << "\n" 2373ca95b02SDimitry Andric << " SCEV " << *Expr 2385517e702SDimitry Andric << " U: " << SE.getUnsignedRange(Expr) 2395517e702SDimitry Andric << ", S: " << SE.getSignedRange(Expr) << "\n" 2403ca95b02SDimitry Andric << " Range " << AccessRange << "\n" 2413ca95b02SDimitry Andric << " AllocaRange " << AllocaRange << "\n" 2423ca95b02SDimitry Andric << " " << (Safe ? "safe" : "unsafe") << "\n"); 2433ca95b02SDimitry Andric 2443ca95b02SDimitry Andric return Safe; 2453ca95b02SDimitry Andric } 2463ca95b02SDimitry Andric 2473ca95b02SDimitry Andric bool SafeStack::IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, 2483ca95b02SDimitry Andric const Value *AllocaPtr, 2493ca95b02SDimitry Andric uint64_t AllocaSize) { 2503ca95b02SDimitry Andric // All MemIntrinsics have destination address in Arg0 and size in Arg2. 2513ca95b02SDimitry Andric if (MI->getRawDest() != U) return true; 2523ca95b02SDimitry Andric const auto *Len = dyn_cast<ConstantInt>(MI->getLength()); 2533ca95b02SDimitry Andric // Non-constant size => unsafe. FIXME: try SCEV getRange. 2543ca95b02SDimitry Andric if (!Len) return false; 2553ca95b02SDimitry Andric return IsAccessSafe(U, Len->getZExtValue(), AllocaPtr, AllocaSize); 2563ca95b02SDimitry Andric } 2573ca95b02SDimitry Andric 2583ca95b02SDimitry Andric /// Check whether a given allocation must be put on the safe 2593ca95b02SDimitry Andric /// stack or not. The function analyzes all uses of AI and checks whether it is 2603ca95b02SDimitry Andric /// only accessed in a memory safe way (as decided statically). 2613ca95b02SDimitry Andric bool SafeStack::IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize) { 2623ca95b02SDimitry Andric // Go through all uses of this alloca and check whether all accesses to the 2633ca95b02SDimitry Andric // allocated object are statically known to be memory safe and, hence, the 2643ca95b02SDimitry Andric // object can be placed on the safe stack. 2653ca95b02SDimitry Andric SmallPtrSet<const Value *, 16> Visited; 2663ca95b02SDimitry Andric SmallVector<const Value *, 8> WorkList; 2673ca95b02SDimitry Andric WorkList.push_back(AllocaPtr); 2683ca95b02SDimitry Andric 2693ca95b02SDimitry Andric // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc. 2703ca95b02SDimitry Andric while (!WorkList.empty()) { 2713ca95b02SDimitry Andric const Value *V = WorkList.pop_back_val(); 2723ca95b02SDimitry Andric for (const Use &UI : V->uses()) { 2733ca95b02SDimitry Andric auto I = cast<const Instruction>(UI.getUser()); 2743ca95b02SDimitry Andric assert(V == UI.get()); 2753ca95b02SDimitry Andric 2763ca95b02SDimitry Andric switch (I->getOpcode()) { 2772cab237bSDimitry Andric case Instruction::Load: 2785517e702SDimitry Andric if (!IsAccessSafe(UI, DL.getTypeStoreSize(I->getType()), AllocaPtr, 2793ca95b02SDimitry Andric AllocaSize)) 2803ca95b02SDimitry Andric return false; 2813ca95b02SDimitry Andric break; 2822cab237bSDimitry Andric 2833ca95b02SDimitry Andric case Instruction::VAArg: 2843ca95b02SDimitry Andric // "va-arg" from a pointer is safe. 2853ca95b02SDimitry Andric break; 2862cab237bSDimitry Andric case Instruction::Store: 2873ca95b02SDimitry Andric if (V == I->getOperand(0)) { 2883ca95b02SDimitry Andric // Stored the pointer - conservatively assume it may be unsafe. 2893ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr 2903ca95b02SDimitry Andric << "\n store of address: " << *I << "\n"); 2913ca95b02SDimitry Andric return false; 2923ca95b02SDimitry Andric } 2933ca95b02SDimitry Andric 2945517e702SDimitry Andric if (!IsAccessSafe(UI, DL.getTypeStoreSize(I->getOperand(0)->getType()), 2953ca95b02SDimitry Andric AllocaPtr, AllocaSize)) 2963ca95b02SDimitry Andric return false; 2973ca95b02SDimitry Andric break; 2982cab237bSDimitry Andric 2992cab237bSDimitry Andric case Instruction::Ret: 3003ca95b02SDimitry Andric // Information leak. 3013ca95b02SDimitry Andric return false; 3023ca95b02SDimitry Andric 3033ca95b02SDimitry Andric case Instruction::Call: 3043ca95b02SDimitry Andric case Instruction::Invoke: { 3053ca95b02SDimitry Andric ImmutableCallSite CS(I); 3063ca95b02SDimitry Andric 3073ca95b02SDimitry Andric if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { 3083ca95b02SDimitry Andric if (II->getIntrinsicID() == Intrinsic::lifetime_start || 3093ca95b02SDimitry Andric II->getIntrinsicID() == Intrinsic::lifetime_end) 3103ca95b02SDimitry Andric continue; 3113ca95b02SDimitry Andric } 3123ca95b02SDimitry Andric 3133ca95b02SDimitry Andric if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { 3143ca95b02SDimitry Andric if (!IsMemIntrinsicSafe(MI, UI, AllocaPtr, AllocaSize)) { 3153ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr 3163ca95b02SDimitry Andric << "\n unsafe memintrinsic: " << *I 3173ca95b02SDimitry Andric << "\n"); 3183ca95b02SDimitry Andric return false; 3193ca95b02SDimitry Andric } 3203ca95b02SDimitry Andric continue; 3213ca95b02SDimitry Andric } 3223ca95b02SDimitry Andric 3233ca95b02SDimitry Andric // LLVM 'nocapture' attribute is only set for arguments whose address 3243ca95b02SDimitry Andric // is not stored, passed around, or used in any other non-trivial way. 3253ca95b02SDimitry Andric // We assume that passing a pointer to an object as a 'nocapture 3263ca95b02SDimitry Andric // readnone' argument is safe. 3273ca95b02SDimitry Andric // FIXME: a more precise solution would require an interprocedural 3283ca95b02SDimitry Andric // analysis here, which would look at all uses of an argument inside 3293ca95b02SDimitry Andric // the function being called. 3303ca95b02SDimitry Andric ImmutableCallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end(); 3313ca95b02SDimitry Andric for (ImmutableCallSite::arg_iterator A = B; A != E; ++A) 3323ca95b02SDimitry Andric if (A->get() == V) 3333ca95b02SDimitry Andric if (!(CS.doesNotCapture(A - B) && (CS.doesNotAccessMemory(A - B) || 3343ca95b02SDimitry Andric CS.doesNotAccessMemory()))) { 3353ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr 3363ca95b02SDimitry Andric << "\n unsafe call: " << *I << "\n"); 3373ca95b02SDimitry Andric return false; 3383ca95b02SDimitry Andric } 3393ca95b02SDimitry Andric continue; 3403ca95b02SDimitry Andric } 3413ca95b02SDimitry Andric 3423ca95b02SDimitry Andric default: 3433ca95b02SDimitry Andric if (Visited.insert(I).second) 3443ca95b02SDimitry Andric WorkList.push_back(cast<const Instruction>(I)); 3453ca95b02SDimitry Andric } 3463ca95b02SDimitry Andric } 3473ca95b02SDimitry Andric } 3483ca95b02SDimitry Andric 3493ca95b02SDimitry Andric // All uses of the alloca are safe, we can place it on the safe stack. 3503ca95b02SDimitry Andric return true; 3513ca95b02SDimitry Andric } 3523ca95b02SDimitry Andric 3533ca95b02SDimitry Andric Value *SafeStack::getStackGuard(IRBuilder<> &IRB, Function &F) { 3545517e702SDimitry Andric Value *StackGuardVar = TL.getIRStackGuard(IRB); 3553ca95b02SDimitry Andric if (!StackGuardVar) 3563ca95b02SDimitry Andric StackGuardVar = 3573ca95b02SDimitry Andric F.getParent()->getOrInsertGlobal("__stack_chk_guard", StackPtrTy); 3583ca95b02SDimitry Andric return IRB.CreateLoad(StackGuardVar, "StackGuard"); 3593ca95b02SDimitry Andric } 3603ca95b02SDimitry Andric 3613ca95b02SDimitry Andric void SafeStack::findInsts(Function &F, 3623ca95b02SDimitry Andric SmallVectorImpl<AllocaInst *> &StaticAllocas, 3633ca95b02SDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas, 3643ca95b02SDimitry Andric SmallVectorImpl<Argument *> &ByValArguments, 3653ca95b02SDimitry Andric SmallVectorImpl<ReturnInst *> &Returns, 3663ca95b02SDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints) { 3673ca95b02SDimitry Andric for (Instruction &I : instructions(&F)) { 3683ca95b02SDimitry Andric if (auto AI = dyn_cast<AllocaInst>(&I)) { 3693ca95b02SDimitry Andric ++NumAllocas; 3703ca95b02SDimitry Andric 3713ca95b02SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 3723ca95b02SDimitry Andric if (IsSafeStackAlloca(AI, Size)) 3733ca95b02SDimitry Andric continue; 3743ca95b02SDimitry Andric 3753ca95b02SDimitry Andric if (AI->isStaticAlloca()) { 3763ca95b02SDimitry Andric ++NumUnsafeStaticAllocas; 3773ca95b02SDimitry Andric StaticAllocas.push_back(AI); 3783ca95b02SDimitry Andric } else { 3793ca95b02SDimitry Andric ++NumUnsafeDynamicAllocas; 3803ca95b02SDimitry Andric DynamicAllocas.push_back(AI); 3813ca95b02SDimitry Andric } 3823ca95b02SDimitry Andric } else if (auto RI = dyn_cast<ReturnInst>(&I)) { 3833ca95b02SDimitry Andric Returns.push_back(RI); 3843ca95b02SDimitry Andric } else if (auto CI = dyn_cast<CallInst>(&I)) { 3853ca95b02SDimitry Andric // setjmps require stack restore. 3863ca95b02SDimitry Andric if (CI->getCalledFunction() && CI->canReturnTwice()) 3873ca95b02SDimitry Andric StackRestorePoints.push_back(CI); 3883ca95b02SDimitry Andric } else if (auto LP = dyn_cast<LandingPadInst>(&I)) { 3893ca95b02SDimitry Andric // Exception landing pads require stack restore. 3903ca95b02SDimitry Andric StackRestorePoints.push_back(LP); 3913ca95b02SDimitry Andric } else if (auto II = dyn_cast<IntrinsicInst>(&I)) { 3923ca95b02SDimitry Andric if (II->getIntrinsicID() == Intrinsic::gcroot) 3932cab237bSDimitry Andric report_fatal_error( 3943ca95b02SDimitry Andric "gcroot intrinsic not compatible with safestack attribute"); 3953ca95b02SDimitry Andric } 3963ca95b02SDimitry Andric } 3973ca95b02SDimitry Andric for (Argument &Arg : F.args()) { 3983ca95b02SDimitry Andric if (!Arg.hasByValAttr()) 3993ca95b02SDimitry Andric continue; 4003ca95b02SDimitry Andric uint64_t Size = 4015517e702SDimitry Andric DL.getTypeStoreSize(Arg.getType()->getPointerElementType()); 4023ca95b02SDimitry Andric if (IsSafeStackAlloca(&Arg, Size)) 4033ca95b02SDimitry Andric continue; 4043ca95b02SDimitry Andric 4053ca95b02SDimitry Andric ++NumUnsafeByValArguments; 4063ca95b02SDimitry Andric ByValArguments.push_back(&Arg); 4073ca95b02SDimitry Andric } 4083ca95b02SDimitry Andric } 4093ca95b02SDimitry Andric 4103ca95b02SDimitry Andric AllocaInst * 4113ca95b02SDimitry Andric SafeStack::createStackRestorePoints(IRBuilder<> &IRB, Function &F, 4123ca95b02SDimitry Andric ArrayRef<Instruction *> StackRestorePoints, 4133ca95b02SDimitry Andric Value *StaticTop, bool NeedDynamicTop) { 4143ca95b02SDimitry Andric assert(StaticTop && "The stack top isn't set."); 4153ca95b02SDimitry Andric 4163ca95b02SDimitry Andric if (StackRestorePoints.empty()) 4173ca95b02SDimitry Andric return nullptr; 4183ca95b02SDimitry Andric 4193ca95b02SDimitry Andric // We need the current value of the shadow stack pointer to restore 4203ca95b02SDimitry Andric // after longjmp or exception catching. 4213ca95b02SDimitry Andric 4223ca95b02SDimitry Andric // FIXME: On some platforms this could be handled by the longjmp/exception 4233ca95b02SDimitry Andric // runtime itself. 4243ca95b02SDimitry Andric 4253ca95b02SDimitry Andric AllocaInst *DynamicTop = nullptr; 4263ca95b02SDimitry Andric if (NeedDynamicTop) { 4273ca95b02SDimitry Andric // If we also have dynamic alloca's, the stack pointer value changes 4283ca95b02SDimitry Andric // throughout the function. For now we store it in an alloca. 4293ca95b02SDimitry Andric DynamicTop = IRB.CreateAlloca(StackPtrTy, /*ArraySize=*/nullptr, 4303ca95b02SDimitry Andric "unsafe_stack_dynamic_ptr"); 4313ca95b02SDimitry Andric IRB.CreateStore(StaticTop, DynamicTop); 4323ca95b02SDimitry Andric } 4333ca95b02SDimitry Andric 4343ca95b02SDimitry Andric // Restore current stack pointer after longjmp/exception catch. 4353ca95b02SDimitry Andric for (Instruction *I : StackRestorePoints) { 4363ca95b02SDimitry Andric ++NumUnsafeStackRestorePoints; 4373ca95b02SDimitry Andric 4383ca95b02SDimitry Andric IRB.SetInsertPoint(I->getNextNode()); 4393ca95b02SDimitry Andric Value *CurrentTop = DynamicTop ? IRB.CreateLoad(DynamicTop) : StaticTop; 4403ca95b02SDimitry Andric IRB.CreateStore(CurrentTop, UnsafeStackPtr); 4413ca95b02SDimitry Andric } 4423ca95b02SDimitry Andric 4433ca95b02SDimitry Andric return DynamicTop; 4443ca95b02SDimitry Andric } 4453ca95b02SDimitry Andric 4463ca95b02SDimitry Andric void SafeStack::checkStackGuard(IRBuilder<> &IRB, Function &F, ReturnInst &RI, 4473ca95b02SDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard) { 4483ca95b02SDimitry Andric Value *V = IRB.CreateLoad(StackGuardSlot); 4493ca95b02SDimitry Andric Value *Cmp = IRB.CreateICmpNE(StackGuard, V); 4503ca95b02SDimitry Andric 4513ca95b02SDimitry Andric auto SuccessProb = BranchProbabilityInfo::getBranchProbStackProtector(true); 4523ca95b02SDimitry Andric auto FailureProb = BranchProbabilityInfo::getBranchProbStackProtector(false); 4533ca95b02SDimitry Andric MDNode *Weights = MDBuilder(F.getContext()) 4543ca95b02SDimitry Andric .createBranchWeights(SuccessProb.getNumerator(), 4553ca95b02SDimitry Andric FailureProb.getNumerator()); 4563ca95b02SDimitry Andric Instruction *CheckTerm = 4573ca95b02SDimitry Andric SplitBlockAndInsertIfThen(Cmp, &RI, 4583ca95b02SDimitry Andric /* Unreachable */ true, Weights); 4593ca95b02SDimitry Andric IRBuilder<> IRBFail(CheckTerm); 4603ca95b02SDimitry Andric // FIXME: respect -fsanitize-trap / -ftrap-function here? 4613ca95b02SDimitry Andric Constant *StackChkFail = F.getParent()->getOrInsertFunction( 4627a7e6055SDimitry Andric "__stack_chk_fail", IRB.getVoidTy()); 4633ca95b02SDimitry Andric IRBFail.CreateCall(StackChkFail, {}); 4643ca95b02SDimitry Andric } 4653ca95b02SDimitry Andric 4663ca95b02SDimitry Andric /// We explicitly compute and set the unsafe stack layout for all unsafe 4673ca95b02SDimitry Andric /// static alloca instructions. We save the unsafe "base pointer" in the 4683ca95b02SDimitry Andric /// prologue into a local variable and restore it in the epilogue. 4693ca95b02SDimitry Andric Value *SafeStack::moveStaticAllocasToUnsafeStack( 4703ca95b02SDimitry Andric IRBuilder<> &IRB, Function &F, ArrayRef<AllocaInst *> StaticAllocas, 4713ca95b02SDimitry Andric ArrayRef<Argument *> ByValArguments, ArrayRef<ReturnInst *> Returns, 4723ca95b02SDimitry Andric Instruction *BasePointer, AllocaInst *StackGuardSlot) { 4733ca95b02SDimitry Andric if (StaticAllocas.empty() && ByValArguments.empty()) 4743ca95b02SDimitry Andric return BasePointer; 4753ca95b02SDimitry Andric 4763ca95b02SDimitry Andric DIBuilder DIB(*F.getParent()); 4773ca95b02SDimitry Andric 4783ca95b02SDimitry Andric StackColoring SSC(F, StaticAllocas); 4793ca95b02SDimitry Andric SSC.run(); 4803ca95b02SDimitry Andric SSC.removeAllMarkers(); 4813ca95b02SDimitry Andric 4823ca95b02SDimitry Andric // Unsafe stack always grows down. 4833ca95b02SDimitry Andric StackLayout SSL(StackAlignment); 4843ca95b02SDimitry Andric if (StackGuardSlot) { 4853ca95b02SDimitry Andric Type *Ty = StackGuardSlot->getAllocatedType(); 4863ca95b02SDimitry Andric unsigned Align = 4875517e702SDimitry Andric std::max(DL.getPrefTypeAlignment(Ty), StackGuardSlot->getAlignment()); 4883ca95b02SDimitry Andric SSL.addObject(StackGuardSlot, getStaticAllocaAllocationSize(StackGuardSlot), 4896c4bc1bdSDimitry Andric Align, SSC.getFullLiveRange()); 4903ca95b02SDimitry Andric } 4913ca95b02SDimitry Andric 4923ca95b02SDimitry Andric for (Argument *Arg : ByValArguments) { 4933ca95b02SDimitry Andric Type *Ty = Arg->getType()->getPointerElementType(); 4945517e702SDimitry Andric uint64_t Size = DL.getTypeStoreSize(Ty); 4953ca95b02SDimitry Andric if (Size == 0) 4963ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 4973ca95b02SDimitry Andric 4983ca95b02SDimitry Andric // Ensure the object is properly aligned. 4995517e702SDimitry Andric unsigned Align = std::max((unsigned)DL.getPrefTypeAlignment(Ty), 5003ca95b02SDimitry Andric Arg->getParamAlignment()); 5013ca95b02SDimitry Andric SSL.addObject(Arg, Size, Align, SSC.getFullLiveRange()); 5023ca95b02SDimitry Andric } 5033ca95b02SDimitry Andric 5043ca95b02SDimitry Andric for (AllocaInst *AI : StaticAllocas) { 5053ca95b02SDimitry Andric Type *Ty = AI->getAllocatedType(); 5063ca95b02SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 5073ca95b02SDimitry Andric if (Size == 0) 5083ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5093ca95b02SDimitry Andric 5103ca95b02SDimitry Andric // Ensure the object is properly aligned. 5113ca95b02SDimitry Andric unsigned Align = 5125517e702SDimitry Andric std::max((unsigned)DL.getPrefTypeAlignment(Ty), AI->getAlignment()); 5133ca95b02SDimitry Andric 5143ca95b02SDimitry Andric SSL.addObject(AI, Size, Align, SSC.getLiveRange(AI)); 5153ca95b02SDimitry Andric } 5163ca95b02SDimitry Andric 5173ca95b02SDimitry Andric SSL.computeLayout(); 5183ca95b02SDimitry Andric unsigned FrameAlignment = SSL.getFrameAlignment(); 5193ca95b02SDimitry Andric 5203ca95b02SDimitry Andric // FIXME: tell SSL that we start at a less-then-MaxAlignment aligned location 5213ca95b02SDimitry Andric // (AlignmentSkew). 5223ca95b02SDimitry Andric if (FrameAlignment > StackAlignment) { 5233ca95b02SDimitry Andric // Re-align the base pointer according to the max requested alignment. 5243ca95b02SDimitry Andric assert(isPowerOf2_32(FrameAlignment)); 5253ca95b02SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 5263ca95b02SDimitry Andric BasePointer = cast<Instruction>(IRB.CreateIntToPtr( 5273ca95b02SDimitry Andric IRB.CreateAnd(IRB.CreatePtrToInt(BasePointer, IntPtrTy), 5283ca95b02SDimitry Andric ConstantInt::get(IntPtrTy, ~uint64_t(FrameAlignment - 1))), 5293ca95b02SDimitry Andric StackPtrTy)); 5303ca95b02SDimitry Andric } 5313ca95b02SDimitry Andric 5323ca95b02SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 5333ca95b02SDimitry Andric 5343ca95b02SDimitry Andric if (StackGuardSlot) { 5353ca95b02SDimitry Andric unsigned Offset = SSL.getObjectOffset(StackGuardSlot); 5363ca95b02SDimitry Andric Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* 5373ca95b02SDimitry Andric ConstantInt::get(Int32Ty, -Offset)); 5383ca95b02SDimitry Andric Value *NewAI = 5393ca95b02SDimitry Andric IRB.CreateBitCast(Off, StackGuardSlot->getType(), "StackGuardSlot"); 5403ca95b02SDimitry Andric 5413ca95b02SDimitry Andric // Replace alloc with the new location. 5423ca95b02SDimitry Andric StackGuardSlot->replaceAllUsesWith(NewAI); 5433ca95b02SDimitry Andric StackGuardSlot->eraseFromParent(); 5443ca95b02SDimitry Andric } 5453ca95b02SDimitry Andric 5463ca95b02SDimitry Andric for (Argument *Arg : ByValArguments) { 5473ca95b02SDimitry Andric unsigned Offset = SSL.getObjectOffset(Arg); 5483ca95b02SDimitry Andric Type *Ty = Arg->getType()->getPointerElementType(); 5493ca95b02SDimitry Andric 5505517e702SDimitry Andric uint64_t Size = DL.getTypeStoreSize(Ty); 5513ca95b02SDimitry Andric if (Size == 0) 5523ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5533ca95b02SDimitry Andric 5543ca95b02SDimitry Andric Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* 5553ca95b02SDimitry Andric ConstantInt::get(Int32Ty, -Offset)); 5563ca95b02SDimitry Andric Value *NewArg = IRB.CreateBitCast(Off, Arg->getType(), 5573ca95b02SDimitry Andric Arg->getName() + ".unsafe-byval"); 5583ca95b02SDimitry Andric 5593ca95b02SDimitry Andric // Replace alloc with the new location. 5603ca95b02SDimitry Andric replaceDbgDeclare(Arg, BasePointer, BasePointer->getNextNode(), DIB, 5612cab237bSDimitry Andric DIExpression::NoDeref, -Offset, DIExpression::NoDeref); 5623ca95b02SDimitry Andric Arg->replaceAllUsesWith(NewArg); 5633ca95b02SDimitry Andric IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode()); 5643ca95b02SDimitry Andric IRB.CreateMemCpy(Off, Arg, Size, Arg->getParamAlignment()); 5653ca95b02SDimitry Andric } 5663ca95b02SDimitry Andric 5673ca95b02SDimitry Andric // Allocate space for every unsafe static AllocaInst on the unsafe stack. 5683ca95b02SDimitry Andric for (AllocaInst *AI : StaticAllocas) { 5693ca95b02SDimitry Andric IRB.SetInsertPoint(AI); 5703ca95b02SDimitry Andric unsigned Offset = SSL.getObjectOffset(AI); 5713ca95b02SDimitry Andric 5723ca95b02SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 5733ca95b02SDimitry Andric if (Size == 0) 5743ca95b02SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5753ca95b02SDimitry Andric 5762cab237bSDimitry Andric replaceDbgDeclareForAlloca(AI, BasePointer, DIB, DIExpression::NoDeref, 5772cab237bSDimitry Andric -Offset, DIExpression::NoDeref); 5783ca95b02SDimitry Andric replaceDbgValueForAlloca(AI, BasePointer, DIB, -Offset); 5793ca95b02SDimitry Andric 5803ca95b02SDimitry Andric // Replace uses of the alloca with the new location. 5813ca95b02SDimitry Andric // Insert address calculation close to each use to work around PR27844. 5823ca95b02SDimitry Andric std::string Name = std::string(AI->getName()) + ".unsafe"; 5833ca95b02SDimitry Andric while (!AI->use_empty()) { 5843ca95b02SDimitry Andric Use &U = *AI->use_begin(); 5853ca95b02SDimitry Andric Instruction *User = cast<Instruction>(U.getUser()); 5863ca95b02SDimitry Andric 5873ca95b02SDimitry Andric Instruction *InsertBefore; 5883ca95b02SDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User)) 5893ca95b02SDimitry Andric InsertBefore = PHI->getIncomingBlock(U)->getTerminator(); 5903ca95b02SDimitry Andric else 5913ca95b02SDimitry Andric InsertBefore = User; 5923ca95b02SDimitry Andric 5933ca95b02SDimitry Andric IRBuilder<> IRBUser(InsertBefore); 5943ca95b02SDimitry Andric Value *Off = IRBUser.CreateGEP(BasePointer, // BasePointer is i8* 5953ca95b02SDimitry Andric ConstantInt::get(Int32Ty, -Offset)); 5963ca95b02SDimitry Andric Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name); 5973ca95b02SDimitry Andric 5983ca95b02SDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User)) { 5993ca95b02SDimitry Andric // PHI nodes may have multiple incoming edges from the same BB (why??), 6003ca95b02SDimitry Andric // all must be updated at once with the same incoming value. 6013ca95b02SDimitry Andric auto *BB = PHI->getIncomingBlock(U); 6023ca95b02SDimitry Andric for (unsigned I = 0; I < PHI->getNumIncomingValues(); ++I) 6033ca95b02SDimitry Andric if (PHI->getIncomingBlock(I) == BB) 6043ca95b02SDimitry Andric PHI->setIncomingValue(I, Replacement); 6053ca95b02SDimitry Andric } else { 6063ca95b02SDimitry Andric U.set(Replacement); 6073ca95b02SDimitry Andric } 6083ca95b02SDimitry Andric } 6093ca95b02SDimitry Andric 6103ca95b02SDimitry Andric AI->eraseFromParent(); 6113ca95b02SDimitry Andric } 6123ca95b02SDimitry Andric 6133ca95b02SDimitry Andric // Re-align BasePointer so that our callees would see it aligned as 6143ca95b02SDimitry Andric // expected. 6153ca95b02SDimitry Andric // FIXME: no need to update BasePointer in leaf functions. 6163ca95b02SDimitry Andric unsigned FrameSize = alignTo(SSL.getFrameSize(), StackAlignment); 6173ca95b02SDimitry Andric 6183ca95b02SDimitry Andric // Update shadow stack pointer in the function epilogue. 6193ca95b02SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 6203ca95b02SDimitry Andric 6213ca95b02SDimitry Andric Value *StaticTop = 6223ca95b02SDimitry Andric IRB.CreateGEP(BasePointer, ConstantInt::get(Int32Ty, -FrameSize), 6233ca95b02SDimitry Andric "unsafe_stack_static_top"); 6243ca95b02SDimitry Andric IRB.CreateStore(StaticTop, UnsafeStackPtr); 6253ca95b02SDimitry Andric return StaticTop; 6263ca95b02SDimitry Andric } 6273ca95b02SDimitry Andric 6283ca95b02SDimitry Andric void SafeStack::moveDynamicAllocasToUnsafeStack( 6293ca95b02SDimitry Andric Function &F, Value *UnsafeStackPtr, AllocaInst *DynamicTop, 6303ca95b02SDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas) { 6313ca95b02SDimitry Andric DIBuilder DIB(*F.getParent()); 6323ca95b02SDimitry Andric 6333ca95b02SDimitry Andric for (AllocaInst *AI : DynamicAllocas) { 6343ca95b02SDimitry Andric IRBuilder<> IRB(AI); 6353ca95b02SDimitry Andric 6363ca95b02SDimitry Andric // Compute the new SP value (after AI). 6373ca95b02SDimitry Andric Value *ArraySize = AI->getArraySize(); 6383ca95b02SDimitry Andric if (ArraySize->getType() != IntPtrTy) 6393ca95b02SDimitry Andric ArraySize = IRB.CreateIntCast(ArraySize, IntPtrTy, false); 6403ca95b02SDimitry Andric 6413ca95b02SDimitry Andric Type *Ty = AI->getAllocatedType(); 6425517e702SDimitry Andric uint64_t TySize = DL.getTypeAllocSize(Ty); 6433ca95b02SDimitry Andric Value *Size = IRB.CreateMul(ArraySize, ConstantInt::get(IntPtrTy, TySize)); 6443ca95b02SDimitry Andric 6453ca95b02SDimitry Andric Value *SP = IRB.CreatePtrToInt(IRB.CreateLoad(UnsafeStackPtr), IntPtrTy); 6463ca95b02SDimitry Andric SP = IRB.CreateSub(SP, Size); 6473ca95b02SDimitry Andric 6483ca95b02SDimitry Andric // Align the SP value to satisfy the AllocaInst, type and stack alignments. 6493ca95b02SDimitry Andric unsigned Align = std::max( 6505517e702SDimitry Andric std::max((unsigned)DL.getPrefTypeAlignment(Ty), AI->getAlignment()), 6513ca95b02SDimitry Andric (unsigned)StackAlignment); 6523ca95b02SDimitry Andric 6533ca95b02SDimitry Andric assert(isPowerOf2_32(Align)); 6543ca95b02SDimitry Andric Value *NewTop = IRB.CreateIntToPtr( 6553ca95b02SDimitry Andric IRB.CreateAnd(SP, ConstantInt::get(IntPtrTy, ~uint64_t(Align - 1))), 6563ca95b02SDimitry Andric StackPtrTy); 6573ca95b02SDimitry Andric 6583ca95b02SDimitry Andric // Save the stack pointer. 6593ca95b02SDimitry Andric IRB.CreateStore(NewTop, UnsafeStackPtr); 6603ca95b02SDimitry Andric if (DynamicTop) 6613ca95b02SDimitry Andric IRB.CreateStore(NewTop, DynamicTop); 6623ca95b02SDimitry Andric 6633ca95b02SDimitry Andric Value *NewAI = IRB.CreatePointerCast(NewTop, AI->getType()); 6643ca95b02SDimitry Andric if (AI->hasName() && isa<Instruction>(NewAI)) 6653ca95b02SDimitry Andric NewAI->takeName(AI); 6663ca95b02SDimitry Andric 6672cab237bSDimitry Andric replaceDbgDeclareForAlloca(AI, NewAI, DIB, DIExpression::NoDeref, 0, 6682cab237bSDimitry Andric DIExpression::NoDeref); 6693ca95b02SDimitry Andric AI->replaceAllUsesWith(NewAI); 6703ca95b02SDimitry Andric AI->eraseFromParent(); 6713ca95b02SDimitry Andric } 6723ca95b02SDimitry Andric 6733ca95b02SDimitry Andric if (!DynamicAllocas.empty()) { 6743ca95b02SDimitry Andric // Now go through the instructions again, replacing stacksave/stackrestore. 6753ca95b02SDimitry Andric for (inst_iterator It = inst_begin(&F), Ie = inst_end(&F); It != Ie;) { 6763ca95b02SDimitry Andric Instruction *I = &*(It++); 6773ca95b02SDimitry Andric auto II = dyn_cast<IntrinsicInst>(I); 6783ca95b02SDimitry Andric if (!II) 6793ca95b02SDimitry Andric continue; 6803ca95b02SDimitry Andric 6813ca95b02SDimitry Andric if (II->getIntrinsicID() == Intrinsic::stacksave) { 6823ca95b02SDimitry Andric IRBuilder<> IRB(II); 6833ca95b02SDimitry Andric Instruction *LI = IRB.CreateLoad(UnsafeStackPtr); 6843ca95b02SDimitry Andric LI->takeName(II); 6853ca95b02SDimitry Andric II->replaceAllUsesWith(LI); 6863ca95b02SDimitry Andric II->eraseFromParent(); 6873ca95b02SDimitry Andric } else if (II->getIntrinsicID() == Intrinsic::stackrestore) { 6883ca95b02SDimitry Andric IRBuilder<> IRB(II); 6893ca95b02SDimitry Andric Instruction *SI = IRB.CreateStore(II->getArgOperand(0), UnsafeStackPtr); 6903ca95b02SDimitry Andric SI->takeName(II); 6913ca95b02SDimitry Andric assert(II->use_empty()); 6923ca95b02SDimitry Andric II->eraseFromParent(); 6933ca95b02SDimitry Andric } 6943ca95b02SDimitry Andric } 6953ca95b02SDimitry Andric } 6963ca95b02SDimitry Andric } 6973ca95b02SDimitry Andric 6985517e702SDimitry Andric bool SafeStack::run() { 6995517e702SDimitry Andric assert(F.hasFnAttribute(Attribute::SafeStack) && 7005517e702SDimitry Andric "Can't run SafeStack on a function without the attribute"); 7015517e702SDimitry Andric assert(!F.isDeclaration() && "Can't run SafeStack on a function declaration"); 7023ca95b02SDimitry Andric 7033ca95b02SDimitry Andric ++NumFunctions; 7043ca95b02SDimitry Andric 7053ca95b02SDimitry Andric SmallVector<AllocaInst *, 16> StaticAllocas; 7063ca95b02SDimitry Andric SmallVector<AllocaInst *, 4> DynamicAllocas; 7073ca95b02SDimitry Andric SmallVector<Argument *, 4> ByValArguments; 7083ca95b02SDimitry Andric SmallVector<ReturnInst *, 4> Returns; 7093ca95b02SDimitry Andric 7103ca95b02SDimitry Andric // Collect all points where stack gets unwound and needs to be restored 7113ca95b02SDimitry Andric // This is only necessary because the runtime (setjmp and unwind code) is 712d88c1a5aSDimitry Andric // not aware of the unsafe stack and won't unwind/restore it properly. 7133ca95b02SDimitry Andric // To work around this problem without changing the runtime, we insert 7143ca95b02SDimitry Andric // instrumentation to restore the unsafe stack pointer when necessary. 7153ca95b02SDimitry Andric SmallVector<Instruction *, 4> StackRestorePoints; 7163ca95b02SDimitry Andric 7173ca95b02SDimitry Andric // Find all static and dynamic alloca instructions that must be moved to the 7183ca95b02SDimitry Andric // unsafe stack, all return instructions and stack restore points. 7193ca95b02SDimitry Andric findInsts(F, StaticAllocas, DynamicAllocas, ByValArguments, Returns, 7203ca95b02SDimitry Andric StackRestorePoints); 7213ca95b02SDimitry Andric 7223ca95b02SDimitry Andric if (StaticAllocas.empty() && DynamicAllocas.empty() && 7233ca95b02SDimitry Andric ByValArguments.empty() && StackRestorePoints.empty()) 7243ca95b02SDimitry Andric return false; // Nothing to do in this function. 7253ca95b02SDimitry Andric 7263ca95b02SDimitry Andric if (!StaticAllocas.empty() || !DynamicAllocas.empty() || 7273ca95b02SDimitry Andric !ByValArguments.empty()) 7283ca95b02SDimitry Andric ++NumUnsafeStackFunctions; // This function has the unsafe stack. 7293ca95b02SDimitry Andric 7303ca95b02SDimitry Andric if (!StackRestorePoints.empty()) 7313ca95b02SDimitry Andric ++NumUnsafeStackRestorePointsFunctions; 7323ca95b02SDimitry Andric 7333ca95b02SDimitry Andric IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt()); 7345517e702SDimitry Andric UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB); 7353ca95b02SDimitry Andric 7363ca95b02SDimitry Andric // Load the current stack pointer (we'll also use it as a base pointer). 7373ca95b02SDimitry Andric // FIXME: use a dedicated register for it ? 7383ca95b02SDimitry Andric Instruction *BasePointer = 7393ca95b02SDimitry Andric IRB.CreateLoad(UnsafeStackPtr, false, "unsafe_stack_ptr"); 7403ca95b02SDimitry Andric assert(BasePointer->getType() == StackPtrTy); 7413ca95b02SDimitry Andric 7423ca95b02SDimitry Andric AllocaInst *StackGuardSlot = nullptr; 7433ca95b02SDimitry Andric // FIXME: implement weaker forms of stack protector. 7443ca95b02SDimitry Andric if (F.hasFnAttribute(Attribute::StackProtect) || 7453ca95b02SDimitry Andric F.hasFnAttribute(Attribute::StackProtectStrong) || 7463ca95b02SDimitry Andric F.hasFnAttribute(Attribute::StackProtectReq)) { 7473ca95b02SDimitry Andric Value *StackGuard = getStackGuard(IRB, F); 7483ca95b02SDimitry Andric StackGuardSlot = IRB.CreateAlloca(StackPtrTy, nullptr); 7493ca95b02SDimitry Andric IRB.CreateStore(StackGuard, StackGuardSlot); 7503ca95b02SDimitry Andric 7513ca95b02SDimitry Andric for (ReturnInst *RI : Returns) { 7523ca95b02SDimitry Andric IRBuilder<> IRBRet(RI); 7533ca95b02SDimitry Andric checkStackGuard(IRBRet, F, *RI, StackGuardSlot, StackGuard); 7543ca95b02SDimitry Andric } 7553ca95b02SDimitry Andric } 7563ca95b02SDimitry Andric 7573ca95b02SDimitry Andric // The top of the unsafe stack after all unsafe static allocas are 7583ca95b02SDimitry Andric // allocated. 7593ca95b02SDimitry Andric Value *StaticTop = 7603ca95b02SDimitry Andric moveStaticAllocasToUnsafeStack(IRB, F, StaticAllocas, ByValArguments, 7613ca95b02SDimitry Andric Returns, BasePointer, StackGuardSlot); 7623ca95b02SDimitry Andric 7633ca95b02SDimitry Andric // Safe stack object that stores the current unsafe stack top. It is updated 7643ca95b02SDimitry Andric // as unsafe dynamic (non-constant-sized) allocas are allocated and freed. 7653ca95b02SDimitry Andric // This is only needed if we need to restore stack pointer after longjmp 7663ca95b02SDimitry Andric // or exceptions, and we have dynamic allocations. 7673ca95b02SDimitry Andric // FIXME: a better alternative might be to store the unsafe stack pointer 7683ca95b02SDimitry Andric // before setjmp / invoke instructions. 7693ca95b02SDimitry Andric AllocaInst *DynamicTop = createStackRestorePoints( 7703ca95b02SDimitry Andric IRB, F, StackRestorePoints, StaticTop, !DynamicAllocas.empty()); 7713ca95b02SDimitry Andric 7723ca95b02SDimitry Andric // Handle dynamic allocas. 7733ca95b02SDimitry Andric moveDynamicAllocasToUnsafeStack(F, UnsafeStackPtr, DynamicTop, 7743ca95b02SDimitry Andric DynamicAllocas); 7753ca95b02SDimitry Andric 7763ca95b02SDimitry Andric // Restore the unsafe stack pointer before each return. 7773ca95b02SDimitry Andric for (ReturnInst *RI : Returns) { 7783ca95b02SDimitry Andric IRB.SetInsertPoint(RI); 7793ca95b02SDimitry Andric IRB.CreateStore(BasePointer, UnsafeStackPtr); 7803ca95b02SDimitry Andric } 7813ca95b02SDimitry Andric 7823ca95b02SDimitry Andric DEBUG(dbgs() << "[SafeStack] safestack applied\n"); 7833ca95b02SDimitry Andric return true; 7843ca95b02SDimitry Andric } 7853ca95b02SDimitry Andric 7865517e702SDimitry Andric class SafeStackLegacyPass : public FunctionPass { 7872cab237bSDimitry Andric const TargetMachine *TM = nullptr; 7885517e702SDimitry Andric 7895517e702SDimitry Andric public: 7905517e702SDimitry Andric static char ID; // Pass identification, replacement for typeid.. 7912cab237bSDimitry Andric 7922cab237bSDimitry Andric SafeStackLegacyPass() : FunctionPass(ID) { 7935517e702SDimitry Andric initializeSafeStackLegacyPassPass(*PassRegistry::getPassRegistry()); 7945517e702SDimitry Andric } 7955517e702SDimitry Andric 7965517e702SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 797d8866befSDimitry Andric AU.addRequired<TargetPassConfig>(); 7985517e702SDimitry Andric AU.addRequired<TargetLibraryInfoWrapperPass>(); 7995517e702SDimitry Andric AU.addRequired<AssumptionCacheTracker>(); 8005517e702SDimitry Andric } 8015517e702SDimitry Andric 8025517e702SDimitry Andric bool runOnFunction(Function &F) override { 8035517e702SDimitry Andric DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n"); 8045517e702SDimitry Andric 8055517e702SDimitry Andric if (!F.hasFnAttribute(Attribute::SafeStack)) { 8065517e702SDimitry Andric DEBUG(dbgs() << "[SafeStack] safestack is not requested" 8075517e702SDimitry Andric " for this function\n"); 8085517e702SDimitry Andric return false; 8095517e702SDimitry Andric } 8105517e702SDimitry Andric 8115517e702SDimitry Andric if (F.isDeclaration()) { 8125517e702SDimitry Andric DEBUG(dbgs() << "[SafeStack] function definition" 8135517e702SDimitry Andric " is not available\n"); 8145517e702SDimitry Andric return false; 8155517e702SDimitry Andric } 8165517e702SDimitry Andric 817d8866befSDimitry Andric TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>(); 8185517e702SDimitry Andric auto *TL = TM->getSubtargetImpl(F)->getTargetLowering(); 8195517e702SDimitry Andric if (!TL) 8205517e702SDimitry Andric report_fatal_error("TargetLowering instance is required"); 8215517e702SDimitry Andric 8225517e702SDimitry Andric auto *DL = &F.getParent()->getDataLayout(); 8235517e702SDimitry Andric auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); 8245517e702SDimitry Andric auto &ACT = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 8255517e702SDimitry Andric 8265517e702SDimitry Andric // Compute DT and LI only for functions that have the attribute. 8275517e702SDimitry Andric // This is only useful because the legacy pass manager doesn't let us 8285517e702SDimitry Andric // compute analyzes lazily. 8295517e702SDimitry Andric // In the backend pipeline, nothing preserves DT before SafeStack, so we 8305517e702SDimitry Andric // would otherwise always compute it wastefully, even if there is no 8315517e702SDimitry Andric // function with the safestack attribute. 8325517e702SDimitry Andric DominatorTree DT(F); 8335517e702SDimitry Andric LoopInfo LI(DT); 8345517e702SDimitry Andric 8355517e702SDimitry Andric ScalarEvolution SE(F, TLI, ACT, DT, LI); 8365517e702SDimitry Andric 8375517e702SDimitry Andric return SafeStack(F, *TL, *DL, SE).run(); 8385517e702SDimitry Andric } 8395517e702SDimitry Andric }; 8405517e702SDimitry Andric 8412cab237bSDimitry Andric } // end anonymous namespace 8423ca95b02SDimitry Andric 8435517e702SDimitry Andric char SafeStackLegacyPass::ID = 0; 8442cab237bSDimitry Andric 845302affcbSDimitry Andric INITIALIZE_PASS_BEGIN(SafeStackLegacyPass, DEBUG_TYPE, 8463ca95b02SDimitry Andric "Safe Stack instrumentation pass", false, false) 847d8866befSDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 848302affcbSDimitry Andric INITIALIZE_PASS_END(SafeStackLegacyPass, DEBUG_TYPE, 8493ca95b02SDimitry Andric "Safe Stack instrumentation pass", false, false) 8503ca95b02SDimitry Andric 851d8866befSDimitry Andric FunctionPass *llvm::createSafeStackPass() { return new SafeStackLegacyPass(); } 852