10b57cec5SDimitry Andric //===- SafeStack.cpp - Safe Stack Insertion -------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass splits the stack into the safe stack (kept as-is for LLVM backend) 100b57cec5SDimitry Andric // and the unsafe stack (explicitly allocated and managed through the runtime 110b57cec5SDimitry Andric // support library). 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric // http://clang.llvm.org/docs/SafeStack.html 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 175f757f3fSDimitry Andric #include "llvm/CodeGen/SafeStack.h" 180b57cec5SDimitry Andric #include "SafeStackLayout.h" 190b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 200b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 220b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 230b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 240b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h" 26fe6060f1SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 270b57cec5SDimitry Andric #include "llvm/Analysis/InlineCost.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 290b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h" 300b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h" 315ffd83dbSDimitry Andric #include "llvm/Analysis/StackLifetime.h" 320b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 360b57cec5SDimitry Andric #include "llvm/IR/Argument.h" 370b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 380b57cec5SDimitry Andric #include "llvm/IR/ConstantRange.h" 390b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 400b57cec5SDimitry Andric #include "llvm/IR/DIBuilder.h" 410b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 420b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 430b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 440b57cec5SDimitry Andric #include "llvm/IR/Function.h" 450b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 460b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h" 470b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 480b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 490b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 500b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 510b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 5281ad6265SDimitry Andric #include "llvm/IR/Metadata.h" 530b57cec5SDimitry Andric #include "llvm/IR/Module.h" 540b57cec5SDimitry Andric #include "llvm/IR/Type.h" 550b57cec5SDimitry Andric #include "llvm/IR/Use.h" 560b57cec5SDimitry Andric #include "llvm/IR/Value.h" 57480093f4SDimitry Andric #include "llvm/InitializePasses.h" 580b57cec5SDimitry Andric #include "llvm/Pass.h" 590b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 600b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 610b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 620b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 630b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 640b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 650b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 660b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 67480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 680b57cec5SDimitry Andric #include <algorithm> 690b57cec5SDimitry Andric #include <cassert> 700b57cec5SDimitry Andric #include <cstdint> 71bdd1243dSDimitry Andric #include <optional> 720b57cec5SDimitry Andric #include <string> 730b57cec5SDimitry Andric #include <utility> 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric using namespace llvm; 760b57cec5SDimitry Andric using namespace llvm::safestack; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric #define DEBUG_TYPE "safe-stack" 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric namespace llvm { 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric STATISTIC(NumFunctions, "Total number of functions"); 830b57cec5SDimitry Andric STATISTIC(NumUnsafeStackFunctions, "Number of functions with unsafe stack"); 840b57cec5SDimitry Andric STATISTIC(NumUnsafeStackRestorePointsFunctions, 850b57cec5SDimitry Andric "Number of functions that use setjmp or exceptions"); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric STATISTIC(NumAllocas, "Total number of allocas"); 880b57cec5SDimitry Andric STATISTIC(NumUnsafeStaticAllocas, "Number of unsafe static allocas"); 890b57cec5SDimitry Andric STATISTIC(NumUnsafeDynamicAllocas, "Number of unsafe dynamic allocas"); 900b57cec5SDimitry Andric STATISTIC(NumUnsafeByValArguments, "Number of unsafe byval arguments"); 910b57cec5SDimitry Andric STATISTIC(NumUnsafeStackRestorePoints, "Number of setjmps and landingpads"); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric } // namespace llvm 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric /// Use __safestack_pointer_address even if the platform has a faster way of 960b57cec5SDimitry Andric /// access safe stack pointer. 970b57cec5SDimitry Andric static cl::opt<bool> 980b57cec5SDimitry Andric SafeStackUsePointerAddress("safestack-use-pointer-address", 990b57cec5SDimitry Andric cl::init(false), cl::Hidden); 1000b57cec5SDimitry Andric 1015ffd83dbSDimitry Andric static cl::opt<bool> ClColoring("safe-stack-coloring", 1025ffd83dbSDimitry Andric cl::desc("enable safe stack coloring"), 10381ad6265SDimitry Andric cl::Hidden, cl::init(true)); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric namespace { 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// The SafeStack pass splits the stack of each function into the safe 1080b57cec5SDimitry Andric /// stack, which is only accessed through memory safe dereferences (as 1090b57cec5SDimitry Andric /// determined statically), and the unsafe stack, which contains all 1100b57cec5SDimitry Andric /// local variables that are accessed in ways that we can't prove to 1110b57cec5SDimitry Andric /// be safe. 1120b57cec5SDimitry Andric class SafeStack { 1130b57cec5SDimitry Andric Function &F; 1140b57cec5SDimitry Andric const TargetLoweringBase &TL; 1150b57cec5SDimitry Andric const DataLayout &DL; 116fe6060f1SDimitry Andric DomTreeUpdater *DTU; 1170b57cec5SDimitry Andric ScalarEvolution &SE; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric Type *StackPtrTy; 1200b57cec5SDimitry Andric Type *IntPtrTy; 1210b57cec5SDimitry Andric Type *Int32Ty; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric Value *UnsafeStackPtr = nullptr; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric /// Unsafe stack alignment. Each stack frame must ensure that the stack is 1260b57cec5SDimitry Andric /// aligned to this value. We need to re-align the unsafe stack if the 1270b57cec5SDimitry Andric /// alignment of any object on the stack exceeds this value. 1280b57cec5SDimitry Andric /// 1290b57cec5SDimitry Andric /// 16 seems like a reasonable upper bound on the alignment of objects that we 1300b57cec5SDimitry Andric /// might expect to appear on the stack on most common targets. 13181ad6265SDimitry Andric static constexpr Align StackAlignment = Align::Constant<16>(); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric /// Return the value of the stack canary. 1340b57cec5SDimitry Andric Value *getStackGuard(IRBuilder<> &IRB, Function &F); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric /// Load stack guard from the frame and check if it has changed. 137e8d8bef9SDimitry Andric void checkStackGuard(IRBuilder<> &IRB, Function &F, Instruction &RI, 1380b57cec5SDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric /// Find all static allocas, dynamic allocas, return instructions and 1410b57cec5SDimitry Andric /// stack restore points (exception unwind blocks and setjmp calls) in the 1420b57cec5SDimitry Andric /// given function and append them to the respective vectors. 1430b57cec5SDimitry Andric void findInsts(Function &F, SmallVectorImpl<AllocaInst *> &StaticAllocas, 1440b57cec5SDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas, 1450b57cec5SDimitry Andric SmallVectorImpl<Argument *> &ByValArguments, 146e8d8bef9SDimitry Andric SmallVectorImpl<Instruction *> &Returns, 1470b57cec5SDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints); 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric /// Calculate the allocation size of a given alloca. Returns 0 if the 1500b57cec5SDimitry Andric /// size can not be statically determined. 1510b57cec5SDimitry Andric uint64_t getStaticAllocaAllocationSize(const AllocaInst* AI); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric /// Allocate space for all static allocas in \p StaticAllocas, 154e8d8bef9SDimitry Andric /// replace allocas with pointers into the unsafe stack. 1550b57cec5SDimitry Andric /// 1560b57cec5SDimitry Andric /// \returns A pointer to the top of the unsafe stack after all unsafe static 1570b57cec5SDimitry Andric /// allocas are allocated. 1580b57cec5SDimitry Andric Value *moveStaticAllocasToUnsafeStack(IRBuilder<> &IRB, Function &F, 1590b57cec5SDimitry Andric ArrayRef<AllocaInst *> StaticAllocas, 1600b57cec5SDimitry Andric ArrayRef<Argument *> ByValArguments, 1610b57cec5SDimitry Andric Instruction *BasePointer, 1620b57cec5SDimitry Andric AllocaInst *StackGuardSlot); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric /// Generate code to restore the stack after all stack restore points 1650b57cec5SDimitry Andric /// in \p StackRestorePoints. 1660b57cec5SDimitry Andric /// 1670b57cec5SDimitry Andric /// \returns A local variable in which to maintain the dynamic top of the 1680b57cec5SDimitry Andric /// unsafe stack if needed. 1690b57cec5SDimitry Andric AllocaInst * 1700b57cec5SDimitry Andric createStackRestorePoints(IRBuilder<> &IRB, Function &F, 1710b57cec5SDimitry Andric ArrayRef<Instruction *> StackRestorePoints, 1720b57cec5SDimitry Andric Value *StaticTop, bool NeedDynamicTop); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric /// Replace all allocas in \p DynamicAllocas with code to allocate 1750b57cec5SDimitry Andric /// space dynamically on the unsafe stack and store the dynamic unsafe stack 1760b57cec5SDimitry Andric /// top to \p DynamicTop if non-null. 1770b57cec5SDimitry Andric void moveDynamicAllocasToUnsafeStack(Function &F, Value *UnsafeStackPtr, 1780b57cec5SDimitry Andric AllocaInst *DynamicTop, 1790b57cec5SDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas); 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric bool IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric bool IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, 1840b57cec5SDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize); 1850b57cec5SDimitry Andric bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr, 1860b57cec5SDimitry Andric uint64_t AllocaSize); 1870b57cec5SDimitry Andric 1885ffd83dbSDimitry Andric bool ShouldInlinePointerAddress(CallInst &CI); 1890b57cec5SDimitry Andric void TryInlinePointerAddress(); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric public: 1920b57cec5SDimitry Andric SafeStack(Function &F, const TargetLoweringBase &TL, const DataLayout &DL, 193fe6060f1SDimitry Andric DomTreeUpdater *DTU, ScalarEvolution &SE) 194fe6060f1SDimitry Andric : F(F), TL(TL), DL(DL), DTU(DTU), SE(SE), 1955f757f3fSDimitry Andric StackPtrTy(PointerType::getUnqual(F.getContext())), 1960b57cec5SDimitry Andric IntPtrTy(DL.getIntPtrType(F.getContext())), 1977a6dacacSDimitry Andric Int32Ty(Type::getInt32Ty(F.getContext())) {} 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // Run the transformation on the associated function. 2000b57cec5SDimitry Andric // Returns whether the function was changed. 2010b57cec5SDimitry Andric bool run(); 2020b57cec5SDimitry Andric }; 2030b57cec5SDimitry Andric 20481ad6265SDimitry Andric constexpr Align SafeStack::StackAlignment; 205349cc55cSDimitry Andric 2060b57cec5SDimitry Andric uint64_t SafeStack::getStaticAllocaAllocationSize(const AllocaInst* AI) { 2070b57cec5SDimitry Andric uint64_t Size = DL.getTypeAllocSize(AI->getAllocatedType()); 2080b57cec5SDimitry Andric if (AI->isArrayAllocation()) { 2090b57cec5SDimitry Andric auto C = dyn_cast<ConstantInt>(AI->getArraySize()); 2100b57cec5SDimitry Andric if (!C) 2110b57cec5SDimitry Andric return 0; 2120b57cec5SDimitry Andric Size *= C->getZExtValue(); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric return Size; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric bool SafeStack::IsAccessSafe(Value *Addr, uint64_t AccessSize, 2180b57cec5SDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize) { 21981ad6265SDimitry Andric const SCEV *AddrExpr = SE.getSCEV(Addr); 22081ad6265SDimitry Andric const auto *Base = dyn_cast<SCEVUnknown>(SE.getPointerBase(AddrExpr)); 22181ad6265SDimitry Andric if (!Base || Base->getValue() != AllocaPtr) { 22281ad6265SDimitry Andric LLVM_DEBUG( 22381ad6265SDimitry Andric dbgs() << "[SafeStack] " 22481ad6265SDimitry Andric << (isa<AllocaInst>(AllocaPtr) ? "Alloca " : "ByValArgument ") 22581ad6265SDimitry Andric << *AllocaPtr << "\n" 22681ad6265SDimitry Andric << "SCEV " << *AddrExpr << " not directly based on alloca\n"); 22781ad6265SDimitry Andric return false; 22881ad6265SDimitry Andric } 2290b57cec5SDimitry Andric 23081ad6265SDimitry Andric const SCEV *Expr = SE.removePointerBase(AddrExpr); 2310b57cec5SDimitry Andric uint64_t BitWidth = SE.getTypeSizeInBits(Expr->getType()); 2320b57cec5SDimitry Andric ConstantRange AccessStartRange = SE.getUnsignedRange(Expr); 2330b57cec5SDimitry Andric ConstantRange SizeRange = 2340b57cec5SDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AccessSize)); 2350b57cec5SDimitry Andric ConstantRange AccessRange = AccessStartRange.add(SizeRange); 2360b57cec5SDimitry Andric ConstantRange AllocaRange = 2370b57cec5SDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AllocaSize)); 2380b57cec5SDimitry Andric bool Safe = AllocaRange.contains(AccessRange); 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric LLVM_DEBUG( 2410b57cec5SDimitry Andric dbgs() << "[SafeStack] " 2420b57cec5SDimitry Andric << (isa<AllocaInst>(AllocaPtr) ? "Alloca " : "ByValArgument ") 2430b57cec5SDimitry Andric << *AllocaPtr << "\n" 2440b57cec5SDimitry Andric << " Access " << *Addr << "\n" 2450b57cec5SDimitry Andric << " SCEV " << *Expr 2460b57cec5SDimitry Andric << " U: " << SE.getUnsignedRange(Expr) 2470b57cec5SDimitry Andric << ", S: " << SE.getSignedRange(Expr) << "\n" 2480b57cec5SDimitry Andric << " Range " << AccessRange << "\n" 2490b57cec5SDimitry Andric << " AllocaRange " << AllocaRange << "\n" 2500b57cec5SDimitry Andric << " " << (Safe ? "safe" : "unsafe") << "\n"); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric return Safe; 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric bool SafeStack::IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, 2560b57cec5SDimitry Andric const Value *AllocaPtr, 2570b57cec5SDimitry Andric uint64_t AllocaSize) { 2580b57cec5SDimitry Andric if (auto MTI = dyn_cast<MemTransferInst>(MI)) { 2590b57cec5SDimitry Andric if (MTI->getRawSource() != U && MTI->getRawDest() != U) 2600b57cec5SDimitry Andric return true; 2610b57cec5SDimitry Andric } else { 2620b57cec5SDimitry Andric if (MI->getRawDest() != U) 2630b57cec5SDimitry Andric return true; 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric const auto *Len = dyn_cast<ConstantInt>(MI->getLength()); 2670b57cec5SDimitry Andric // Non-constant size => unsafe. FIXME: try SCEV getRange. 2680b57cec5SDimitry Andric if (!Len) return false; 2690b57cec5SDimitry Andric return IsAccessSafe(U, Len->getZExtValue(), AllocaPtr, AllocaSize); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric /// Check whether a given allocation must be put on the safe 2730b57cec5SDimitry Andric /// stack or not. The function analyzes all uses of AI and checks whether it is 2740b57cec5SDimitry Andric /// only accessed in a memory safe way (as decided statically). 2750b57cec5SDimitry Andric bool SafeStack::IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize) { 2760b57cec5SDimitry Andric // Go through all uses of this alloca and check whether all accesses to the 2770b57cec5SDimitry Andric // allocated object are statically known to be memory safe and, hence, the 2780b57cec5SDimitry Andric // object can be placed on the safe stack. 2790b57cec5SDimitry Andric SmallPtrSet<const Value *, 16> Visited; 2800b57cec5SDimitry Andric SmallVector<const Value *, 8> WorkList; 2810b57cec5SDimitry Andric WorkList.push_back(AllocaPtr); 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc. 2840b57cec5SDimitry Andric while (!WorkList.empty()) { 2850b57cec5SDimitry Andric const Value *V = WorkList.pop_back_val(); 2860b57cec5SDimitry Andric for (const Use &UI : V->uses()) { 2870b57cec5SDimitry Andric auto I = cast<const Instruction>(UI.getUser()); 2880b57cec5SDimitry Andric assert(V == UI.get()); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric switch (I->getOpcode()) { 2910b57cec5SDimitry Andric case Instruction::Load: 2920b57cec5SDimitry Andric if (!IsAccessSafe(UI, DL.getTypeStoreSize(I->getType()), AllocaPtr, 2930b57cec5SDimitry Andric AllocaSize)) 2940b57cec5SDimitry Andric return false; 2950b57cec5SDimitry Andric break; 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric case Instruction::VAArg: 2980b57cec5SDimitry Andric // "va-arg" from a pointer is safe. 2990b57cec5SDimitry Andric break; 3000b57cec5SDimitry Andric case Instruction::Store: 3010b57cec5SDimitry Andric if (V == I->getOperand(0)) { 3020b57cec5SDimitry Andric // Stored the pointer - conservatively assume it may be unsafe. 3030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 3040b57cec5SDimitry Andric << "[SafeStack] Unsafe alloca: " << *AllocaPtr 3050b57cec5SDimitry Andric << "\n store of address: " << *I << "\n"); 3060b57cec5SDimitry Andric return false; 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric if (!IsAccessSafe(UI, DL.getTypeStoreSize(I->getOperand(0)->getType()), 3100b57cec5SDimitry Andric AllocaPtr, AllocaSize)) 3110b57cec5SDimitry Andric return false; 3120b57cec5SDimitry Andric break; 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric case Instruction::Ret: 3150b57cec5SDimitry Andric // Information leak. 3160b57cec5SDimitry Andric return false; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric case Instruction::Call: 3190b57cec5SDimitry Andric case Instruction::Invoke: { 3205ffd83dbSDimitry Andric const CallBase &CS = *cast<CallBase>(I); 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric if (I->isLifetimeStartOrEnd()) 3230b57cec5SDimitry Andric continue; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { 3260b57cec5SDimitry Andric if (!IsMemIntrinsicSafe(MI, UI, AllocaPtr, AllocaSize)) { 3270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 3280b57cec5SDimitry Andric << "[SafeStack] Unsafe alloca: " << *AllocaPtr 3290b57cec5SDimitry Andric << "\n unsafe memintrinsic: " << *I << "\n"); 3300b57cec5SDimitry Andric return false; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric continue; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric // LLVM 'nocapture' attribute is only set for arguments whose address 3360b57cec5SDimitry Andric // is not stored, passed around, or used in any other non-trivial way. 3370b57cec5SDimitry Andric // We assume that passing a pointer to an object as a 'nocapture 3380b57cec5SDimitry Andric // readnone' argument is safe. 3390b57cec5SDimitry Andric // FIXME: a more precise solution would require an interprocedural 3400b57cec5SDimitry Andric // analysis here, which would look at all uses of an argument inside 3410b57cec5SDimitry Andric // the function being called. 3425ffd83dbSDimitry Andric auto B = CS.arg_begin(), E = CS.arg_end(); 343fcaf7f86SDimitry Andric for (const auto *A = B; A != E; ++A) 3440b57cec5SDimitry Andric if (A->get() == V) 3450b57cec5SDimitry Andric if (!(CS.doesNotCapture(A - B) && (CS.doesNotAccessMemory(A - B) || 3460b57cec5SDimitry Andric CS.doesNotAccessMemory()))) { 3470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr 3480b57cec5SDimitry Andric << "\n unsafe call: " << *I << "\n"); 3490b57cec5SDimitry Andric return false; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric continue; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric default: 3550b57cec5SDimitry Andric if (Visited.insert(I).second) 3560b57cec5SDimitry Andric WorkList.push_back(cast<const Instruction>(I)); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric // All uses of the alloca are safe, we can place it on the safe stack. 3620b57cec5SDimitry Andric return true; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric Value *SafeStack::getStackGuard(IRBuilder<> &IRB, Function &F) { 3660b57cec5SDimitry Andric Value *StackGuardVar = TL.getIRStackGuard(IRB); 367fe6060f1SDimitry Andric Module *M = F.getParent(); 368fe6060f1SDimitry Andric 369fe6060f1SDimitry Andric if (!StackGuardVar) { 370fe6060f1SDimitry Andric TL.insertSSPDeclarations(*M); 371fe6060f1SDimitry Andric return IRB.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackguard)); 372fe6060f1SDimitry Andric } 373fe6060f1SDimitry Andric 3740b57cec5SDimitry Andric return IRB.CreateLoad(StackPtrTy, StackGuardVar, "StackGuard"); 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric void SafeStack::findInsts(Function &F, 3780b57cec5SDimitry Andric SmallVectorImpl<AllocaInst *> &StaticAllocas, 3790b57cec5SDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas, 3800b57cec5SDimitry Andric SmallVectorImpl<Argument *> &ByValArguments, 381e8d8bef9SDimitry Andric SmallVectorImpl<Instruction *> &Returns, 3820b57cec5SDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints) { 3830b57cec5SDimitry Andric for (Instruction &I : instructions(&F)) { 3840b57cec5SDimitry Andric if (auto AI = dyn_cast<AllocaInst>(&I)) { 3850b57cec5SDimitry Andric ++NumAllocas; 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 3880b57cec5SDimitry Andric if (IsSafeStackAlloca(AI, Size)) 3890b57cec5SDimitry Andric continue; 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric if (AI->isStaticAlloca()) { 3920b57cec5SDimitry Andric ++NumUnsafeStaticAllocas; 3930b57cec5SDimitry Andric StaticAllocas.push_back(AI); 3940b57cec5SDimitry Andric } else { 3950b57cec5SDimitry Andric ++NumUnsafeDynamicAllocas; 3960b57cec5SDimitry Andric DynamicAllocas.push_back(AI); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric } else if (auto RI = dyn_cast<ReturnInst>(&I)) { 399e8d8bef9SDimitry Andric if (CallInst *CI = I.getParent()->getTerminatingMustTailCall()) 400e8d8bef9SDimitry Andric Returns.push_back(CI); 401e8d8bef9SDimitry Andric else 4020b57cec5SDimitry Andric Returns.push_back(RI); 4030b57cec5SDimitry Andric } else if (auto CI = dyn_cast<CallInst>(&I)) { 4040b57cec5SDimitry Andric // setjmps require stack restore. 4050b57cec5SDimitry Andric if (CI->getCalledFunction() && CI->canReturnTwice()) 4060b57cec5SDimitry Andric StackRestorePoints.push_back(CI); 4070b57cec5SDimitry Andric } else if (auto LP = dyn_cast<LandingPadInst>(&I)) { 4080b57cec5SDimitry Andric // Exception landing pads require stack restore. 4090b57cec5SDimitry Andric StackRestorePoints.push_back(LP); 4100b57cec5SDimitry Andric } else if (auto II = dyn_cast<IntrinsicInst>(&I)) { 4110b57cec5SDimitry Andric if (II->getIntrinsicID() == Intrinsic::gcroot) 4120b57cec5SDimitry Andric report_fatal_error( 4130b57cec5SDimitry Andric "gcroot intrinsic not compatible with safestack attribute"); 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric for (Argument &Arg : F.args()) { 4170b57cec5SDimitry Andric if (!Arg.hasByValAttr()) 4180b57cec5SDimitry Andric continue; 419fe6060f1SDimitry Andric uint64_t Size = DL.getTypeStoreSize(Arg.getParamByValType()); 4200b57cec5SDimitry Andric if (IsSafeStackAlloca(&Arg, Size)) 4210b57cec5SDimitry Andric continue; 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric ++NumUnsafeByValArguments; 4240b57cec5SDimitry Andric ByValArguments.push_back(&Arg); 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric AllocaInst * 4290b57cec5SDimitry Andric SafeStack::createStackRestorePoints(IRBuilder<> &IRB, Function &F, 4300b57cec5SDimitry Andric ArrayRef<Instruction *> StackRestorePoints, 4310b57cec5SDimitry Andric Value *StaticTop, bool NeedDynamicTop) { 4320b57cec5SDimitry Andric assert(StaticTop && "The stack top isn't set."); 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric if (StackRestorePoints.empty()) 4350b57cec5SDimitry Andric return nullptr; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric // We need the current value of the shadow stack pointer to restore 4380b57cec5SDimitry Andric // after longjmp or exception catching. 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric // FIXME: On some platforms this could be handled by the longjmp/exception 4410b57cec5SDimitry Andric // runtime itself. 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric AllocaInst *DynamicTop = nullptr; 4440b57cec5SDimitry Andric if (NeedDynamicTop) { 4450b57cec5SDimitry Andric // If we also have dynamic alloca's, the stack pointer value changes 4460b57cec5SDimitry Andric // throughout the function. For now we store it in an alloca. 4470b57cec5SDimitry Andric DynamicTop = IRB.CreateAlloca(StackPtrTy, /*ArraySize=*/nullptr, 4480b57cec5SDimitry Andric "unsafe_stack_dynamic_ptr"); 4490b57cec5SDimitry Andric IRB.CreateStore(StaticTop, DynamicTop); 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric // Restore current stack pointer after longjmp/exception catch. 4530b57cec5SDimitry Andric for (Instruction *I : StackRestorePoints) { 4540b57cec5SDimitry Andric ++NumUnsafeStackRestorePoints; 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric IRB.SetInsertPoint(I->getNextNode()); 4570b57cec5SDimitry Andric Value *CurrentTop = 4580b57cec5SDimitry Andric DynamicTop ? IRB.CreateLoad(StackPtrTy, DynamicTop) : StaticTop; 4590b57cec5SDimitry Andric IRB.CreateStore(CurrentTop, UnsafeStackPtr); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric return DynamicTop; 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 465e8d8bef9SDimitry Andric void SafeStack::checkStackGuard(IRBuilder<> &IRB, Function &F, Instruction &RI, 4660b57cec5SDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard) { 4670b57cec5SDimitry Andric Value *V = IRB.CreateLoad(StackPtrTy, StackGuardSlot); 4680b57cec5SDimitry Andric Value *Cmp = IRB.CreateICmpNE(StackGuard, V); 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric auto SuccessProb = BranchProbabilityInfo::getBranchProbStackProtector(true); 4710b57cec5SDimitry Andric auto FailureProb = BranchProbabilityInfo::getBranchProbStackProtector(false); 4720b57cec5SDimitry Andric MDNode *Weights = MDBuilder(F.getContext()) 4730b57cec5SDimitry Andric .createBranchWeights(SuccessProb.getNumerator(), 4740b57cec5SDimitry Andric FailureProb.getNumerator()); 4750b57cec5SDimitry Andric Instruction *CheckTerm = 476fe6060f1SDimitry Andric SplitBlockAndInsertIfThen(Cmp, &RI, /* Unreachable */ true, Weights, DTU); 4770b57cec5SDimitry Andric IRBuilder<> IRBFail(CheckTerm); 4780b57cec5SDimitry Andric // FIXME: respect -fsanitize-trap / -ftrap-function here? 4790b57cec5SDimitry Andric FunctionCallee StackChkFail = 4800b57cec5SDimitry Andric F.getParent()->getOrInsertFunction("__stack_chk_fail", IRB.getVoidTy()); 4810b57cec5SDimitry Andric IRBFail.CreateCall(StackChkFail, {}); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric /// We explicitly compute and set the unsafe stack layout for all unsafe 4850b57cec5SDimitry Andric /// static alloca instructions. We save the unsafe "base pointer" in the 4860b57cec5SDimitry Andric /// prologue into a local variable and restore it in the epilogue. 4870b57cec5SDimitry Andric Value *SafeStack::moveStaticAllocasToUnsafeStack( 4880b57cec5SDimitry Andric IRBuilder<> &IRB, Function &F, ArrayRef<AllocaInst *> StaticAllocas, 489e8d8bef9SDimitry Andric ArrayRef<Argument *> ByValArguments, Instruction *BasePointer, 490e8d8bef9SDimitry Andric AllocaInst *StackGuardSlot) { 4910b57cec5SDimitry Andric if (StaticAllocas.empty() && ByValArguments.empty()) 4920b57cec5SDimitry Andric return BasePointer; 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric DIBuilder DIB(*F.getParent()); 4950b57cec5SDimitry Andric 4965ffd83dbSDimitry Andric StackLifetime SSC(F, StaticAllocas, StackLifetime::LivenessType::May); 4975ffd83dbSDimitry Andric static const StackLifetime::LiveRange NoColoringRange(1, true); 4985ffd83dbSDimitry Andric if (ClColoring) 4990b57cec5SDimitry Andric SSC.run(); 5005ffd83dbSDimitry Andric 501fcaf7f86SDimitry Andric for (const auto *I : SSC.getMarkers()) { 5025ffd83dbSDimitry Andric auto *Op = dyn_cast<Instruction>(I->getOperand(1)); 5035ffd83dbSDimitry Andric const_cast<IntrinsicInst *>(I)->eraseFromParent(); 5045ffd83dbSDimitry Andric // Remove the operand bitcast, too, if it has no more uses left. 5055ffd83dbSDimitry Andric if (Op && Op->use_empty()) 5065ffd83dbSDimitry Andric Op->eraseFromParent(); 5075ffd83dbSDimitry Andric } 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric // Unsafe stack always grows down. 5100b57cec5SDimitry Andric StackLayout SSL(StackAlignment); 5110b57cec5SDimitry Andric if (StackGuardSlot) { 5120b57cec5SDimitry Andric Type *Ty = StackGuardSlot->getAllocatedType(); 5130eae32dcSDimitry Andric Align Align = std::max(DL.getPrefTypeAlign(Ty), StackGuardSlot->getAlign()); 5140b57cec5SDimitry Andric SSL.addObject(StackGuardSlot, getStaticAllocaAllocationSize(StackGuardSlot), 5150b57cec5SDimitry Andric Align, SSC.getFullLiveRange()); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric for (Argument *Arg : ByValArguments) { 519fe6060f1SDimitry Andric Type *Ty = Arg->getParamByValType(); 5200b57cec5SDimitry Andric uint64_t Size = DL.getTypeStoreSize(Ty); 5210b57cec5SDimitry Andric if (Size == 0) 5220b57cec5SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric // Ensure the object is properly aligned. 5250eae32dcSDimitry Andric Align Align = DL.getPrefTypeAlign(Ty); 5260eae32dcSDimitry Andric if (auto A = Arg->getParamAlign()) 5270eae32dcSDimitry Andric Align = std::max(Align, *A); 5280b57cec5SDimitry Andric SSL.addObject(Arg, Size, Align, SSC.getFullLiveRange()); 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric for (AllocaInst *AI : StaticAllocas) { 5320b57cec5SDimitry Andric Type *Ty = AI->getAllocatedType(); 5330b57cec5SDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI); 5340b57cec5SDimitry Andric if (Size == 0) 5350b57cec5SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric // Ensure the object is properly aligned. 5380eae32dcSDimitry Andric Align Align = std::max(DL.getPrefTypeAlign(Ty), AI->getAlign()); 5390b57cec5SDimitry Andric 5405ffd83dbSDimitry Andric SSL.addObject(AI, Size, Align, 5415ffd83dbSDimitry Andric ClColoring ? SSC.getLiveRange(AI) : NoColoringRange); 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric SSL.computeLayout(); 5450eae32dcSDimitry Andric Align FrameAlignment = SSL.getFrameAlignment(); 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric // FIXME: tell SSL that we start at a less-then-MaxAlignment aligned location 5480b57cec5SDimitry Andric // (AlignmentSkew). 5490b57cec5SDimitry Andric if (FrameAlignment > StackAlignment) { 5500b57cec5SDimitry Andric // Re-align the base pointer according to the max requested alignment. 5510b57cec5SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 5520b57cec5SDimitry Andric BasePointer = cast<Instruction>(IRB.CreateIntToPtr( 5530eae32dcSDimitry Andric IRB.CreateAnd( 5540eae32dcSDimitry Andric IRB.CreatePtrToInt(BasePointer, IntPtrTy), 5550eae32dcSDimitry Andric ConstantInt::get(IntPtrTy, ~(FrameAlignment.value() - 1))), 5560b57cec5SDimitry Andric StackPtrTy)); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric if (StackGuardSlot) { 5620b57cec5SDimitry Andric unsigned Offset = SSL.getObjectOffset(StackGuardSlot); 5637a6dacacSDimitry Andric Value *Off = 5647a6dacacSDimitry Andric IRB.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -Offset)); 5650b57cec5SDimitry Andric Value *NewAI = 5660b57cec5SDimitry Andric IRB.CreateBitCast(Off, StackGuardSlot->getType(), "StackGuardSlot"); 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric // Replace alloc with the new location. 5690b57cec5SDimitry Andric StackGuardSlot->replaceAllUsesWith(NewAI); 5700b57cec5SDimitry Andric StackGuardSlot->eraseFromParent(); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric for (Argument *Arg : ByValArguments) { 5740b57cec5SDimitry Andric unsigned Offset = SSL.getObjectOffset(Arg); 575480093f4SDimitry Andric MaybeAlign Align(SSL.getObjectAlignment(Arg)); 576fe6060f1SDimitry Andric Type *Ty = Arg->getParamByValType(); 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric uint64_t Size = DL.getTypeStoreSize(Ty); 5790b57cec5SDimitry Andric if (Size == 0) 5800b57cec5SDimitry Andric Size = 1; // Don't create zero-sized stack objects. 5810b57cec5SDimitry Andric 5827a6dacacSDimitry Andric Value *Off = 5837a6dacacSDimitry Andric IRB.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -Offset)); 5840b57cec5SDimitry Andric Value *NewArg = IRB.CreateBitCast(Off, Arg->getType(), 5850b57cec5SDimitry Andric Arg->getName() + ".unsafe-byval"); 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric // Replace alloc with the new location. 5885ffd83dbSDimitry Andric replaceDbgDeclare(Arg, BasePointer, DIB, DIExpression::ApplyOffset, 5895ffd83dbSDimitry Andric -Offset); 5900b57cec5SDimitry Andric Arg->replaceAllUsesWith(NewArg); 5910b57cec5SDimitry Andric IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode()); 592480093f4SDimitry Andric IRB.CreateMemCpy(Off, Align, Arg, Arg->getParamAlign(), Size); 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric // Allocate space for every unsafe static AllocaInst on the unsafe stack. 5960b57cec5SDimitry Andric for (AllocaInst *AI : StaticAllocas) { 5970b57cec5SDimitry Andric IRB.SetInsertPoint(AI); 5980b57cec5SDimitry Andric unsigned Offset = SSL.getObjectOffset(AI); 5990b57cec5SDimitry Andric 6005ffd83dbSDimitry Andric replaceDbgDeclare(AI, BasePointer, DIB, DIExpression::ApplyOffset, -Offset); 6010b57cec5SDimitry Andric replaceDbgValueForAlloca(AI, BasePointer, DIB, -Offset); 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric // Replace uses of the alloca with the new location. 6040b57cec5SDimitry Andric // Insert address calculation close to each use to work around PR27844. 6050b57cec5SDimitry Andric std::string Name = std::string(AI->getName()) + ".unsafe"; 6060b57cec5SDimitry Andric while (!AI->use_empty()) { 6070b57cec5SDimitry Andric Use &U = *AI->use_begin(); 6080b57cec5SDimitry Andric Instruction *User = cast<Instruction>(U.getUser()); 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric Instruction *InsertBefore; 6110b57cec5SDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User)) 6120b57cec5SDimitry Andric InsertBefore = PHI->getIncomingBlock(U)->getTerminator(); 6130b57cec5SDimitry Andric else 6140b57cec5SDimitry Andric InsertBefore = User; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric IRBuilder<> IRBUser(InsertBefore); 6177a6dacacSDimitry Andric Value *Off = 6187a6dacacSDimitry Andric IRBUser.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -Offset)); 6190b57cec5SDimitry Andric Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name); 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User)) 6220b57cec5SDimitry Andric // PHI nodes may have multiple incoming edges from the same BB (why??), 6230b57cec5SDimitry Andric // all must be updated at once with the same incoming value. 6240b57cec5SDimitry Andric PHI->setIncomingValueForBlock(PHI->getIncomingBlock(U), Replacement); 6250b57cec5SDimitry Andric else 6260b57cec5SDimitry Andric U.set(Replacement); 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric AI->eraseFromParent(); 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric // Re-align BasePointer so that our callees would see it aligned as 6330b57cec5SDimitry Andric // expected. 6340b57cec5SDimitry Andric // FIXME: no need to update BasePointer in leaf functions. 6350b57cec5SDimitry Andric unsigned FrameSize = alignTo(SSL.getFrameSize(), StackAlignment); 6360b57cec5SDimitry Andric 63781ad6265SDimitry Andric MDBuilder MDB(F.getContext()); 63881ad6265SDimitry Andric SmallVector<Metadata *, 2> Data; 63981ad6265SDimitry Andric Data.push_back(MDB.createString("unsafe-stack-size")); 64081ad6265SDimitry Andric Data.push_back(MDB.createConstant(ConstantInt::get(Int32Ty, FrameSize))); 64181ad6265SDimitry Andric MDNode *MD = MDTuple::get(F.getContext(), Data); 64281ad6265SDimitry Andric F.setMetadata(LLVMContext::MD_annotation, MD); 64381ad6265SDimitry Andric 6440b57cec5SDimitry Andric // Update shadow stack pointer in the function epilogue. 6450b57cec5SDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode()); 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric Value *StaticTop = 6487a6dacacSDimitry Andric IRB.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -FrameSize), 6490b57cec5SDimitry Andric "unsafe_stack_static_top"); 6500b57cec5SDimitry Andric IRB.CreateStore(StaticTop, UnsafeStackPtr); 6510b57cec5SDimitry Andric return StaticTop; 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric void SafeStack::moveDynamicAllocasToUnsafeStack( 6550b57cec5SDimitry Andric Function &F, Value *UnsafeStackPtr, AllocaInst *DynamicTop, 6560b57cec5SDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas) { 6570b57cec5SDimitry Andric DIBuilder DIB(*F.getParent()); 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric for (AllocaInst *AI : DynamicAllocas) { 6600b57cec5SDimitry Andric IRBuilder<> IRB(AI); 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric // Compute the new SP value (after AI). 6630b57cec5SDimitry Andric Value *ArraySize = AI->getArraySize(); 6640b57cec5SDimitry Andric if (ArraySize->getType() != IntPtrTy) 6650b57cec5SDimitry Andric ArraySize = IRB.CreateIntCast(ArraySize, IntPtrTy, false); 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric Type *Ty = AI->getAllocatedType(); 6680b57cec5SDimitry Andric uint64_t TySize = DL.getTypeAllocSize(Ty); 6690b57cec5SDimitry Andric Value *Size = IRB.CreateMul(ArraySize, ConstantInt::get(IntPtrTy, TySize)); 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric Value *SP = IRB.CreatePtrToInt(IRB.CreateLoad(StackPtrTy, UnsafeStackPtr), 6720b57cec5SDimitry Andric IntPtrTy); 6730b57cec5SDimitry Andric SP = IRB.CreateSub(SP, Size); 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric // Align the SP value to satisfy the AllocaInst, type and stack alignments. 67681ad6265SDimitry Andric auto Align = std::max(std::max(DL.getPrefTypeAlign(Ty), AI->getAlign()), 677349cc55cSDimitry Andric StackAlignment); 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric Value *NewTop = IRB.CreateIntToPtr( 68081ad6265SDimitry Andric IRB.CreateAnd(SP, 68181ad6265SDimitry Andric ConstantInt::get(IntPtrTy, ~uint64_t(Align.value() - 1))), 6820b57cec5SDimitry Andric StackPtrTy); 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric // Save the stack pointer. 6850b57cec5SDimitry Andric IRB.CreateStore(NewTop, UnsafeStackPtr); 6860b57cec5SDimitry Andric if (DynamicTop) 6870b57cec5SDimitry Andric IRB.CreateStore(NewTop, DynamicTop); 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric Value *NewAI = IRB.CreatePointerCast(NewTop, AI->getType()); 6900b57cec5SDimitry Andric if (AI->hasName() && isa<Instruction>(NewAI)) 6910b57cec5SDimitry Andric NewAI->takeName(AI); 6920b57cec5SDimitry Andric 6935ffd83dbSDimitry Andric replaceDbgDeclare(AI, NewAI, DIB, DIExpression::ApplyOffset, 0); 6940b57cec5SDimitry Andric AI->replaceAllUsesWith(NewAI); 6950b57cec5SDimitry Andric AI->eraseFromParent(); 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric if (!DynamicAllocas.empty()) { 6990b57cec5SDimitry Andric // Now go through the instructions again, replacing stacksave/stackrestore. 700349cc55cSDimitry Andric for (Instruction &I : llvm::make_early_inc_range(instructions(&F))) { 701349cc55cSDimitry Andric auto *II = dyn_cast<IntrinsicInst>(&I); 7020b57cec5SDimitry Andric if (!II) 7030b57cec5SDimitry Andric continue; 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric if (II->getIntrinsicID() == Intrinsic::stacksave) { 7060b57cec5SDimitry Andric IRBuilder<> IRB(II); 7070b57cec5SDimitry Andric Instruction *LI = IRB.CreateLoad(StackPtrTy, UnsafeStackPtr); 7080b57cec5SDimitry Andric LI->takeName(II); 7090b57cec5SDimitry Andric II->replaceAllUsesWith(LI); 7100b57cec5SDimitry Andric II->eraseFromParent(); 7110b57cec5SDimitry Andric } else if (II->getIntrinsicID() == Intrinsic::stackrestore) { 7120b57cec5SDimitry Andric IRBuilder<> IRB(II); 7130b57cec5SDimitry Andric Instruction *SI = IRB.CreateStore(II->getArgOperand(0), UnsafeStackPtr); 7140b57cec5SDimitry Andric SI->takeName(II); 7150b57cec5SDimitry Andric assert(II->use_empty()); 7160b57cec5SDimitry Andric II->eraseFromParent(); 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric 7225ffd83dbSDimitry Andric bool SafeStack::ShouldInlinePointerAddress(CallInst &CI) { 7235ffd83dbSDimitry Andric Function *Callee = CI.getCalledFunction(); 7245ffd83dbSDimitry Andric if (CI.hasFnAttr(Attribute::AlwaysInline) && 7255ffd83dbSDimitry Andric isInlineViable(*Callee).isSuccess()) 7260b57cec5SDimitry Andric return true; 7270b57cec5SDimitry Andric if (Callee->isInterposable() || Callee->hasFnAttribute(Attribute::NoInline) || 7285ffd83dbSDimitry Andric CI.isNoInline()) 7290b57cec5SDimitry Andric return false; 7300b57cec5SDimitry Andric return true; 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric void SafeStack::TryInlinePointerAddress() { 7345ffd83dbSDimitry Andric auto *CI = dyn_cast<CallInst>(UnsafeStackPtr); 7355ffd83dbSDimitry Andric if (!CI) 7360b57cec5SDimitry Andric return; 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric if(F.hasOptNone()) 7390b57cec5SDimitry Andric return; 7400b57cec5SDimitry Andric 7415ffd83dbSDimitry Andric Function *Callee = CI->getCalledFunction(); 7420b57cec5SDimitry Andric if (!Callee || Callee->isDeclaration()) 7430b57cec5SDimitry Andric return; 7440b57cec5SDimitry Andric 7455ffd83dbSDimitry Andric if (!ShouldInlinePointerAddress(*CI)) 7460b57cec5SDimitry Andric return; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric InlineFunctionInfo IFI; 7495ffd83dbSDimitry Andric InlineFunction(*CI, IFI); 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric bool SafeStack::run() { 7530b57cec5SDimitry Andric assert(F.hasFnAttribute(Attribute::SafeStack) && 7540b57cec5SDimitry Andric "Can't run SafeStack on a function without the attribute"); 7550b57cec5SDimitry Andric assert(!F.isDeclaration() && "Can't run SafeStack on a function declaration"); 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric ++NumFunctions; 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric SmallVector<AllocaInst *, 16> StaticAllocas; 7600b57cec5SDimitry Andric SmallVector<AllocaInst *, 4> DynamicAllocas; 7610b57cec5SDimitry Andric SmallVector<Argument *, 4> ByValArguments; 762e8d8bef9SDimitry Andric SmallVector<Instruction *, 4> Returns; 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric // Collect all points where stack gets unwound and needs to be restored 7650b57cec5SDimitry Andric // This is only necessary because the runtime (setjmp and unwind code) is 7660b57cec5SDimitry Andric // not aware of the unsafe stack and won't unwind/restore it properly. 7670b57cec5SDimitry Andric // To work around this problem without changing the runtime, we insert 7680b57cec5SDimitry Andric // instrumentation to restore the unsafe stack pointer when necessary. 7690b57cec5SDimitry Andric SmallVector<Instruction *, 4> StackRestorePoints; 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric // Find all static and dynamic alloca instructions that must be moved to the 7720b57cec5SDimitry Andric // unsafe stack, all return instructions and stack restore points. 7730b57cec5SDimitry Andric findInsts(F, StaticAllocas, DynamicAllocas, ByValArguments, Returns, 7740b57cec5SDimitry Andric StackRestorePoints); 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric if (StaticAllocas.empty() && DynamicAllocas.empty() && 7770b57cec5SDimitry Andric ByValArguments.empty() && StackRestorePoints.empty()) 7780b57cec5SDimitry Andric return false; // Nothing to do in this function. 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric if (!StaticAllocas.empty() || !DynamicAllocas.empty() || 7810b57cec5SDimitry Andric !ByValArguments.empty()) 7820b57cec5SDimitry Andric ++NumUnsafeStackFunctions; // This function has the unsafe stack. 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric if (!StackRestorePoints.empty()) 7850b57cec5SDimitry Andric ++NumUnsafeStackRestorePointsFunctions; 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt()); 7880b57cec5SDimitry Andric // Calls must always have a debug location, or else inlining breaks. So 7890b57cec5SDimitry Andric // we explicitly set a artificial debug location here. 7900b57cec5SDimitry Andric if (DISubprogram *SP = F.getSubprogram()) 791e8d8bef9SDimitry Andric IRB.SetCurrentDebugLocation( 792e8d8bef9SDimitry Andric DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP)); 7930b57cec5SDimitry Andric if (SafeStackUsePointerAddress) { 7940b57cec5SDimitry Andric FunctionCallee Fn = F.getParent()->getOrInsertFunction( 7955f757f3fSDimitry Andric "__safestack_pointer_address", IRB.getPtrTy(0)); 7960b57cec5SDimitry Andric UnsafeStackPtr = IRB.CreateCall(Fn); 7970b57cec5SDimitry Andric } else { 7980b57cec5SDimitry Andric UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB); 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric // Load the current stack pointer (we'll also use it as a base pointer). 8020b57cec5SDimitry Andric // FIXME: use a dedicated register for it ? 8030b57cec5SDimitry Andric Instruction *BasePointer = 8040b57cec5SDimitry Andric IRB.CreateLoad(StackPtrTy, UnsafeStackPtr, false, "unsafe_stack_ptr"); 8050b57cec5SDimitry Andric assert(BasePointer->getType() == StackPtrTy); 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric AllocaInst *StackGuardSlot = nullptr; 8080b57cec5SDimitry Andric // FIXME: implement weaker forms of stack protector. 8090b57cec5SDimitry Andric if (F.hasFnAttribute(Attribute::StackProtect) || 8100b57cec5SDimitry Andric F.hasFnAttribute(Attribute::StackProtectStrong) || 8110b57cec5SDimitry Andric F.hasFnAttribute(Attribute::StackProtectReq)) { 8120b57cec5SDimitry Andric Value *StackGuard = getStackGuard(IRB, F); 8130b57cec5SDimitry Andric StackGuardSlot = IRB.CreateAlloca(StackPtrTy, nullptr); 8140b57cec5SDimitry Andric IRB.CreateStore(StackGuard, StackGuardSlot); 8150b57cec5SDimitry Andric 816e8d8bef9SDimitry Andric for (Instruction *RI : Returns) { 8170b57cec5SDimitry Andric IRBuilder<> IRBRet(RI); 8180b57cec5SDimitry Andric checkStackGuard(IRBRet, F, *RI, StackGuardSlot, StackGuard); 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric } 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric // The top of the unsafe stack after all unsafe static allocas are 8230b57cec5SDimitry Andric // allocated. 824e8d8bef9SDimitry Andric Value *StaticTop = moveStaticAllocasToUnsafeStack( 825e8d8bef9SDimitry Andric IRB, F, StaticAllocas, ByValArguments, BasePointer, StackGuardSlot); 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric // Safe stack object that stores the current unsafe stack top. It is updated 8280b57cec5SDimitry Andric // as unsafe dynamic (non-constant-sized) allocas are allocated and freed. 8290b57cec5SDimitry Andric // This is only needed if we need to restore stack pointer after longjmp 8300b57cec5SDimitry Andric // or exceptions, and we have dynamic allocations. 8310b57cec5SDimitry Andric // FIXME: a better alternative might be to store the unsafe stack pointer 8320b57cec5SDimitry Andric // before setjmp / invoke instructions. 8330b57cec5SDimitry Andric AllocaInst *DynamicTop = createStackRestorePoints( 8340b57cec5SDimitry Andric IRB, F, StackRestorePoints, StaticTop, !DynamicAllocas.empty()); 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric // Handle dynamic allocas. 8370b57cec5SDimitry Andric moveDynamicAllocasToUnsafeStack(F, UnsafeStackPtr, DynamicTop, 8380b57cec5SDimitry Andric DynamicAllocas); 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric // Restore the unsafe stack pointer before each return. 841e8d8bef9SDimitry Andric for (Instruction *RI : Returns) { 8420b57cec5SDimitry Andric IRB.SetInsertPoint(RI); 8430b57cec5SDimitry Andric IRB.CreateStore(BasePointer, UnsafeStackPtr); 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric TryInlinePointerAddress(); 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] safestack applied\n"); 8490b57cec5SDimitry Andric return true; 8500b57cec5SDimitry Andric } 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric class SafeStackLegacyPass : public FunctionPass { 8530b57cec5SDimitry Andric const TargetMachine *TM = nullptr; 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric public: 8560b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid.. 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric SafeStackLegacyPass() : FunctionPass(ID) { 8590b57cec5SDimitry Andric initializeSafeStackLegacyPassPass(*PassRegistry::getPassRegistry()); 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 8630b57cec5SDimitry Andric AU.addRequired<TargetPassConfig>(); 8640b57cec5SDimitry Andric AU.addRequired<TargetLibraryInfoWrapperPass>(); 8650b57cec5SDimitry Andric AU.addRequired<AssumptionCacheTracker>(); 866fe6060f1SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric bool runOnFunction(Function &F) override { 8700b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n"); 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric if (!F.hasFnAttribute(Attribute::SafeStack)) { 8730b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] safestack is not requested" 8740b57cec5SDimitry Andric " for this function\n"); 8750b57cec5SDimitry Andric return false; 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric if (F.isDeclaration()) { 8790b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] function definition" 8800b57cec5SDimitry Andric " is not available\n"); 8810b57cec5SDimitry Andric return false; 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>(); 8850b57cec5SDimitry Andric auto *TL = TM->getSubtargetImpl(F)->getTargetLowering(); 8860b57cec5SDimitry Andric if (!TL) 8870b57cec5SDimitry Andric report_fatal_error("TargetLowering instance is required"); 8880b57cec5SDimitry Andric 889*0fca6ea1SDimitry Andric auto *DL = &F.getDataLayout(); 8908bcb0991SDimitry Andric auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); 8910b57cec5SDimitry Andric auto &ACT = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric // Compute DT and LI only for functions that have the attribute. 8940b57cec5SDimitry Andric // This is only useful because the legacy pass manager doesn't let us 8950b57cec5SDimitry Andric // compute analyzes lazily. 8960b57cec5SDimitry Andric 897fe6060f1SDimitry Andric DominatorTree *DT; 898fe6060f1SDimitry Andric bool ShouldPreserveDominatorTree; 899bdd1243dSDimitry Andric std::optional<DominatorTree> LazilyComputedDomTree; 9000b57cec5SDimitry Andric 901fe6060f1SDimitry Andric // Do we already have a DominatorTree avaliable from the previous pass? 902fe6060f1SDimitry Andric // Note that we should *NOT* require it, to avoid the case where we end up 903fe6060f1SDimitry Andric // not needing it, but the legacy PM would have computed it for us anyways. 904fe6060f1SDimitry Andric if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) { 905fe6060f1SDimitry Andric DT = &DTWP->getDomTree(); 906fe6060f1SDimitry Andric ShouldPreserveDominatorTree = true; 907fe6060f1SDimitry Andric } else { 908fe6060f1SDimitry Andric // Otherwise, we need to compute it. 909fe6060f1SDimitry Andric LazilyComputedDomTree.emplace(F); 910bdd1243dSDimitry Andric DT = &*LazilyComputedDomTree; 911fe6060f1SDimitry Andric ShouldPreserveDominatorTree = false; 912fe6060f1SDimitry Andric } 913fe6060f1SDimitry Andric 914fe6060f1SDimitry Andric // Likewise, lazily compute loop info. 915fe6060f1SDimitry Andric LoopInfo LI(*DT); 916fe6060f1SDimitry Andric 917fe6060f1SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); 918fe6060f1SDimitry Andric 919fe6060f1SDimitry Andric ScalarEvolution SE(F, TLI, ACT, *DT, LI); 920fe6060f1SDimitry Andric 921fe6060f1SDimitry Andric return SafeStack(F, *TL, *DL, ShouldPreserveDominatorTree ? &DTU : nullptr, 922fe6060f1SDimitry Andric SE) 923fe6060f1SDimitry Andric .run(); 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric }; 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric } // end anonymous namespace 9280b57cec5SDimitry Andric 9295f757f3fSDimitry Andric PreservedAnalyses SafeStackPass::run(Function &F, 9305f757f3fSDimitry Andric FunctionAnalysisManager &FAM) { 9315f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n"); 9325f757f3fSDimitry Andric 9335f757f3fSDimitry Andric if (!F.hasFnAttribute(Attribute::SafeStack)) { 9345f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] safestack is not requested" 9355f757f3fSDimitry Andric " for this function\n"); 9365f757f3fSDimitry Andric return PreservedAnalyses::all(); 9375f757f3fSDimitry Andric } 9385f757f3fSDimitry Andric 9395f757f3fSDimitry Andric if (F.isDeclaration()) { 9405f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] function definition" 9415f757f3fSDimitry Andric " is not available\n"); 9425f757f3fSDimitry Andric return PreservedAnalyses::all(); 9435f757f3fSDimitry Andric } 9445f757f3fSDimitry Andric 9455f757f3fSDimitry Andric auto *TL = TM->getSubtargetImpl(F)->getTargetLowering(); 9465f757f3fSDimitry Andric if (!TL) 9475f757f3fSDimitry Andric report_fatal_error("TargetLowering instance is required"); 9485f757f3fSDimitry Andric 949*0fca6ea1SDimitry Andric auto &DL = F.getDataLayout(); 9505f757f3fSDimitry Andric 9515f757f3fSDimitry Andric // preserve DominatorTree 9525f757f3fSDimitry Andric auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); 9535f757f3fSDimitry Andric auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F); 9545f757f3fSDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); 9555f757f3fSDimitry Andric 9565f757f3fSDimitry Andric bool Changed = SafeStack(F, *TL, DL, &DTU, SE).run(); 9575f757f3fSDimitry Andric 9585f757f3fSDimitry Andric if (!Changed) 9595f757f3fSDimitry Andric return PreservedAnalyses::all(); 9605f757f3fSDimitry Andric PreservedAnalyses PA; 9615f757f3fSDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 9625f757f3fSDimitry Andric return PA; 9635f757f3fSDimitry Andric } 9645f757f3fSDimitry Andric 9650b57cec5SDimitry Andric char SafeStackLegacyPass::ID = 0; 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(SafeStackLegacyPass, DEBUG_TYPE, 9680b57cec5SDimitry Andric "Safe Stack instrumentation pass", false, false) 9690b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 970fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 9710b57cec5SDimitry Andric INITIALIZE_PASS_END(SafeStackLegacyPass, DEBUG_TYPE, 9720b57cec5SDimitry Andric "Safe Stack instrumentation pass", false, false) 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric FunctionPass *llvm::createSafeStackPass() { return new SafeStackLegacyPass(); } 975