1044eb2f6SDimitry Andric //===- SafeStack.cpp - Safe Stack Insertion -------------------------------===//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric //
901095a5dSDimitry Andric // This pass splits the stack into the safe stack (kept as-is for LLVM backend)
1001095a5dSDimitry Andric // and the unsafe stack (explicitly allocated and managed through the runtime
1101095a5dSDimitry Andric // support library).
1201095a5dSDimitry Andric //
1301095a5dSDimitry Andric // http://clang.llvm.org/docs/SafeStack.html
1401095a5dSDimitry Andric //
1501095a5dSDimitry Andric //===----------------------------------------------------------------------===//
1601095a5dSDimitry Andric
17b1c73532SDimitry Andric #include "llvm/CodeGen/SafeStack.h"
1801095a5dSDimitry Andric #include "SafeStackLayout.h"
19044eb2f6SDimitry Andric #include "llvm/ADT/APInt.h"
20044eb2f6SDimitry Andric #include "llvm/ADT/ArrayRef.h"
21044eb2f6SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
22044eb2f6SDimitry Andric #include "llvm/ADT/SmallVector.h"
2301095a5dSDimitry Andric #include "llvm/ADT/Statistic.h"
246b3f41edSDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
2501095a5dSDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
26344a3780SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h"
27eb11fae6SDimitry Andric #include "llvm/Analysis/InlineCost.h"
28044eb2f6SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
2901095a5dSDimitry Andric #include "llvm/Analysis/ScalarEvolution.h"
3001095a5dSDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h"
31cfca06d7SDimitry Andric #include "llvm/Analysis/StackLifetime.h"
32044eb2f6SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
33044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
34b5630dbaSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
35044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
36044eb2f6SDimitry Andric #include "llvm/IR/Argument.h"
37044eb2f6SDimitry Andric #include "llvm/IR/Attributes.h"
38044eb2f6SDimitry Andric #include "llvm/IR/ConstantRange.h"
3901095a5dSDimitry Andric #include "llvm/IR/Constants.h"
4001095a5dSDimitry Andric #include "llvm/IR/DIBuilder.h"
4101095a5dSDimitry Andric #include "llvm/IR/DataLayout.h"
4201095a5dSDimitry Andric #include "llvm/IR/DerivedTypes.h"
43044eb2f6SDimitry Andric #include "llvm/IR/Dominators.h"
4401095a5dSDimitry Andric #include "llvm/IR/Function.h"
4501095a5dSDimitry Andric #include "llvm/IR/IRBuilder.h"
4601095a5dSDimitry Andric #include "llvm/IR/InstIterator.h"
47044eb2f6SDimitry Andric #include "llvm/IR/Instruction.h"
4801095a5dSDimitry Andric #include "llvm/IR/Instructions.h"
4901095a5dSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
5001095a5dSDimitry Andric #include "llvm/IR/Intrinsics.h"
5101095a5dSDimitry Andric #include "llvm/IR/MDBuilder.h"
52145449b1SDimitry Andric #include "llvm/IR/Metadata.h"
5301095a5dSDimitry Andric #include "llvm/IR/Module.h"
54044eb2f6SDimitry Andric #include "llvm/IR/Type.h"
55044eb2f6SDimitry Andric #include "llvm/IR/Use.h"
56044eb2f6SDimitry Andric #include "llvm/IR/Value.h"
57706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
5801095a5dSDimitry Andric #include "llvm/Pass.h"
59044eb2f6SDimitry Andric #include "llvm/Support/Casting.h"
6001095a5dSDimitry Andric #include "llvm/Support/Debug.h"
61044eb2f6SDimitry Andric #include "llvm/Support/ErrorHandling.h"
6201095a5dSDimitry Andric #include "llvm/Support/MathExtras.h"
63044eb2f6SDimitry Andric #include "llvm/Support/raw_ostream.h"
64044eb2f6SDimitry Andric #include "llvm/Target/TargetMachine.h"
6501095a5dSDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
66eb11fae6SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
67706b4fc4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
68044eb2f6SDimitry Andric #include <algorithm>
69044eb2f6SDimitry Andric #include <cassert>
70044eb2f6SDimitry Andric #include <cstdint>
71e3b55780SDimitry Andric #include <optional>
72044eb2f6SDimitry Andric #include <string>
73044eb2f6SDimitry Andric #include <utility>
7401095a5dSDimitry Andric
7501095a5dSDimitry Andric using namespace llvm;
7601095a5dSDimitry Andric using namespace llvm::safestack;
7701095a5dSDimitry Andric
78ab44ce3dSDimitry Andric #define DEBUG_TYPE "safe-stack"
7901095a5dSDimitry Andric
8001095a5dSDimitry Andric namespace llvm {
8101095a5dSDimitry Andric
8201095a5dSDimitry Andric STATISTIC(NumFunctions, "Total number of functions");
8301095a5dSDimitry Andric STATISTIC(NumUnsafeStackFunctions, "Number of functions with unsafe stack");
8401095a5dSDimitry Andric STATISTIC(NumUnsafeStackRestorePointsFunctions,
8501095a5dSDimitry Andric "Number of functions that use setjmp or exceptions");
8601095a5dSDimitry Andric
8701095a5dSDimitry Andric STATISTIC(NumAllocas, "Total number of allocas");
8801095a5dSDimitry Andric STATISTIC(NumUnsafeStaticAllocas, "Number of unsafe static allocas");
8901095a5dSDimitry Andric STATISTIC(NumUnsafeDynamicAllocas, "Number of unsafe dynamic allocas");
9001095a5dSDimitry Andric STATISTIC(NumUnsafeByValArguments, "Number of unsafe byval arguments");
9101095a5dSDimitry Andric STATISTIC(NumUnsafeStackRestorePoints, "Number of setjmps and landingpads");
9201095a5dSDimitry Andric
9301095a5dSDimitry Andric } // namespace llvm
9401095a5dSDimitry Andric
95eb11fae6SDimitry Andric /// Use __safestack_pointer_address even if the platform has a faster way of
96eb11fae6SDimitry Andric /// access safe stack pointer.
97eb11fae6SDimitry Andric static cl::opt<bool>
98eb11fae6SDimitry Andric SafeStackUsePointerAddress("safestack-use-pointer-address",
99eb11fae6SDimitry Andric cl::init(false), cl::Hidden);
100eb11fae6SDimitry Andric
101cfca06d7SDimitry Andric static cl::opt<bool> ClColoring("safe-stack-coloring",
102cfca06d7SDimitry Andric cl::desc("enable safe stack coloring"),
103145449b1SDimitry Andric cl::Hidden, cl::init(true));
104eb11fae6SDimitry Andric
10501095a5dSDimitry Andric namespace {
10601095a5dSDimitry Andric
10701095a5dSDimitry Andric /// The SafeStack pass splits the stack of each function into the safe
10801095a5dSDimitry Andric /// stack, which is only accessed through memory safe dereferences (as
10901095a5dSDimitry Andric /// determined statically), and the unsafe stack, which contains all
11001095a5dSDimitry Andric /// local variables that are accessed in ways that we can't prove to
11101095a5dSDimitry Andric /// be safe.
1126b3f41edSDimitry Andric class SafeStack {
1136b3f41edSDimitry Andric Function &F;
1146b3f41edSDimitry Andric const TargetLoweringBase &TL;
1156b3f41edSDimitry Andric const DataLayout &DL;
116344a3780SDimitry Andric DomTreeUpdater *DTU;
1176b3f41edSDimitry Andric ScalarEvolution &SE;
11801095a5dSDimitry Andric
11901095a5dSDimitry Andric Type *StackPtrTy;
12001095a5dSDimitry Andric Type *IntPtrTy;
12101095a5dSDimitry Andric Type *Int32Ty;
12201095a5dSDimitry Andric
12301095a5dSDimitry Andric Value *UnsafeStackPtr = nullptr;
12401095a5dSDimitry Andric
12501095a5dSDimitry Andric /// Unsafe stack alignment. Each stack frame must ensure that the stack is
12601095a5dSDimitry Andric /// aligned to this value. We need to re-align the unsafe stack if the
12701095a5dSDimitry Andric /// alignment of any object on the stack exceeds this value.
12801095a5dSDimitry Andric ///
12901095a5dSDimitry Andric /// 16 seems like a reasonable upper bound on the alignment of objects that we
13001095a5dSDimitry Andric /// might expect to appear on the stack on most common targets.
131145449b1SDimitry Andric static constexpr Align StackAlignment = Align::Constant<16>();
13201095a5dSDimitry Andric
133eb11fae6SDimitry Andric /// Return the value of the stack canary.
13401095a5dSDimitry Andric Value *getStackGuard(IRBuilder<> &IRB, Function &F);
13501095a5dSDimitry Andric
136eb11fae6SDimitry Andric /// Load stack guard from the frame and check if it has changed.
137b60736ecSDimitry Andric void checkStackGuard(IRBuilder<> &IRB, Function &F, Instruction &RI,
13801095a5dSDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard);
13901095a5dSDimitry Andric
140eb11fae6SDimitry Andric /// Find all static allocas, dynamic allocas, return instructions and
14101095a5dSDimitry Andric /// stack restore points (exception unwind blocks and setjmp calls) in the
14201095a5dSDimitry Andric /// given function and append them to the respective vectors.
14301095a5dSDimitry Andric void findInsts(Function &F, SmallVectorImpl<AllocaInst *> &StaticAllocas,
14401095a5dSDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas,
14501095a5dSDimitry Andric SmallVectorImpl<Argument *> &ByValArguments,
146b60736ecSDimitry Andric SmallVectorImpl<Instruction *> &Returns,
14701095a5dSDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints);
14801095a5dSDimitry Andric
149eb11fae6SDimitry Andric /// Calculate the allocation size of a given alloca. Returns 0 if the
15001095a5dSDimitry Andric /// size can not be statically determined.
15101095a5dSDimitry Andric uint64_t getStaticAllocaAllocationSize(const AllocaInst* AI);
15201095a5dSDimitry Andric
153eb11fae6SDimitry Andric /// Allocate space for all static allocas in \p StaticAllocas,
154b60736ecSDimitry Andric /// replace allocas with pointers into the unsafe stack.
15501095a5dSDimitry Andric ///
15601095a5dSDimitry Andric /// \returns A pointer to the top of the unsafe stack after all unsafe static
15701095a5dSDimitry Andric /// allocas are allocated.
15801095a5dSDimitry Andric Value *moveStaticAllocasToUnsafeStack(IRBuilder<> &IRB, Function &F,
15901095a5dSDimitry Andric ArrayRef<AllocaInst *> StaticAllocas,
16001095a5dSDimitry Andric ArrayRef<Argument *> ByValArguments,
16101095a5dSDimitry Andric Instruction *BasePointer,
16201095a5dSDimitry Andric AllocaInst *StackGuardSlot);
16301095a5dSDimitry Andric
164eb11fae6SDimitry Andric /// Generate code to restore the stack after all stack restore points
16501095a5dSDimitry Andric /// in \p StackRestorePoints.
16601095a5dSDimitry Andric ///
16701095a5dSDimitry Andric /// \returns A local variable in which to maintain the dynamic top of the
16801095a5dSDimitry Andric /// unsafe stack if needed.
16901095a5dSDimitry Andric AllocaInst *
17001095a5dSDimitry Andric createStackRestorePoints(IRBuilder<> &IRB, Function &F,
17101095a5dSDimitry Andric ArrayRef<Instruction *> StackRestorePoints,
17201095a5dSDimitry Andric Value *StaticTop, bool NeedDynamicTop);
17301095a5dSDimitry Andric
174eb11fae6SDimitry Andric /// Replace all allocas in \p DynamicAllocas with code to allocate
17501095a5dSDimitry Andric /// space dynamically on the unsafe stack and store the dynamic unsafe stack
17601095a5dSDimitry Andric /// top to \p DynamicTop if non-null.
17701095a5dSDimitry Andric void moveDynamicAllocasToUnsafeStack(Function &F, Value *UnsafeStackPtr,
17801095a5dSDimitry Andric AllocaInst *DynamicTop,
17901095a5dSDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas);
18001095a5dSDimitry Andric
18101095a5dSDimitry Andric bool IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize);
18201095a5dSDimitry Andric
18301095a5dSDimitry Andric bool IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U,
18401095a5dSDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize);
18501095a5dSDimitry Andric bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr,
18601095a5dSDimitry Andric uint64_t AllocaSize);
18701095a5dSDimitry Andric
188cfca06d7SDimitry Andric bool ShouldInlinePointerAddress(CallInst &CI);
189eb11fae6SDimitry Andric void TryInlinePointerAddress();
190eb11fae6SDimitry Andric
19101095a5dSDimitry Andric public:
SafeStack(Function & F,const TargetLoweringBase & TL,const DataLayout & DL,DomTreeUpdater * DTU,ScalarEvolution & SE)1926b3f41edSDimitry Andric SafeStack(Function &F, const TargetLoweringBase &TL, const DataLayout &DL,
193344a3780SDimitry Andric DomTreeUpdater *DTU, ScalarEvolution &SE)
194344a3780SDimitry Andric : F(F), TL(TL), DL(DL), DTU(DTU), SE(SE),
195b1c73532SDimitry Andric StackPtrTy(PointerType::getUnqual(F.getContext())),
1966b3f41edSDimitry Andric IntPtrTy(DL.getIntPtrType(F.getContext())),
1974df029ccSDimitry Andric Int32Ty(Type::getInt32Ty(F.getContext())) {}
19801095a5dSDimitry Andric
1996b3f41edSDimitry Andric // Run the transformation on the associated function.
2006b3f41edSDimitry Andric // Returns whether the function was changed.
2016b3f41edSDimitry Andric bool run();
2026b3f41edSDimitry Andric };
20301095a5dSDimitry Andric
204145449b1SDimitry Andric constexpr Align SafeStack::StackAlignment;
205c0981da4SDimitry Andric
getStaticAllocaAllocationSize(const AllocaInst * AI)20601095a5dSDimitry Andric uint64_t SafeStack::getStaticAllocaAllocationSize(const AllocaInst* AI) {
2076b3f41edSDimitry Andric uint64_t Size = DL.getTypeAllocSize(AI->getAllocatedType());
20801095a5dSDimitry Andric if (AI->isArrayAllocation()) {
20901095a5dSDimitry Andric auto C = dyn_cast<ConstantInt>(AI->getArraySize());
21001095a5dSDimitry Andric if (!C)
21101095a5dSDimitry Andric return 0;
21201095a5dSDimitry Andric Size *= C->getZExtValue();
21301095a5dSDimitry Andric }
21401095a5dSDimitry Andric return Size;
21501095a5dSDimitry Andric }
21601095a5dSDimitry Andric
IsAccessSafe(Value * Addr,uint64_t AccessSize,const Value * AllocaPtr,uint64_t AllocaSize)21701095a5dSDimitry Andric bool SafeStack::IsAccessSafe(Value *Addr, uint64_t AccessSize,
21801095a5dSDimitry Andric const Value *AllocaPtr, uint64_t AllocaSize) {
219145449b1SDimitry Andric const SCEV *AddrExpr = SE.getSCEV(Addr);
220145449b1SDimitry Andric const auto *Base = dyn_cast<SCEVUnknown>(SE.getPointerBase(AddrExpr));
221145449b1SDimitry Andric if (!Base || Base->getValue() != AllocaPtr) {
222145449b1SDimitry Andric LLVM_DEBUG(
223145449b1SDimitry Andric dbgs() << "[SafeStack] "
224145449b1SDimitry Andric << (isa<AllocaInst>(AllocaPtr) ? "Alloca " : "ByValArgument ")
225145449b1SDimitry Andric << *AllocaPtr << "\n"
226145449b1SDimitry Andric << "SCEV " << *AddrExpr << " not directly based on alloca\n");
227145449b1SDimitry Andric return false;
228145449b1SDimitry Andric }
22901095a5dSDimitry Andric
230145449b1SDimitry Andric const SCEV *Expr = SE.removePointerBase(AddrExpr);
2316b3f41edSDimitry Andric uint64_t BitWidth = SE.getTypeSizeInBits(Expr->getType());
2326b3f41edSDimitry Andric ConstantRange AccessStartRange = SE.getUnsignedRange(Expr);
23301095a5dSDimitry Andric ConstantRange SizeRange =
23401095a5dSDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AccessSize));
23501095a5dSDimitry Andric ConstantRange AccessRange = AccessStartRange.add(SizeRange);
23601095a5dSDimitry Andric ConstantRange AllocaRange =
23701095a5dSDimitry Andric ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, AllocaSize));
23801095a5dSDimitry Andric bool Safe = AllocaRange.contains(AccessRange);
23901095a5dSDimitry Andric
240eb11fae6SDimitry Andric LLVM_DEBUG(
241eb11fae6SDimitry Andric dbgs() << "[SafeStack] "
24201095a5dSDimitry Andric << (isa<AllocaInst>(AllocaPtr) ? "Alloca " : "ByValArgument ")
24301095a5dSDimitry Andric << *AllocaPtr << "\n"
24401095a5dSDimitry Andric << " Access " << *Addr << "\n"
24501095a5dSDimitry Andric << " SCEV " << *Expr
2466b3f41edSDimitry Andric << " U: " << SE.getUnsignedRange(Expr)
2476b3f41edSDimitry Andric << ", S: " << SE.getSignedRange(Expr) << "\n"
24801095a5dSDimitry Andric << " Range " << AccessRange << "\n"
24901095a5dSDimitry Andric << " AllocaRange " << AllocaRange << "\n"
25001095a5dSDimitry Andric << " " << (Safe ? "safe" : "unsafe") << "\n");
25101095a5dSDimitry Andric
25201095a5dSDimitry Andric return Safe;
25301095a5dSDimitry Andric }
25401095a5dSDimitry Andric
IsMemIntrinsicSafe(const MemIntrinsic * MI,const Use & U,const Value * AllocaPtr,uint64_t AllocaSize)25501095a5dSDimitry Andric bool SafeStack::IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U,
25601095a5dSDimitry Andric const Value *AllocaPtr,
25701095a5dSDimitry Andric uint64_t AllocaSize) {
258d8e91e46SDimitry Andric if (auto MTI = dyn_cast<MemTransferInst>(MI)) {
259d8e91e46SDimitry Andric if (MTI->getRawSource() != U && MTI->getRawDest() != U)
260d8e91e46SDimitry Andric return true;
261d8e91e46SDimitry Andric } else {
262d8e91e46SDimitry Andric if (MI->getRawDest() != U)
263d8e91e46SDimitry Andric return true;
264d8e91e46SDimitry Andric }
265d8e91e46SDimitry Andric
26601095a5dSDimitry Andric const auto *Len = dyn_cast<ConstantInt>(MI->getLength());
26701095a5dSDimitry Andric // Non-constant size => unsafe. FIXME: try SCEV getRange.
26801095a5dSDimitry Andric if (!Len) return false;
26901095a5dSDimitry Andric return IsAccessSafe(U, Len->getZExtValue(), AllocaPtr, AllocaSize);
27001095a5dSDimitry Andric }
27101095a5dSDimitry Andric
27201095a5dSDimitry Andric /// Check whether a given allocation must be put on the safe
27301095a5dSDimitry Andric /// stack or not. The function analyzes all uses of AI and checks whether it is
27401095a5dSDimitry Andric /// only accessed in a memory safe way (as decided statically).
IsSafeStackAlloca(const Value * AllocaPtr,uint64_t AllocaSize)27501095a5dSDimitry Andric bool SafeStack::IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize) {
27601095a5dSDimitry Andric // Go through all uses of this alloca and check whether all accesses to the
27701095a5dSDimitry Andric // allocated object are statically known to be memory safe and, hence, the
27801095a5dSDimitry Andric // object can be placed on the safe stack.
27901095a5dSDimitry Andric SmallPtrSet<const Value *, 16> Visited;
28001095a5dSDimitry Andric SmallVector<const Value *, 8> WorkList;
28101095a5dSDimitry Andric WorkList.push_back(AllocaPtr);
28201095a5dSDimitry Andric
28301095a5dSDimitry Andric // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc.
28401095a5dSDimitry Andric while (!WorkList.empty()) {
28501095a5dSDimitry Andric const Value *V = WorkList.pop_back_val();
28601095a5dSDimitry Andric for (const Use &UI : V->uses()) {
28701095a5dSDimitry Andric auto I = cast<const Instruction>(UI.getUser());
28801095a5dSDimitry Andric assert(V == UI.get());
28901095a5dSDimitry Andric
29001095a5dSDimitry Andric switch (I->getOpcode()) {
291044eb2f6SDimitry Andric case Instruction::Load:
2926b3f41edSDimitry Andric if (!IsAccessSafe(UI, DL.getTypeStoreSize(I->getType()), AllocaPtr,
29301095a5dSDimitry Andric AllocaSize))
29401095a5dSDimitry Andric return false;
29501095a5dSDimitry Andric break;
296044eb2f6SDimitry Andric
29701095a5dSDimitry Andric case Instruction::VAArg:
29801095a5dSDimitry Andric // "va-arg" from a pointer is safe.
29901095a5dSDimitry Andric break;
300044eb2f6SDimitry Andric case Instruction::Store:
30101095a5dSDimitry Andric if (V == I->getOperand(0)) {
30201095a5dSDimitry Andric // Stored the pointer - conservatively assume it may be unsafe.
303eb11fae6SDimitry Andric LLVM_DEBUG(dbgs()
304eb11fae6SDimitry Andric << "[SafeStack] Unsafe alloca: " << *AllocaPtr
30501095a5dSDimitry Andric << "\n store of address: " << *I << "\n");
30601095a5dSDimitry Andric return false;
30701095a5dSDimitry Andric }
30801095a5dSDimitry Andric
3096b3f41edSDimitry Andric if (!IsAccessSafe(UI, DL.getTypeStoreSize(I->getOperand(0)->getType()),
31001095a5dSDimitry Andric AllocaPtr, AllocaSize))
31101095a5dSDimitry Andric return false;
31201095a5dSDimitry Andric break;
313044eb2f6SDimitry Andric
314044eb2f6SDimitry Andric case Instruction::Ret:
31501095a5dSDimitry Andric // Information leak.
31601095a5dSDimitry Andric return false;
31701095a5dSDimitry Andric
31801095a5dSDimitry Andric case Instruction::Call:
31901095a5dSDimitry Andric case Instruction::Invoke: {
320cfca06d7SDimitry Andric const CallBase &CS = *cast<CallBase>(I);
32101095a5dSDimitry Andric
322d8e91e46SDimitry Andric if (I->isLifetimeStartOrEnd())
32301095a5dSDimitry Andric continue;
32401095a5dSDimitry Andric
32501095a5dSDimitry Andric if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) {
32601095a5dSDimitry Andric if (!IsMemIntrinsicSafe(MI, UI, AllocaPtr, AllocaSize)) {
327eb11fae6SDimitry Andric LLVM_DEBUG(dbgs()
328eb11fae6SDimitry Andric << "[SafeStack] Unsafe alloca: " << *AllocaPtr
329eb11fae6SDimitry Andric << "\n unsafe memintrinsic: " << *I << "\n");
33001095a5dSDimitry Andric return false;
33101095a5dSDimitry Andric }
33201095a5dSDimitry Andric continue;
33301095a5dSDimitry Andric }
33401095a5dSDimitry Andric
33501095a5dSDimitry Andric // LLVM 'nocapture' attribute is only set for arguments whose address
33601095a5dSDimitry Andric // is not stored, passed around, or used in any other non-trivial way.
33701095a5dSDimitry Andric // We assume that passing a pointer to an object as a 'nocapture
33801095a5dSDimitry Andric // readnone' argument is safe.
33901095a5dSDimitry Andric // FIXME: a more precise solution would require an interprocedural
34001095a5dSDimitry Andric // analysis here, which would look at all uses of an argument inside
34101095a5dSDimitry Andric // the function being called.
342cfca06d7SDimitry Andric auto B = CS.arg_begin(), E = CS.arg_end();
3434b4fe385SDimitry Andric for (const auto *A = B; A != E; ++A)
34401095a5dSDimitry Andric if (A->get() == V)
34501095a5dSDimitry Andric if (!(CS.doesNotCapture(A - B) && (CS.doesNotAccessMemory(A - B) ||
34601095a5dSDimitry Andric CS.doesNotAccessMemory()))) {
347eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] Unsafe alloca: " << *AllocaPtr
34801095a5dSDimitry Andric << "\n unsafe call: " << *I << "\n");
34901095a5dSDimitry Andric return false;
35001095a5dSDimitry Andric }
35101095a5dSDimitry Andric continue;
35201095a5dSDimitry Andric }
35301095a5dSDimitry Andric
35401095a5dSDimitry Andric default:
35501095a5dSDimitry Andric if (Visited.insert(I).second)
35601095a5dSDimitry Andric WorkList.push_back(cast<const Instruction>(I));
35701095a5dSDimitry Andric }
35801095a5dSDimitry Andric }
35901095a5dSDimitry Andric }
36001095a5dSDimitry Andric
36101095a5dSDimitry Andric // All uses of the alloca are safe, we can place it on the safe stack.
36201095a5dSDimitry Andric return true;
36301095a5dSDimitry Andric }
36401095a5dSDimitry Andric
getStackGuard(IRBuilder<> & IRB,Function & F)36501095a5dSDimitry Andric Value *SafeStack::getStackGuard(IRBuilder<> &IRB, Function &F) {
3666b3f41edSDimitry Andric Value *StackGuardVar = TL.getIRStackGuard(IRB);
367344a3780SDimitry Andric Module *M = F.getParent();
368344a3780SDimitry Andric
369344a3780SDimitry Andric if (!StackGuardVar) {
370344a3780SDimitry Andric TL.insertSSPDeclarations(*M);
371344a3780SDimitry Andric return IRB.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackguard));
372344a3780SDimitry Andric }
373344a3780SDimitry Andric
374e6d15924SDimitry Andric return IRB.CreateLoad(StackPtrTy, StackGuardVar, "StackGuard");
37501095a5dSDimitry Andric }
37601095a5dSDimitry Andric
findInsts(Function & F,SmallVectorImpl<AllocaInst * > & StaticAllocas,SmallVectorImpl<AllocaInst * > & DynamicAllocas,SmallVectorImpl<Argument * > & ByValArguments,SmallVectorImpl<Instruction * > & Returns,SmallVectorImpl<Instruction * > & StackRestorePoints)37701095a5dSDimitry Andric void SafeStack::findInsts(Function &F,
37801095a5dSDimitry Andric SmallVectorImpl<AllocaInst *> &StaticAllocas,
37901095a5dSDimitry Andric SmallVectorImpl<AllocaInst *> &DynamicAllocas,
38001095a5dSDimitry Andric SmallVectorImpl<Argument *> &ByValArguments,
381b60736ecSDimitry Andric SmallVectorImpl<Instruction *> &Returns,
38201095a5dSDimitry Andric SmallVectorImpl<Instruction *> &StackRestorePoints) {
38301095a5dSDimitry Andric for (Instruction &I : instructions(&F)) {
38401095a5dSDimitry Andric if (auto AI = dyn_cast<AllocaInst>(&I)) {
38501095a5dSDimitry Andric ++NumAllocas;
38601095a5dSDimitry Andric
38701095a5dSDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI);
38801095a5dSDimitry Andric if (IsSafeStackAlloca(AI, Size))
38901095a5dSDimitry Andric continue;
39001095a5dSDimitry Andric
39101095a5dSDimitry Andric if (AI->isStaticAlloca()) {
39201095a5dSDimitry Andric ++NumUnsafeStaticAllocas;
39301095a5dSDimitry Andric StaticAllocas.push_back(AI);
39401095a5dSDimitry Andric } else {
39501095a5dSDimitry Andric ++NumUnsafeDynamicAllocas;
39601095a5dSDimitry Andric DynamicAllocas.push_back(AI);
39701095a5dSDimitry Andric }
39801095a5dSDimitry Andric } else if (auto RI = dyn_cast<ReturnInst>(&I)) {
399b60736ecSDimitry Andric if (CallInst *CI = I.getParent()->getTerminatingMustTailCall())
400b60736ecSDimitry Andric Returns.push_back(CI);
401b60736ecSDimitry Andric else
40201095a5dSDimitry Andric Returns.push_back(RI);
40301095a5dSDimitry Andric } else if (auto CI = dyn_cast<CallInst>(&I)) {
40401095a5dSDimitry Andric // setjmps require stack restore.
40501095a5dSDimitry Andric if (CI->getCalledFunction() && CI->canReturnTwice())
40601095a5dSDimitry Andric StackRestorePoints.push_back(CI);
40701095a5dSDimitry Andric } else if (auto LP = dyn_cast<LandingPadInst>(&I)) {
40801095a5dSDimitry Andric // Exception landing pads require stack restore.
40901095a5dSDimitry Andric StackRestorePoints.push_back(LP);
41001095a5dSDimitry Andric } else if (auto II = dyn_cast<IntrinsicInst>(&I)) {
41101095a5dSDimitry Andric if (II->getIntrinsicID() == Intrinsic::gcroot)
412044eb2f6SDimitry Andric report_fatal_error(
41301095a5dSDimitry Andric "gcroot intrinsic not compatible with safestack attribute");
41401095a5dSDimitry Andric }
41501095a5dSDimitry Andric }
41601095a5dSDimitry Andric for (Argument &Arg : F.args()) {
41701095a5dSDimitry Andric if (!Arg.hasByValAttr())
41801095a5dSDimitry Andric continue;
419344a3780SDimitry Andric uint64_t Size = DL.getTypeStoreSize(Arg.getParamByValType());
42001095a5dSDimitry Andric if (IsSafeStackAlloca(&Arg, Size))
42101095a5dSDimitry Andric continue;
42201095a5dSDimitry Andric
42301095a5dSDimitry Andric ++NumUnsafeByValArguments;
42401095a5dSDimitry Andric ByValArguments.push_back(&Arg);
42501095a5dSDimitry Andric }
42601095a5dSDimitry Andric }
42701095a5dSDimitry Andric
42801095a5dSDimitry Andric AllocaInst *
createStackRestorePoints(IRBuilder<> & IRB,Function & F,ArrayRef<Instruction * > StackRestorePoints,Value * StaticTop,bool NeedDynamicTop)42901095a5dSDimitry Andric SafeStack::createStackRestorePoints(IRBuilder<> &IRB, Function &F,
43001095a5dSDimitry Andric ArrayRef<Instruction *> StackRestorePoints,
43101095a5dSDimitry Andric Value *StaticTop, bool NeedDynamicTop) {
43201095a5dSDimitry Andric assert(StaticTop && "The stack top isn't set.");
43301095a5dSDimitry Andric
43401095a5dSDimitry Andric if (StackRestorePoints.empty())
43501095a5dSDimitry Andric return nullptr;
43601095a5dSDimitry Andric
43701095a5dSDimitry Andric // We need the current value of the shadow stack pointer to restore
43801095a5dSDimitry Andric // after longjmp or exception catching.
43901095a5dSDimitry Andric
44001095a5dSDimitry Andric // FIXME: On some platforms this could be handled by the longjmp/exception
44101095a5dSDimitry Andric // runtime itself.
44201095a5dSDimitry Andric
44301095a5dSDimitry Andric AllocaInst *DynamicTop = nullptr;
44401095a5dSDimitry Andric if (NeedDynamicTop) {
44501095a5dSDimitry Andric // If we also have dynamic alloca's, the stack pointer value changes
44601095a5dSDimitry Andric // throughout the function. For now we store it in an alloca.
44701095a5dSDimitry Andric DynamicTop = IRB.CreateAlloca(StackPtrTy, /*ArraySize=*/nullptr,
44801095a5dSDimitry Andric "unsafe_stack_dynamic_ptr");
44901095a5dSDimitry Andric IRB.CreateStore(StaticTop, DynamicTop);
45001095a5dSDimitry Andric }
45101095a5dSDimitry Andric
45201095a5dSDimitry Andric // Restore current stack pointer after longjmp/exception catch.
45301095a5dSDimitry Andric for (Instruction *I : StackRestorePoints) {
45401095a5dSDimitry Andric ++NumUnsafeStackRestorePoints;
45501095a5dSDimitry Andric
45601095a5dSDimitry Andric IRB.SetInsertPoint(I->getNextNode());
457e6d15924SDimitry Andric Value *CurrentTop =
458e6d15924SDimitry Andric DynamicTop ? IRB.CreateLoad(StackPtrTy, DynamicTop) : StaticTop;
45901095a5dSDimitry Andric IRB.CreateStore(CurrentTop, UnsafeStackPtr);
46001095a5dSDimitry Andric }
46101095a5dSDimitry Andric
46201095a5dSDimitry Andric return DynamicTop;
46301095a5dSDimitry Andric }
46401095a5dSDimitry Andric
checkStackGuard(IRBuilder<> & IRB,Function & F,Instruction & RI,AllocaInst * StackGuardSlot,Value * StackGuard)465b60736ecSDimitry Andric void SafeStack::checkStackGuard(IRBuilder<> &IRB, Function &F, Instruction &RI,
46601095a5dSDimitry Andric AllocaInst *StackGuardSlot, Value *StackGuard) {
467e6d15924SDimitry Andric Value *V = IRB.CreateLoad(StackPtrTy, StackGuardSlot);
46801095a5dSDimitry Andric Value *Cmp = IRB.CreateICmpNE(StackGuard, V);
46901095a5dSDimitry Andric
47001095a5dSDimitry Andric auto SuccessProb = BranchProbabilityInfo::getBranchProbStackProtector(true);
47101095a5dSDimitry Andric auto FailureProb = BranchProbabilityInfo::getBranchProbStackProtector(false);
47201095a5dSDimitry Andric MDNode *Weights = MDBuilder(F.getContext())
47301095a5dSDimitry Andric .createBranchWeights(SuccessProb.getNumerator(),
47401095a5dSDimitry Andric FailureProb.getNumerator());
47501095a5dSDimitry Andric Instruction *CheckTerm =
476344a3780SDimitry Andric SplitBlockAndInsertIfThen(Cmp, &RI, /* Unreachable */ true, Weights, DTU);
47701095a5dSDimitry Andric IRBuilder<> IRBFail(CheckTerm);
47801095a5dSDimitry Andric // FIXME: respect -fsanitize-trap / -ftrap-function here?
479e6d15924SDimitry Andric FunctionCallee StackChkFail =
480e6d15924SDimitry Andric F.getParent()->getOrInsertFunction("__stack_chk_fail", IRB.getVoidTy());
48101095a5dSDimitry Andric IRBFail.CreateCall(StackChkFail, {});
48201095a5dSDimitry Andric }
48301095a5dSDimitry Andric
48401095a5dSDimitry Andric /// We explicitly compute and set the unsafe stack layout for all unsafe
48501095a5dSDimitry Andric /// static alloca instructions. We save the unsafe "base pointer" in the
48601095a5dSDimitry Andric /// prologue into a local variable and restore it in the epilogue.
moveStaticAllocasToUnsafeStack(IRBuilder<> & IRB,Function & F,ArrayRef<AllocaInst * > StaticAllocas,ArrayRef<Argument * > ByValArguments,Instruction * BasePointer,AllocaInst * StackGuardSlot)48701095a5dSDimitry Andric Value *SafeStack::moveStaticAllocasToUnsafeStack(
48801095a5dSDimitry Andric IRBuilder<> &IRB, Function &F, ArrayRef<AllocaInst *> StaticAllocas,
489b60736ecSDimitry Andric ArrayRef<Argument *> ByValArguments, Instruction *BasePointer,
490b60736ecSDimitry Andric AllocaInst *StackGuardSlot) {
49101095a5dSDimitry Andric if (StaticAllocas.empty() && ByValArguments.empty())
49201095a5dSDimitry Andric return BasePointer;
49301095a5dSDimitry Andric
49401095a5dSDimitry Andric DIBuilder DIB(*F.getParent());
49501095a5dSDimitry Andric
496cfca06d7SDimitry Andric StackLifetime SSC(F, StaticAllocas, StackLifetime::LivenessType::May);
497cfca06d7SDimitry Andric static const StackLifetime::LiveRange NoColoringRange(1, true);
498cfca06d7SDimitry Andric if (ClColoring)
49901095a5dSDimitry Andric SSC.run();
500cfca06d7SDimitry Andric
5014b4fe385SDimitry Andric for (const auto *I : SSC.getMarkers()) {
502cfca06d7SDimitry Andric auto *Op = dyn_cast<Instruction>(I->getOperand(1));
503cfca06d7SDimitry Andric const_cast<IntrinsicInst *>(I)->eraseFromParent();
504cfca06d7SDimitry Andric // Remove the operand bitcast, too, if it has no more uses left.
505cfca06d7SDimitry Andric if (Op && Op->use_empty())
506cfca06d7SDimitry Andric Op->eraseFromParent();
507cfca06d7SDimitry Andric }
50801095a5dSDimitry Andric
50901095a5dSDimitry Andric // Unsafe stack always grows down.
51001095a5dSDimitry Andric StackLayout SSL(StackAlignment);
51101095a5dSDimitry Andric if (StackGuardSlot) {
51201095a5dSDimitry Andric Type *Ty = StackGuardSlot->getAllocatedType();
51377fc4c14SDimitry Andric Align Align = std::max(DL.getPrefTypeAlign(Ty), StackGuardSlot->getAlign());
51401095a5dSDimitry Andric SSL.addObject(StackGuardSlot, getStaticAllocaAllocationSize(StackGuardSlot),
515a7fe922bSDimitry Andric Align, SSC.getFullLiveRange());
51601095a5dSDimitry Andric }
51701095a5dSDimitry Andric
51801095a5dSDimitry Andric for (Argument *Arg : ByValArguments) {
519344a3780SDimitry Andric Type *Ty = Arg->getParamByValType();
5206b3f41edSDimitry Andric uint64_t Size = DL.getTypeStoreSize(Ty);
52101095a5dSDimitry Andric if (Size == 0)
52201095a5dSDimitry Andric Size = 1; // Don't create zero-sized stack objects.
52301095a5dSDimitry Andric
52401095a5dSDimitry Andric // Ensure the object is properly aligned.
52577fc4c14SDimitry Andric Align Align = DL.getPrefTypeAlign(Ty);
52677fc4c14SDimitry Andric if (auto A = Arg->getParamAlign())
52777fc4c14SDimitry Andric Align = std::max(Align, *A);
52801095a5dSDimitry Andric SSL.addObject(Arg, Size, Align, SSC.getFullLiveRange());
52901095a5dSDimitry Andric }
53001095a5dSDimitry Andric
53101095a5dSDimitry Andric for (AllocaInst *AI : StaticAllocas) {
53201095a5dSDimitry Andric Type *Ty = AI->getAllocatedType();
53301095a5dSDimitry Andric uint64_t Size = getStaticAllocaAllocationSize(AI);
53401095a5dSDimitry Andric if (Size == 0)
53501095a5dSDimitry Andric Size = 1; // Don't create zero-sized stack objects.
53601095a5dSDimitry Andric
53701095a5dSDimitry Andric // Ensure the object is properly aligned.
53877fc4c14SDimitry Andric Align Align = std::max(DL.getPrefTypeAlign(Ty), AI->getAlign());
53901095a5dSDimitry Andric
540cfca06d7SDimitry Andric SSL.addObject(AI, Size, Align,
541cfca06d7SDimitry Andric ClColoring ? SSC.getLiveRange(AI) : NoColoringRange);
54201095a5dSDimitry Andric }
54301095a5dSDimitry Andric
54401095a5dSDimitry Andric SSL.computeLayout();
54577fc4c14SDimitry Andric Align FrameAlignment = SSL.getFrameAlignment();
54601095a5dSDimitry Andric
54701095a5dSDimitry Andric // FIXME: tell SSL that we start at a less-then-MaxAlignment aligned location
54801095a5dSDimitry Andric // (AlignmentSkew).
54901095a5dSDimitry Andric if (FrameAlignment > StackAlignment) {
55001095a5dSDimitry Andric // Re-align the base pointer according to the max requested alignment.
55101095a5dSDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode());
55201095a5dSDimitry Andric BasePointer = cast<Instruction>(IRB.CreateIntToPtr(
55377fc4c14SDimitry Andric IRB.CreateAnd(
55477fc4c14SDimitry Andric IRB.CreatePtrToInt(BasePointer, IntPtrTy),
55577fc4c14SDimitry Andric ConstantInt::get(IntPtrTy, ~(FrameAlignment.value() - 1))),
55601095a5dSDimitry Andric StackPtrTy));
55701095a5dSDimitry Andric }
55801095a5dSDimitry Andric
55901095a5dSDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode());
56001095a5dSDimitry Andric
56101095a5dSDimitry Andric if (StackGuardSlot) {
56201095a5dSDimitry Andric unsigned Offset = SSL.getObjectOffset(StackGuardSlot);
5634df029ccSDimitry Andric Value *Off =
5644df029ccSDimitry Andric IRB.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -Offset));
56501095a5dSDimitry Andric Value *NewAI =
56601095a5dSDimitry Andric IRB.CreateBitCast(Off, StackGuardSlot->getType(), "StackGuardSlot");
56701095a5dSDimitry Andric
56801095a5dSDimitry Andric // Replace alloc with the new location.
56901095a5dSDimitry Andric StackGuardSlot->replaceAllUsesWith(NewAI);
57001095a5dSDimitry Andric StackGuardSlot->eraseFromParent();
57101095a5dSDimitry Andric }
57201095a5dSDimitry Andric
57301095a5dSDimitry Andric for (Argument *Arg : ByValArguments) {
57401095a5dSDimitry Andric unsigned Offset = SSL.getObjectOffset(Arg);
575706b4fc4SDimitry Andric MaybeAlign Align(SSL.getObjectAlignment(Arg));
576344a3780SDimitry Andric Type *Ty = Arg->getParamByValType();
57701095a5dSDimitry Andric
5786b3f41edSDimitry Andric uint64_t Size = DL.getTypeStoreSize(Ty);
57901095a5dSDimitry Andric if (Size == 0)
58001095a5dSDimitry Andric Size = 1; // Don't create zero-sized stack objects.
58101095a5dSDimitry Andric
5824df029ccSDimitry Andric Value *Off =
5834df029ccSDimitry Andric IRB.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -Offset));
58401095a5dSDimitry Andric Value *NewArg = IRB.CreateBitCast(Off, Arg->getType(),
58501095a5dSDimitry Andric Arg->getName() + ".unsafe-byval");
58601095a5dSDimitry Andric
58701095a5dSDimitry Andric // Replace alloc with the new location.
588cfca06d7SDimitry Andric replaceDbgDeclare(Arg, BasePointer, DIB, DIExpression::ApplyOffset,
589cfca06d7SDimitry Andric -Offset);
59001095a5dSDimitry Andric Arg->replaceAllUsesWith(NewArg);
59101095a5dSDimitry Andric IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode());
592706b4fc4SDimitry Andric IRB.CreateMemCpy(Off, Align, Arg, Arg->getParamAlign(), Size);
59301095a5dSDimitry Andric }
59401095a5dSDimitry Andric
59501095a5dSDimitry Andric // Allocate space for every unsafe static AllocaInst on the unsafe stack.
59601095a5dSDimitry Andric for (AllocaInst *AI : StaticAllocas) {
59701095a5dSDimitry Andric IRB.SetInsertPoint(AI);
59801095a5dSDimitry Andric unsigned Offset = SSL.getObjectOffset(AI);
59901095a5dSDimitry Andric
600cfca06d7SDimitry Andric replaceDbgDeclare(AI, BasePointer, DIB, DIExpression::ApplyOffset, -Offset);
60101095a5dSDimitry Andric replaceDbgValueForAlloca(AI, BasePointer, DIB, -Offset);
60201095a5dSDimitry Andric
60301095a5dSDimitry Andric // Replace uses of the alloca with the new location.
60401095a5dSDimitry Andric // Insert address calculation close to each use to work around PR27844.
60501095a5dSDimitry Andric std::string Name = std::string(AI->getName()) + ".unsafe";
60601095a5dSDimitry Andric while (!AI->use_empty()) {
60701095a5dSDimitry Andric Use &U = *AI->use_begin();
60801095a5dSDimitry Andric Instruction *User = cast<Instruction>(U.getUser());
60901095a5dSDimitry Andric
61001095a5dSDimitry Andric Instruction *InsertBefore;
61101095a5dSDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User))
61201095a5dSDimitry Andric InsertBefore = PHI->getIncomingBlock(U)->getTerminator();
61301095a5dSDimitry Andric else
61401095a5dSDimitry Andric InsertBefore = User;
61501095a5dSDimitry Andric
61601095a5dSDimitry Andric IRBuilder<> IRBUser(InsertBefore);
6174df029ccSDimitry Andric Value *Off =
6184df029ccSDimitry Andric IRBUser.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -Offset));
61901095a5dSDimitry Andric Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name);
62001095a5dSDimitry Andric
621e6d15924SDimitry Andric if (auto *PHI = dyn_cast<PHINode>(User))
62201095a5dSDimitry Andric // PHI nodes may have multiple incoming edges from the same BB (why??),
62301095a5dSDimitry Andric // all must be updated at once with the same incoming value.
624e6d15924SDimitry Andric PHI->setIncomingValueForBlock(PHI->getIncomingBlock(U), Replacement);
625e6d15924SDimitry Andric else
62601095a5dSDimitry Andric U.set(Replacement);
62701095a5dSDimitry Andric }
62801095a5dSDimitry Andric
62901095a5dSDimitry Andric AI->eraseFromParent();
63001095a5dSDimitry Andric }
63101095a5dSDimitry Andric
63201095a5dSDimitry Andric // Re-align BasePointer so that our callees would see it aligned as
63301095a5dSDimitry Andric // expected.
63401095a5dSDimitry Andric // FIXME: no need to update BasePointer in leaf functions.
63501095a5dSDimitry Andric unsigned FrameSize = alignTo(SSL.getFrameSize(), StackAlignment);
63601095a5dSDimitry Andric
637145449b1SDimitry Andric MDBuilder MDB(F.getContext());
638145449b1SDimitry Andric SmallVector<Metadata *, 2> Data;
639145449b1SDimitry Andric Data.push_back(MDB.createString("unsafe-stack-size"));
640145449b1SDimitry Andric Data.push_back(MDB.createConstant(ConstantInt::get(Int32Ty, FrameSize)));
641145449b1SDimitry Andric MDNode *MD = MDTuple::get(F.getContext(), Data);
642145449b1SDimitry Andric F.setMetadata(LLVMContext::MD_annotation, MD);
643145449b1SDimitry Andric
64401095a5dSDimitry Andric // Update shadow stack pointer in the function epilogue.
64501095a5dSDimitry Andric IRB.SetInsertPoint(BasePointer->getNextNode());
64601095a5dSDimitry Andric
64701095a5dSDimitry Andric Value *StaticTop =
6484df029ccSDimitry Andric IRB.CreatePtrAdd(BasePointer, ConstantInt::get(Int32Ty, -FrameSize),
64901095a5dSDimitry Andric "unsafe_stack_static_top");
65001095a5dSDimitry Andric IRB.CreateStore(StaticTop, UnsafeStackPtr);
65101095a5dSDimitry Andric return StaticTop;
65201095a5dSDimitry Andric }
65301095a5dSDimitry Andric
moveDynamicAllocasToUnsafeStack(Function & F,Value * UnsafeStackPtr,AllocaInst * DynamicTop,ArrayRef<AllocaInst * > DynamicAllocas)65401095a5dSDimitry Andric void SafeStack::moveDynamicAllocasToUnsafeStack(
65501095a5dSDimitry Andric Function &F, Value *UnsafeStackPtr, AllocaInst *DynamicTop,
65601095a5dSDimitry Andric ArrayRef<AllocaInst *> DynamicAllocas) {
65701095a5dSDimitry Andric DIBuilder DIB(*F.getParent());
65801095a5dSDimitry Andric
65901095a5dSDimitry Andric for (AllocaInst *AI : DynamicAllocas) {
66001095a5dSDimitry Andric IRBuilder<> IRB(AI);
66101095a5dSDimitry Andric
66201095a5dSDimitry Andric // Compute the new SP value (after AI).
66301095a5dSDimitry Andric Value *ArraySize = AI->getArraySize();
66401095a5dSDimitry Andric if (ArraySize->getType() != IntPtrTy)
66501095a5dSDimitry Andric ArraySize = IRB.CreateIntCast(ArraySize, IntPtrTy, false);
66601095a5dSDimitry Andric
66701095a5dSDimitry Andric Type *Ty = AI->getAllocatedType();
6686b3f41edSDimitry Andric uint64_t TySize = DL.getTypeAllocSize(Ty);
66901095a5dSDimitry Andric Value *Size = IRB.CreateMul(ArraySize, ConstantInt::get(IntPtrTy, TySize));
67001095a5dSDimitry Andric
671e6d15924SDimitry Andric Value *SP = IRB.CreatePtrToInt(IRB.CreateLoad(StackPtrTy, UnsafeStackPtr),
672e6d15924SDimitry Andric IntPtrTy);
67301095a5dSDimitry Andric SP = IRB.CreateSub(SP, Size);
67401095a5dSDimitry Andric
67501095a5dSDimitry Andric // Align the SP value to satisfy the AllocaInst, type and stack alignments.
676145449b1SDimitry Andric auto Align = std::max(std::max(DL.getPrefTypeAlign(Ty), AI->getAlign()),
677c0981da4SDimitry Andric StackAlignment);
67801095a5dSDimitry Andric
67901095a5dSDimitry Andric Value *NewTop = IRB.CreateIntToPtr(
680145449b1SDimitry Andric IRB.CreateAnd(SP,
681145449b1SDimitry Andric ConstantInt::get(IntPtrTy, ~uint64_t(Align.value() - 1))),
68201095a5dSDimitry Andric StackPtrTy);
68301095a5dSDimitry Andric
68401095a5dSDimitry Andric // Save the stack pointer.
68501095a5dSDimitry Andric IRB.CreateStore(NewTop, UnsafeStackPtr);
68601095a5dSDimitry Andric if (DynamicTop)
68701095a5dSDimitry Andric IRB.CreateStore(NewTop, DynamicTop);
68801095a5dSDimitry Andric
68901095a5dSDimitry Andric Value *NewAI = IRB.CreatePointerCast(NewTop, AI->getType());
69001095a5dSDimitry Andric if (AI->hasName() && isa<Instruction>(NewAI))
69101095a5dSDimitry Andric NewAI->takeName(AI);
69201095a5dSDimitry Andric
693cfca06d7SDimitry Andric replaceDbgDeclare(AI, NewAI, DIB, DIExpression::ApplyOffset, 0);
69401095a5dSDimitry Andric AI->replaceAllUsesWith(NewAI);
69501095a5dSDimitry Andric AI->eraseFromParent();
69601095a5dSDimitry Andric }
69701095a5dSDimitry Andric
69801095a5dSDimitry Andric if (!DynamicAllocas.empty()) {
69901095a5dSDimitry Andric // Now go through the instructions again, replacing stacksave/stackrestore.
700c0981da4SDimitry Andric for (Instruction &I : llvm::make_early_inc_range(instructions(&F))) {
701c0981da4SDimitry Andric auto *II = dyn_cast<IntrinsicInst>(&I);
70201095a5dSDimitry Andric if (!II)
70301095a5dSDimitry Andric continue;
70401095a5dSDimitry Andric
70501095a5dSDimitry Andric if (II->getIntrinsicID() == Intrinsic::stacksave) {
70601095a5dSDimitry Andric IRBuilder<> IRB(II);
707e6d15924SDimitry Andric Instruction *LI = IRB.CreateLoad(StackPtrTy, UnsafeStackPtr);
70801095a5dSDimitry Andric LI->takeName(II);
70901095a5dSDimitry Andric II->replaceAllUsesWith(LI);
71001095a5dSDimitry Andric II->eraseFromParent();
71101095a5dSDimitry Andric } else if (II->getIntrinsicID() == Intrinsic::stackrestore) {
71201095a5dSDimitry Andric IRBuilder<> IRB(II);
71301095a5dSDimitry Andric Instruction *SI = IRB.CreateStore(II->getArgOperand(0), UnsafeStackPtr);
71401095a5dSDimitry Andric SI->takeName(II);
71501095a5dSDimitry Andric assert(II->use_empty());
71601095a5dSDimitry Andric II->eraseFromParent();
71701095a5dSDimitry Andric }
71801095a5dSDimitry Andric }
71901095a5dSDimitry Andric }
72001095a5dSDimitry Andric }
72101095a5dSDimitry Andric
ShouldInlinePointerAddress(CallInst & CI)722cfca06d7SDimitry Andric bool SafeStack::ShouldInlinePointerAddress(CallInst &CI) {
723cfca06d7SDimitry Andric Function *Callee = CI.getCalledFunction();
724cfca06d7SDimitry Andric if (CI.hasFnAttr(Attribute::AlwaysInline) &&
725cfca06d7SDimitry Andric isInlineViable(*Callee).isSuccess())
726eb11fae6SDimitry Andric return true;
727eb11fae6SDimitry Andric if (Callee->isInterposable() || Callee->hasFnAttribute(Attribute::NoInline) ||
728cfca06d7SDimitry Andric CI.isNoInline())
729eb11fae6SDimitry Andric return false;
730eb11fae6SDimitry Andric return true;
731eb11fae6SDimitry Andric }
732eb11fae6SDimitry Andric
TryInlinePointerAddress()733eb11fae6SDimitry Andric void SafeStack::TryInlinePointerAddress() {
734cfca06d7SDimitry Andric auto *CI = dyn_cast<CallInst>(UnsafeStackPtr);
735cfca06d7SDimitry Andric if (!CI)
736eb11fae6SDimitry Andric return;
737eb11fae6SDimitry Andric
738e6d15924SDimitry Andric if(F.hasOptNone())
739eb11fae6SDimitry Andric return;
740eb11fae6SDimitry Andric
741cfca06d7SDimitry Andric Function *Callee = CI->getCalledFunction();
742eb11fae6SDimitry Andric if (!Callee || Callee->isDeclaration())
743eb11fae6SDimitry Andric return;
744eb11fae6SDimitry Andric
745cfca06d7SDimitry Andric if (!ShouldInlinePointerAddress(*CI))
746eb11fae6SDimitry Andric return;
747eb11fae6SDimitry Andric
748eb11fae6SDimitry Andric InlineFunctionInfo IFI;
749cfca06d7SDimitry Andric InlineFunction(*CI, IFI);
750eb11fae6SDimitry Andric }
751eb11fae6SDimitry Andric
run()7526b3f41edSDimitry Andric bool SafeStack::run() {
7536b3f41edSDimitry Andric assert(F.hasFnAttribute(Attribute::SafeStack) &&
7546b3f41edSDimitry Andric "Can't run SafeStack on a function without the attribute");
7556b3f41edSDimitry Andric assert(!F.isDeclaration() && "Can't run SafeStack on a function declaration");
75601095a5dSDimitry Andric
75701095a5dSDimitry Andric ++NumFunctions;
75801095a5dSDimitry Andric
75901095a5dSDimitry Andric SmallVector<AllocaInst *, 16> StaticAllocas;
76001095a5dSDimitry Andric SmallVector<AllocaInst *, 4> DynamicAllocas;
76101095a5dSDimitry Andric SmallVector<Argument *, 4> ByValArguments;
762b60736ecSDimitry Andric SmallVector<Instruction *, 4> Returns;
76301095a5dSDimitry Andric
76401095a5dSDimitry Andric // Collect all points where stack gets unwound and needs to be restored
76501095a5dSDimitry Andric // This is only necessary because the runtime (setjmp and unwind code) is
766b915e9e0SDimitry Andric // not aware of the unsafe stack and won't unwind/restore it properly.
76701095a5dSDimitry Andric // To work around this problem without changing the runtime, we insert
76801095a5dSDimitry Andric // instrumentation to restore the unsafe stack pointer when necessary.
76901095a5dSDimitry Andric SmallVector<Instruction *, 4> StackRestorePoints;
77001095a5dSDimitry Andric
77101095a5dSDimitry Andric // Find all static and dynamic alloca instructions that must be moved to the
77201095a5dSDimitry Andric // unsafe stack, all return instructions and stack restore points.
77301095a5dSDimitry Andric findInsts(F, StaticAllocas, DynamicAllocas, ByValArguments, Returns,
77401095a5dSDimitry Andric StackRestorePoints);
77501095a5dSDimitry Andric
77601095a5dSDimitry Andric if (StaticAllocas.empty() && DynamicAllocas.empty() &&
77701095a5dSDimitry Andric ByValArguments.empty() && StackRestorePoints.empty())
77801095a5dSDimitry Andric return false; // Nothing to do in this function.
77901095a5dSDimitry Andric
78001095a5dSDimitry Andric if (!StaticAllocas.empty() || !DynamicAllocas.empty() ||
78101095a5dSDimitry Andric !ByValArguments.empty())
78201095a5dSDimitry Andric ++NumUnsafeStackFunctions; // This function has the unsafe stack.
78301095a5dSDimitry Andric
78401095a5dSDimitry Andric if (!StackRestorePoints.empty())
78501095a5dSDimitry Andric ++NumUnsafeStackRestorePointsFunctions;
78601095a5dSDimitry Andric
78701095a5dSDimitry Andric IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt());
788d8e91e46SDimitry Andric // Calls must always have a debug location, or else inlining breaks. So
789d8e91e46SDimitry Andric // we explicitly set a artificial debug location here.
790d8e91e46SDimitry Andric if (DISubprogram *SP = F.getSubprogram())
791b60736ecSDimitry Andric IRB.SetCurrentDebugLocation(
792b60736ecSDimitry Andric DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP));
793eb11fae6SDimitry Andric if (SafeStackUsePointerAddress) {
794e6d15924SDimitry Andric FunctionCallee Fn = F.getParent()->getOrInsertFunction(
795b1c73532SDimitry Andric "__safestack_pointer_address", IRB.getPtrTy(0));
796eb11fae6SDimitry Andric UnsafeStackPtr = IRB.CreateCall(Fn);
797eb11fae6SDimitry Andric } else {
7986b3f41edSDimitry Andric UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB);
799eb11fae6SDimitry Andric }
80001095a5dSDimitry Andric
80101095a5dSDimitry Andric // Load the current stack pointer (we'll also use it as a base pointer).
80201095a5dSDimitry Andric // FIXME: use a dedicated register for it ?
80301095a5dSDimitry Andric Instruction *BasePointer =
804e6d15924SDimitry Andric IRB.CreateLoad(StackPtrTy, UnsafeStackPtr, false, "unsafe_stack_ptr");
80501095a5dSDimitry Andric assert(BasePointer->getType() == StackPtrTy);
80601095a5dSDimitry Andric
80701095a5dSDimitry Andric AllocaInst *StackGuardSlot = nullptr;
80801095a5dSDimitry Andric // FIXME: implement weaker forms of stack protector.
80901095a5dSDimitry Andric if (F.hasFnAttribute(Attribute::StackProtect) ||
81001095a5dSDimitry Andric F.hasFnAttribute(Attribute::StackProtectStrong) ||
81101095a5dSDimitry Andric F.hasFnAttribute(Attribute::StackProtectReq)) {
81201095a5dSDimitry Andric Value *StackGuard = getStackGuard(IRB, F);
81301095a5dSDimitry Andric StackGuardSlot = IRB.CreateAlloca(StackPtrTy, nullptr);
81401095a5dSDimitry Andric IRB.CreateStore(StackGuard, StackGuardSlot);
81501095a5dSDimitry Andric
816b60736ecSDimitry Andric for (Instruction *RI : Returns) {
81701095a5dSDimitry Andric IRBuilder<> IRBRet(RI);
81801095a5dSDimitry Andric checkStackGuard(IRBRet, F, *RI, StackGuardSlot, StackGuard);
81901095a5dSDimitry Andric }
82001095a5dSDimitry Andric }
82101095a5dSDimitry Andric
82201095a5dSDimitry Andric // The top of the unsafe stack after all unsafe static allocas are
82301095a5dSDimitry Andric // allocated.
824b60736ecSDimitry Andric Value *StaticTop = moveStaticAllocasToUnsafeStack(
825b60736ecSDimitry Andric IRB, F, StaticAllocas, ByValArguments, BasePointer, StackGuardSlot);
82601095a5dSDimitry Andric
82701095a5dSDimitry Andric // Safe stack object that stores the current unsafe stack top. It is updated
82801095a5dSDimitry Andric // as unsafe dynamic (non-constant-sized) allocas are allocated and freed.
82901095a5dSDimitry Andric // This is only needed if we need to restore stack pointer after longjmp
83001095a5dSDimitry Andric // or exceptions, and we have dynamic allocations.
83101095a5dSDimitry Andric // FIXME: a better alternative might be to store the unsafe stack pointer
83201095a5dSDimitry Andric // before setjmp / invoke instructions.
83301095a5dSDimitry Andric AllocaInst *DynamicTop = createStackRestorePoints(
83401095a5dSDimitry Andric IRB, F, StackRestorePoints, StaticTop, !DynamicAllocas.empty());
83501095a5dSDimitry Andric
83601095a5dSDimitry Andric // Handle dynamic allocas.
83701095a5dSDimitry Andric moveDynamicAllocasToUnsafeStack(F, UnsafeStackPtr, DynamicTop,
83801095a5dSDimitry Andric DynamicAllocas);
83901095a5dSDimitry Andric
84001095a5dSDimitry Andric // Restore the unsafe stack pointer before each return.
841b60736ecSDimitry Andric for (Instruction *RI : Returns) {
84201095a5dSDimitry Andric IRB.SetInsertPoint(RI);
84301095a5dSDimitry Andric IRB.CreateStore(BasePointer, UnsafeStackPtr);
84401095a5dSDimitry Andric }
84501095a5dSDimitry Andric
846eb11fae6SDimitry Andric TryInlinePointerAddress();
847eb11fae6SDimitry Andric
848eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] safestack applied\n");
84901095a5dSDimitry Andric return true;
85001095a5dSDimitry Andric }
85101095a5dSDimitry Andric
8526b3f41edSDimitry Andric class SafeStackLegacyPass : public FunctionPass {
853044eb2f6SDimitry Andric const TargetMachine *TM = nullptr;
8546b3f41edSDimitry Andric
8556b3f41edSDimitry Andric public:
8566b3f41edSDimitry Andric static char ID; // Pass identification, replacement for typeid..
857044eb2f6SDimitry Andric
SafeStackLegacyPass()858044eb2f6SDimitry Andric SafeStackLegacyPass() : FunctionPass(ID) {
8596b3f41edSDimitry Andric initializeSafeStackLegacyPassPass(*PassRegistry::getPassRegistry());
8606b3f41edSDimitry Andric }
8616b3f41edSDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const8626b3f41edSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
863b5630dbaSDimitry Andric AU.addRequired<TargetPassConfig>();
8646b3f41edSDimitry Andric AU.addRequired<TargetLibraryInfoWrapperPass>();
8656b3f41edSDimitry Andric AU.addRequired<AssumptionCacheTracker>();
866344a3780SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>();
8676b3f41edSDimitry Andric }
8686b3f41edSDimitry Andric
runOnFunction(Function & F)8696b3f41edSDimitry Andric bool runOnFunction(Function &F) override {
870eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n");
8716b3f41edSDimitry Andric
8726b3f41edSDimitry Andric if (!F.hasFnAttribute(Attribute::SafeStack)) {
873eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] safestack is not requested"
8746b3f41edSDimitry Andric " for this function\n");
8756b3f41edSDimitry Andric return false;
8766b3f41edSDimitry Andric }
8776b3f41edSDimitry Andric
8786b3f41edSDimitry Andric if (F.isDeclaration()) {
879eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] function definition"
8806b3f41edSDimitry Andric " is not available\n");
8816b3f41edSDimitry Andric return false;
8826b3f41edSDimitry Andric }
8836b3f41edSDimitry Andric
884b5630dbaSDimitry Andric TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
8856b3f41edSDimitry Andric auto *TL = TM->getSubtargetImpl(F)->getTargetLowering();
8866b3f41edSDimitry Andric if (!TL)
8876b3f41edSDimitry Andric report_fatal_error("TargetLowering instance is required");
8886b3f41edSDimitry Andric
889ac9a064cSDimitry Andric auto *DL = &F.getDataLayout();
8901d5ae102SDimitry Andric auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
8916b3f41edSDimitry Andric auto &ACT = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
8926b3f41edSDimitry Andric
8936b3f41edSDimitry Andric // Compute DT and LI only for functions that have the attribute.
8946b3f41edSDimitry Andric // This is only useful because the legacy pass manager doesn't let us
8956b3f41edSDimitry Andric // compute analyzes lazily.
8966b3f41edSDimitry Andric
897344a3780SDimitry Andric DominatorTree *DT;
898344a3780SDimitry Andric bool ShouldPreserveDominatorTree;
899e3b55780SDimitry Andric std::optional<DominatorTree> LazilyComputedDomTree;
9006b3f41edSDimitry Andric
901344a3780SDimitry Andric // Do we already have a DominatorTree avaliable from the previous pass?
902344a3780SDimitry Andric // Note that we should *NOT* require it, to avoid the case where we end up
903344a3780SDimitry Andric // not needing it, but the legacy PM would have computed it for us anyways.
904344a3780SDimitry Andric if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) {
905344a3780SDimitry Andric DT = &DTWP->getDomTree();
906344a3780SDimitry Andric ShouldPreserveDominatorTree = true;
907344a3780SDimitry Andric } else {
908344a3780SDimitry Andric // Otherwise, we need to compute it.
909344a3780SDimitry Andric LazilyComputedDomTree.emplace(F);
910e3b55780SDimitry Andric DT = &*LazilyComputedDomTree;
911344a3780SDimitry Andric ShouldPreserveDominatorTree = false;
912344a3780SDimitry Andric }
913344a3780SDimitry Andric
914344a3780SDimitry Andric // Likewise, lazily compute loop info.
915344a3780SDimitry Andric LoopInfo LI(*DT);
916344a3780SDimitry Andric
917344a3780SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
918344a3780SDimitry Andric
919344a3780SDimitry Andric ScalarEvolution SE(F, TLI, ACT, *DT, LI);
920344a3780SDimitry Andric
921344a3780SDimitry Andric return SafeStack(F, *TL, *DL, ShouldPreserveDominatorTree ? &DTU : nullptr,
922344a3780SDimitry Andric SE)
923344a3780SDimitry Andric .run();
9246b3f41edSDimitry Andric }
9256b3f41edSDimitry Andric };
9266b3f41edSDimitry Andric
927044eb2f6SDimitry Andric } // end anonymous namespace
92801095a5dSDimitry Andric
run(Function & F,FunctionAnalysisManager & FAM)929b1c73532SDimitry Andric PreservedAnalyses SafeStackPass::run(Function &F,
930b1c73532SDimitry Andric FunctionAnalysisManager &FAM) {
931b1c73532SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n");
932b1c73532SDimitry Andric
933b1c73532SDimitry Andric if (!F.hasFnAttribute(Attribute::SafeStack)) {
934b1c73532SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] safestack is not requested"
935b1c73532SDimitry Andric " for this function\n");
936b1c73532SDimitry Andric return PreservedAnalyses::all();
937b1c73532SDimitry Andric }
938b1c73532SDimitry Andric
939b1c73532SDimitry Andric if (F.isDeclaration()) {
940b1c73532SDimitry Andric LLVM_DEBUG(dbgs() << "[SafeStack] function definition"
941b1c73532SDimitry Andric " is not available\n");
942b1c73532SDimitry Andric return PreservedAnalyses::all();
943b1c73532SDimitry Andric }
944b1c73532SDimitry Andric
945b1c73532SDimitry Andric auto *TL = TM->getSubtargetImpl(F)->getTargetLowering();
946b1c73532SDimitry Andric if (!TL)
947b1c73532SDimitry Andric report_fatal_error("TargetLowering instance is required");
948b1c73532SDimitry Andric
949ac9a064cSDimitry Andric auto &DL = F.getDataLayout();
950b1c73532SDimitry Andric
951b1c73532SDimitry Andric // preserve DominatorTree
952b1c73532SDimitry Andric auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
953b1c73532SDimitry Andric auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
954b1c73532SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
955b1c73532SDimitry Andric
956b1c73532SDimitry Andric bool Changed = SafeStack(F, *TL, DL, &DTU, SE).run();
957b1c73532SDimitry Andric
958b1c73532SDimitry Andric if (!Changed)
959b1c73532SDimitry Andric return PreservedAnalyses::all();
960b1c73532SDimitry Andric PreservedAnalyses PA;
961b1c73532SDimitry Andric PA.preserve<DominatorTreeAnalysis>();
962b1c73532SDimitry Andric return PA;
963b1c73532SDimitry Andric }
964b1c73532SDimitry Andric
9656b3f41edSDimitry Andric char SafeStackLegacyPass::ID = 0;
966044eb2f6SDimitry Andric
967ab44ce3dSDimitry Andric INITIALIZE_PASS_BEGIN(SafeStackLegacyPass, DEBUG_TYPE,
96801095a5dSDimitry Andric "Safe Stack instrumentation pass", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)969b5630dbaSDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
970344a3780SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
971ab44ce3dSDimitry Andric INITIALIZE_PASS_END(SafeStackLegacyPass, DEBUG_TYPE,
97201095a5dSDimitry Andric "Safe Stack instrumentation pass", false, false)
97301095a5dSDimitry Andric
974b5630dbaSDimitry Andric FunctionPass *llvm::createSafeStackPass() { return new SafeStackLegacyPass(); }
975