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