xref: /aosp_15_r20/external/llvm/lib/CodeGen/ShadowStackGCLowering.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- ShadowStackGCLowering.cpp - Custom lowering for shadow-stack gc ---===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains the custom lowering code required by the shadow-stack GC
11*9880d681SAndroid Build Coastguard Worker // strategy.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker // This pass implements the code transformation described in this paper:
14*9880d681SAndroid Build Coastguard Worker //   "Accurate Garbage Collection in an Uncooperative Environment"
15*9880d681SAndroid Build Coastguard Worker //   Fergus Henderson, ISMM, 2002
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*9880d681SAndroid Build Coastguard Worker 
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/GCStrategy.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallSite.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "shadowstackgclowering"
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker namespace {
32*9880d681SAndroid Build Coastguard Worker 
33*9880d681SAndroid Build Coastguard Worker class ShadowStackGCLowering : public FunctionPass {
34*9880d681SAndroid Build Coastguard Worker   /// RootChain - This is the global linked-list that contains the chain of GC
35*9880d681SAndroid Build Coastguard Worker   /// roots.
36*9880d681SAndroid Build Coastguard Worker   GlobalVariable *Head;
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker   /// StackEntryTy - Abstract type of a link in the shadow stack.
39*9880d681SAndroid Build Coastguard Worker   ///
40*9880d681SAndroid Build Coastguard Worker   StructType *StackEntryTy;
41*9880d681SAndroid Build Coastguard Worker   StructType *FrameMapTy;
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   /// Roots - GC roots in the current function. Each is a pair of the
44*9880d681SAndroid Build Coastguard Worker   /// intrinsic call and its corresponding alloca.
45*9880d681SAndroid Build Coastguard Worker   std::vector<std::pair<CallInst *, AllocaInst *>> Roots;
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker public:
48*9880d681SAndroid Build Coastguard Worker   static char ID;
49*9880d681SAndroid Build Coastguard Worker   ShadowStackGCLowering();
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker   bool doInitialization(Module &M) override;
52*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function &F) override;
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker private:
55*9880d681SAndroid Build Coastguard Worker   bool IsNullValue(Value *V);
56*9880d681SAndroid Build Coastguard Worker   Constant *GetFrameMap(Function &F);
57*9880d681SAndroid Build Coastguard Worker   Type *GetConcreteStackEntryType(Function &F);
58*9880d681SAndroid Build Coastguard Worker   void CollectRoots(Function &F);
59*9880d681SAndroid Build Coastguard Worker   static GetElementPtrInst *CreateGEP(LLVMContext &Context, IRBuilder<> &B,
60*9880d681SAndroid Build Coastguard Worker                                       Type *Ty, Value *BasePtr, int Idx1,
61*9880d681SAndroid Build Coastguard Worker                                       const char *Name);
62*9880d681SAndroid Build Coastguard Worker   static GetElementPtrInst *CreateGEP(LLVMContext &Context, IRBuilder<> &B,
63*9880d681SAndroid Build Coastguard Worker                                       Type *Ty, Value *BasePtr, int Idx1, int Idx2,
64*9880d681SAndroid Build Coastguard Worker                                       const char *Name);
65*9880d681SAndroid Build Coastguard Worker };
66*9880d681SAndroid Build Coastguard Worker }
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(ShadowStackGCLowering, "shadow-stack-gc-lowering",
69*9880d681SAndroid Build Coastguard Worker                       "Shadow Stack GC Lowering", false, false)
INITIALIZE_PASS_DEPENDENCY(GCModuleInfo)70*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(GCModuleInfo)
71*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(ShadowStackGCLowering, "shadow-stack-gc-lowering",
72*9880d681SAndroid Build Coastguard Worker                     "Shadow Stack GC Lowering", false, false)
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createShadowStackGCLoweringPass() { return new ShadowStackGCLowering(); }
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker char ShadowStackGCLowering::ID = 0;
77*9880d681SAndroid Build Coastguard Worker 
ShadowStackGCLowering()78*9880d681SAndroid Build Coastguard Worker ShadowStackGCLowering::ShadowStackGCLowering()
79*9880d681SAndroid Build Coastguard Worker   : FunctionPass(ID), Head(nullptr), StackEntryTy(nullptr),
80*9880d681SAndroid Build Coastguard Worker     FrameMapTy(nullptr) {
81*9880d681SAndroid Build Coastguard Worker   initializeShadowStackGCLoweringPass(*PassRegistry::getPassRegistry());
82*9880d681SAndroid Build Coastguard Worker }
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker namespace {
85*9880d681SAndroid Build Coastguard Worker /// EscapeEnumerator - This is a little algorithm to find all escape points
86*9880d681SAndroid Build Coastguard Worker /// from a function so that "finally"-style code can be inserted. In addition
87*9880d681SAndroid Build Coastguard Worker /// to finding the existing return and unwind instructions, it also (if
88*9880d681SAndroid Build Coastguard Worker /// necessary) transforms any call instructions into invokes and sends them to
89*9880d681SAndroid Build Coastguard Worker /// a landing pad.
90*9880d681SAndroid Build Coastguard Worker ///
91*9880d681SAndroid Build Coastguard Worker /// It's wrapped up in a state machine using the same transform C# uses for
92*9880d681SAndroid Build Coastguard Worker /// 'yield return' enumerators, This transform allows it to be non-allocating.
93*9880d681SAndroid Build Coastguard Worker class EscapeEnumerator {
94*9880d681SAndroid Build Coastguard Worker   Function &F;
95*9880d681SAndroid Build Coastguard Worker   const char *CleanupBBName;
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   // State.
98*9880d681SAndroid Build Coastguard Worker   int State;
99*9880d681SAndroid Build Coastguard Worker   Function::iterator StateBB, StateE;
100*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder;
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker public:
EscapeEnumerator(Function & F,const char * N="cleanup")103*9880d681SAndroid Build Coastguard Worker   EscapeEnumerator(Function &F, const char *N = "cleanup")
104*9880d681SAndroid Build Coastguard Worker       : F(F), CleanupBBName(N), State(0), Builder(F.getContext()) {}
105*9880d681SAndroid Build Coastguard Worker 
Next()106*9880d681SAndroid Build Coastguard Worker   IRBuilder<> *Next() {
107*9880d681SAndroid Build Coastguard Worker     switch (State) {
108*9880d681SAndroid Build Coastguard Worker     default:
109*9880d681SAndroid Build Coastguard Worker       return nullptr;
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker     case 0:
112*9880d681SAndroid Build Coastguard Worker       StateBB = F.begin();
113*9880d681SAndroid Build Coastguard Worker       StateE = F.end();
114*9880d681SAndroid Build Coastguard Worker       State = 1;
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker     case 1:
117*9880d681SAndroid Build Coastguard Worker       // Find all 'return', 'resume', and 'unwind' instructions.
118*9880d681SAndroid Build Coastguard Worker       while (StateBB != StateE) {
119*9880d681SAndroid Build Coastguard Worker         BasicBlock *CurBB = &*StateBB++;
120*9880d681SAndroid Build Coastguard Worker 
121*9880d681SAndroid Build Coastguard Worker         // Branches and invokes do not escape, only unwind, resume, and return
122*9880d681SAndroid Build Coastguard Worker         // do.
123*9880d681SAndroid Build Coastguard Worker         TerminatorInst *TI = CurBB->getTerminator();
124*9880d681SAndroid Build Coastguard Worker         if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI))
125*9880d681SAndroid Build Coastguard Worker           continue;
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker         Builder.SetInsertPoint(TI);
128*9880d681SAndroid Build Coastguard Worker         return &Builder;
129*9880d681SAndroid Build Coastguard Worker       }
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker       State = 2;
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker       // Find all 'call' instructions.
134*9880d681SAndroid Build Coastguard Worker       SmallVector<Instruction *, 16> Calls;
135*9880d681SAndroid Build Coastguard Worker       for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
136*9880d681SAndroid Build Coastguard Worker         for (BasicBlock::iterator II = BB->begin(), EE = BB->end(); II != EE;
137*9880d681SAndroid Build Coastguard Worker              ++II)
138*9880d681SAndroid Build Coastguard Worker           if (CallInst *CI = dyn_cast<CallInst>(II))
139*9880d681SAndroid Build Coastguard Worker             if (!CI->getCalledFunction() ||
140*9880d681SAndroid Build Coastguard Worker                 !CI->getCalledFunction()->getIntrinsicID())
141*9880d681SAndroid Build Coastguard Worker               Calls.push_back(CI);
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker       if (Calls.empty())
144*9880d681SAndroid Build Coastguard Worker         return nullptr;
145*9880d681SAndroid Build Coastguard Worker 
146*9880d681SAndroid Build Coastguard Worker       // Create a cleanup block.
147*9880d681SAndroid Build Coastguard Worker       LLVMContext &C = F.getContext();
148*9880d681SAndroid Build Coastguard Worker       BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F);
149*9880d681SAndroid Build Coastguard Worker       Type *ExnTy =
150*9880d681SAndroid Build Coastguard Worker           StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C), nullptr);
151*9880d681SAndroid Build Coastguard Worker       if (!F.hasPersonalityFn()) {
152*9880d681SAndroid Build Coastguard Worker         Constant *PersFn = F.getParent()->getOrInsertFunction(
153*9880d681SAndroid Build Coastguard Worker             "__gcc_personality_v0",
154*9880d681SAndroid Build Coastguard Worker             FunctionType::get(Type::getInt32Ty(C), true));
155*9880d681SAndroid Build Coastguard Worker         F.setPersonalityFn(PersFn);
156*9880d681SAndroid Build Coastguard Worker       }
157*9880d681SAndroid Build Coastguard Worker       LandingPadInst *LPad =
158*9880d681SAndroid Build Coastguard Worker           LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);
159*9880d681SAndroid Build Coastguard Worker       LPad->setCleanup(true);
160*9880d681SAndroid Build Coastguard Worker       ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker       // Transform the 'call' instructions into 'invoke's branching to the
163*9880d681SAndroid Build Coastguard Worker       // cleanup block. Go in reverse order to make prettier BB names.
164*9880d681SAndroid Build Coastguard Worker       SmallVector<Value *, 16> Args;
165*9880d681SAndroid Build Coastguard Worker       for (unsigned I = Calls.size(); I != 0;) {
166*9880d681SAndroid Build Coastguard Worker         CallInst *CI = cast<CallInst>(Calls[--I]);
167*9880d681SAndroid Build Coastguard Worker 
168*9880d681SAndroid Build Coastguard Worker         // Split the basic block containing the function call.
169*9880d681SAndroid Build Coastguard Worker         BasicBlock *CallBB = CI->getParent();
170*9880d681SAndroid Build Coastguard Worker         BasicBlock *NewBB = CallBB->splitBasicBlock(
171*9880d681SAndroid Build Coastguard Worker             CI->getIterator(), CallBB->getName() + ".cont");
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker         // Remove the unconditional branch inserted at the end of CallBB.
174*9880d681SAndroid Build Coastguard Worker         CallBB->getInstList().pop_back();
175*9880d681SAndroid Build Coastguard Worker         NewBB->getInstList().remove(CI);
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker         // Create a new invoke instruction.
178*9880d681SAndroid Build Coastguard Worker         Args.clear();
179*9880d681SAndroid Build Coastguard Worker         CallSite CS(CI);
180*9880d681SAndroid Build Coastguard Worker         Args.append(CS.arg_begin(), CS.arg_end());
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker         InvokeInst *II =
183*9880d681SAndroid Build Coastguard Worker             InvokeInst::Create(CI->getCalledValue(), NewBB, CleanupBB, Args,
184*9880d681SAndroid Build Coastguard Worker                                CI->getName(), CallBB);
185*9880d681SAndroid Build Coastguard Worker         II->setCallingConv(CI->getCallingConv());
186*9880d681SAndroid Build Coastguard Worker         II->setAttributes(CI->getAttributes());
187*9880d681SAndroid Build Coastguard Worker         CI->replaceAllUsesWith(II);
188*9880d681SAndroid Build Coastguard Worker         delete CI;
189*9880d681SAndroid Build Coastguard Worker       }
190*9880d681SAndroid Build Coastguard Worker 
191*9880d681SAndroid Build Coastguard Worker       Builder.SetInsertPoint(RI);
192*9880d681SAndroid Build Coastguard Worker       return &Builder;
193*9880d681SAndroid Build Coastguard Worker     }
194*9880d681SAndroid Build Coastguard Worker   }
195*9880d681SAndroid Build Coastguard Worker };
196*9880d681SAndroid Build Coastguard Worker }
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker 
GetFrameMap(Function & F)199*9880d681SAndroid Build Coastguard Worker Constant *ShadowStackGCLowering::GetFrameMap(Function &F) {
200*9880d681SAndroid Build Coastguard Worker   // doInitialization creates the abstract type of this value.
201*9880d681SAndroid Build Coastguard Worker   Type *VoidPtr = Type::getInt8PtrTy(F.getContext());
202*9880d681SAndroid Build Coastguard Worker 
203*9880d681SAndroid Build Coastguard Worker   // Truncate the ShadowStackDescriptor if some metadata is null.
204*9880d681SAndroid Build Coastguard Worker   unsigned NumMeta = 0;
205*9880d681SAndroid Build Coastguard Worker   SmallVector<Constant *, 16> Metadata;
206*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I != Roots.size(); ++I) {
207*9880d681SAndroid Build Coastguard Worker     Constant *C = cast<Constant>(Roots[I].first->getArgOperand(1));
208*9880d681SAndroid Build Coastguard Worker     if (!C->isNullValue())
209*9880d681SAndroid Build Coastguard Worker       NumMeta = I + 1;
210*9880d681SAndroid Build Coastguard Worker     Metadata.push_back(ConstantExpr::getBitCast(C, VoidPtr));
211*9880d681SAndroid Build Coastguard Worker   }
212*9880d681SAndroid Build Coastguard Worker   Metadata.resize(NumMeta);
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker   Type *Int32Ty = Type::getInt32Ty(F.getContext());
215*9880d681SAndroid Build Coastguard Worker 
216*9880d681SAndroid Build Coastguard Worker   Constant *BaseElts[] = {
217*9880d681SAndroid Build Coastguard Worker       ConstantInt::get(Int32Ty, Roots.size(), false),
218*9880d681SAndroid Build Coastguard Worker       ConstantInt::get(Int32Ty, NumMeta, false),
219*9880d681SAndroid Build Coastguard Worker   };
220*9880d681SAndroid Build Coastguard Worker 
221*9880d681SAndroid Build Coastguard Worker   Constant *DescriptorElts[] = {
222*9880d681SAndroid Build Coastguard Worker       ConstantStruct::get(FrameMapTy, BaseElts),
223*9880d681SAndroid Build Coastguard Worker       ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), Metadata)};
224*9880d681SAndroid Build Coastguard Worker 
225*9880d681SAndroid Build Coastguard Worker   Type *EltTys[] = {DescriptorElts[0]->getType(), DescriptorElts[1]->getType()};
226*9880d681SAndroid Build Coastguard Worker   StructType *STy = StructType::create(EltTys, "gc_map." + utostr(NumMeta));
227*9880d681SAndroid Build Coastguard Worker 
228*9880d681SAndroid Build Coastguard Worker   Constant *FrameMap = ConstantStruct::get(STy, DescriptorElts);
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker   // FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems
231*9880d681SAndroid Build Coastguard Worker   //        that, short of multithreaded LLVM, it should be safe; all that is
232*9880d681SAndroid Build Coastguard Worker   //        necessary is that a simple Module::iterator loop not be invalidated.
233*9880d681SAndroid Build Coastguard Worker   //        Appending to the GlobalVariable list is safe in that sense.
234*9880d681SAndroid Build Coastguard Worker   //
235*9880d681SAndroid Build Coastguard Worker   //        All of the output passes emit globals last. The ExecutionEngine
236*9880d681SAndroid Build Coastguard Worker   //        explicitly supports adding globals to the module after
237*9880d681SAndroid Build Coastguard Worker   //        initialization.
238*9880d681SAndroid Build Coastguard Worker   //
239*9880d681SAndroid Build Coastguard Worker   //        Still, if it isn't deemed acceptable, then this transformation needs
240*9880d681SAndroid Build Coastguard Worker   //        to be a ModulePass (which means it cannot be in the 'llc' pipeline
241*9880d681SAndroid Build Coastguard Worker   //        (which uses a FunctionPassManager (which segfaults (not asserts) if
242*9880d681SAndroid Build Coastguard Worker   //        provided a ModulePass))).
243*9880d681SAndroid Build Coastguard Worker   Constant *GV = new GlobalVariable(*F.getParent(), FrameMap->getType(), true,
244*9880d681SAndroid Build Coastguard Worker                                     GlobalVariable::InternalLinkage, FrameMap,
245*9880d681SAndroid Build Coastguard Worker                                     "__gc_" + F.getName());
246*9880d681SAndroid Build Coastguard Worker 
247*9880d681SAndroid Build Coastguard Worker   Constant *GEPIndices[2] = {
248*9880d681SAndroid Build Coastguard Worker       ConstantInt::get(Type::getInt32Ty(F.getContext()), 0),
249*9880d681SAndroid Build Coastguard Worker       ConstantInt::get(Type::getInt32Ty(F.getContext()), 0)};
250*9880d681SAndroid Build Coastguard Worker   return ConstantExpr::getGetElementPtr(FrameMap->getType(), GV, GEPIndices);
251*9880d681SAndroid Build Coastguard Worker }
252*9880d681SAndroid Build Coastguard Worker 
GetConcreteStackEntryType(Function & F)253*9880d681SAndroid Build Coastguard Worker Type *ShadowStackGCLowering::GetConcreteStackEntryType(Function &F) {
254*9880d681SAndroid Build Coastguard Worker   // doInitialization creates the generic version of this type.
255*9880d681SAndroid Build Coastguard Worker   std::vector<Type *> EltTys;
256*9880d681SAndroid Build Coastguard Worker   EltTys.push_back(StackEntryTy);
257*9880d681SAndroid Build Coastguard Worker   for (size_t I = 0; I != Roots.size(); I++)
258*9880d681SAndroid Build Coastguard Worker     EltTys.push_back(Roots[I].second->getAllocatedType());
259*9880d681SAndroid Build Coastguard Worker 
260*9880d681SAndroid Build Coastguard Worker   return StructType::create(EltTys, ("gc_stackentry." + F.getName()).str());
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker /// doInitialization - If this module uses the GC intrinsics, find them now. If
264*9880d681SAndroid Build Coastguard Worker /// not, exit fast.
doInitialization(Module & M)265*9880d681SAndroid Build Coastguard Worker bool ShadowStackGCLowering::doInitialization(Module &M) {
266*9880d681SAndroid Build Coastguard Worker   bool Active = false;
267*9880d681SAndroid Build Coastguard Worker   for (Function &F : M) {
268*9880d681SAndroid Build Coastguard Worker     if (F.hasGC() && F.getGC() == std::string("shadow-stack")) {
269*9880d681SAndroid Build Coastguard Worker       Active = true;
270*9880d681SAndroid Build Coastguard Worker       break;
271*9880d681SAndroid Build Coastguard Worker     }
272*9880d681SAndroid Build Coastguard Worker   }
273*9880d681SAndroid Build Coastguard Worker   if (!Active)
274*9880d681SAndroid Build Coastguard Worker     return false;
275*9880d681SAndroid Build Coastguard Worker 
276*9880d681SAndroid Build Coastguard Worker   // struct FrameMap {
277*9880d681SAndroid Build Coastguard Worker   //   int32_t NumRoots; // Number of roots in stack frame.
278*9880d681SAndroid Build Coastguard Worker   //   int32_t NumMeta;  // Number of metadata descriptors. May be < NumRoots.
279*9880d681SAndroid Build Coastguard Worker   //   void *Meta[];     // May be absent for roots without metadata.
280*9880d681SAndroid Build Coastguard Worker   // };
281*9880d681SAndroid Build Coastguard Worker   std::vector<Type *> EltTys;
282*9880d681SAndroid Build Coastguard Worker   // 32 bits is ok up to a 32GB stack frame. :)
283*9880d681SAndroid Build Coastguard Worker   EltTys.push_back(Type::getInt32Ty(M.getContext()));
284*9880d681SAndroid Build Coastguard Worker   // Specifies length of variable length array.
285*9880d681SAndroid Build Coastguard Worker   EltTys.push_back(Type::getInt32Ty(M.getContext()));
286*9880d681SAndroid Build Coastguard Worker   FrameMapTy = StructType::create(EltTys, "gc_map");
287*9880d681SAndroid Build Coastguard Worker   PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy);
288*9880d681SAndroid Build Coastguard Worker 
289*9880d681SAndroid Build Coastguard Worker   // struct StackEntry {
290*9880d681SAndroid Build Coastguard Worker   //   ShadowStackEntry *Next; // Caller's stack entry.
291*9880d681SAndroid Build Coastguard Worker   //   FrameMap *Map;          // Pointer to constant FrameMap.
292*9880d681SAndroid Build Coastguard Worker   //   void *Roots[];          // Stack roots (in-place array, so we pretend).
293*9880d681SAndroid Build Coastguard Worker   // };
294*9880d681SAndroid Build Coastguard Worker 
295*9880d681SAndroid Build Coastguard Worker   StackEntryTy = StructType::create(M.getContext(), "gc_stackentry");
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker   EltTys.clear();
298*9880d681SAndroid Build Coastguard Worker   EltTys.push_back(PointerType::getUnqual(StackEntryTy));
299*9880d681SAndroid Build Coastguard Worker   EltTys.push_back(FrameMapPtrTy);
300*9880d681SAndroid Build Coastguard Worker   StackEntryTy->setBody(EltTys);
301*9880d681SAndroid Build Coastguard Worker   PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy);
302*9880d681SAndroid Build Coastguard Worker 
303*9880d681SAndroid Build Coastguard Worker   // Get the root chain if it already exists.
304*9880d681SAndroid Build Coastguard Worker   Head = M.getGlobalVariable("llvm_gc_root_chain");
305*9880d681SAndroid Build Coastguard Worker   if (!Head) {
306*9880d681SAndroid Build Coastguard Worker     // If the root chain does not exist, insert a new one with linkonce
307*9880d681SAndroid Build Coastguard Worker     // linkage!
308*9880d681SAndroid Build Coastguard Worker     Head = new GlobalVariable(
309*9880d681SAndroid Build Coastguard Worker         M, StackEntryPtrTy, false, GlobalValue::LinkOnceAnyLinkage,
310*9880d681SAndroid Build Coastguard Worker         Constant::getNullValue(StackEntryPtrTy), "llvm_gc_root_chain");
311*9880d681SAndroid Build Coastguard Worker   } else if (Head->hasExternalLinkage() && Head->isDeclaration()) {
312*9880d681SAndroid Build Coastguard Worker     Head->setInitializer(Constant::getNullValue(StackEntryPtrTy));
313*9880d681SAndroid Build Coastguard Worker     Head->setLinkage(GlobalValue::LinkOnceAnyLinkage);
314*9880d681SAndroid Build Coastguard Worker   }
315*9880d681SAndroid Build Coastguard Worker 
316*9880d681SAndroid Build Coastguard Worker   return true;
317*9880d681SAndroid Build Coastguard Worker }
318*9880d681SAndroid Build Coastguard Worker 
IsNullValue(Value * V)319*9880d681SAndroid Build Coastguard Worker bool ShadowStackGCLowering::IsNullValue(Value *V) {
320*9880d681SAndroid Build Coastguard Worker   if (Constant *C = dyn_cast<Constant>(V))
321*9880d681SAndroid Build Coastguard Worker     return C->isNullValue();
322*9880d681SAndroid Build Coastguard Worker   return false;
323*9880d681SAndroid Build Coastguard Worker }
324*9880d681SAndroid Build Coastguard Worker 
CollectRoots(Function & F)325*9880d681SAndroid Build Coastguard Worker void ShadowStackGCLowering::CollectRoots(Function &F) {
326*9880d681SAndroid Build Coastguard Worker   // FIXME: Account for original alignment. Could fragment the root array.
327*9880d681SAndroid Build Coastguard Worker   //   Approach 1: Null initialize empty slots at runtime. Yuck.
328*9880d681SAndroid Build Coastguard Worker   //   Approach 2: Emit a map of the array instead of just a count.
329*9880d681SAndroid Build Coastguard Worker 
330*9880d681SAndroid Build Coastguard Worker   assert(Roots.empty() && "Not cleaned up?");
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<CallInst *, AllocaInst *>, 16> MetaRoots;
333*9880d681SAndroid Build Coastguard Worker 
334*9880d681SAndroid Build Coastguard Worker   for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
335*9880d681SAndroid Build Coastguard Worker     for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;)
336*9880d681SAndroid Build Coastguard Worker       if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++))
337*9880d681SAndroid Build Coastguard Worker         if (Function *F = CI->getCalledFunction())
338*9880d681SAndroid Build Coastguard Worker           if (F->getIntrinsicID() == Intrinsic::gcroot) {
339*9880d681SAndroid Build Coastguard Worker             std::pair<CallInst *, AllocaInst *> Pair = std::make_pair(
340*9880d681SAndroid Build Coastguard Worker                 CI,
341*9880d681SAndroid Build Coastguard Worker                 cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts()));
342*9880d681SAndroid Build Coastguard Worker             if (IsNullValue(CI->getArgOperand(1)))
343*9880d681SAndroid Build Coastguard Worker               Roots.push_back(Pair);
344*9880d681SAndroid Build Coastguard Worker             else
345*9880d681SAndroid Build Coastguard Worker               MetaRoots.push_back(Pair);
346*9880d681SAndroid Build Coastguard Worker           }
347*9880d681SAndroid Build Coastguard Worker 
348*9880d681SAndroid Build Coastguard Worker   // Number roots with metadata (usually empty) at the beginning, so that the
349*9880d681SAndroid Build Coastguard Worker   // FrameMap::Meta array can be elided.
350*9880d681SAndroid Build Coastguard Worker   Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end());
351*9880d681SAndroid Build Coastguard Worker }
352*9880d681SAndroid Build Coastguard Worker 
CreateGEP(LLVMContext & Context,IRBuilder<> & B,Type * Ty,Value * BasePtr,int Idx,int Idx2,const char * Name)353*9880d681SAndroid Build Coastguard Worker GetElementPtrInst *ShadowStackGCLowering::CreateGEP(LLVMContext &Context,
354*9880d681SAndroid Build Coastguard Worker                                                     IRBuilder<> &B, Type *Ty,
355*9880d681SAndroid Build Coastguard Worker                                                     Value *BasePtr, int Idx,
356*9880d681SAndroid Build Coastguard Worker                                                     int Idx2,
357*9880d681SAndroid Build Coastguard Worker                                                     const char *Name) {
358*9880d681SAndroid Build Coastguard Worker   Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
359*9880d681SAndroid Build Coastguard Worker                       ConstantInt::get(Type::getInt32Ty(Context), Idx),
360*9880d681SAndroid Build Coastguard Worker                       ConstantInt::get(Type::getInt32Ty(Context), Idx2)};
361*9880d681SAndroid Build Coastguard Worker   Value *Val = B.CreateGEP(Ty, BasePtr, Indices, Name);
362*9880d681SAndroid Build Coastguard Worker 
363*9880d681SAndroid Build Coastguard Worker   assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant");
364*9880d681SAndroid Build Coastguard Worker 
365*9880d681SAndroid Build Coastguard Worker   return dyn_cast<GetElementPtrInst>(Val);
366*9880d681SAndroid Build Coastguard Worker }
367*9880d681SAndroid Build Coastguard Worker 
CreateGEP(LLVMContext & Context,IRBuilder<> & B,Type * Ty,Value * BasePtr,int Idx,const char * Name)368*9880d681SAndroid Build Coastguard Worker GetElementPtrInst *ShadowStackGCLowering::CreateGEP(LLVMContext &Context,
369*9880d681SAndroid Build Coastguard Worker                                             IRBuilder<> &B, Type *Ty, Value *BasePtr,
370*9880d681SAndroid Build Coastguard Worker                                             int Idx, const char *Name) {
371*9880d681SAndroid Build Coastguard Worker   Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
372*9880d681SAndroid Build Coastguard Worker                       ConstantInt::get(Type::getInt32Ty(Context), Idx)};
373*9880d681SAndroid Build Coastguard Worker   Value *Val = B.CreateGEP(Ty, BasePtr, Indices, Name);
374*9880d681SAndroid Build Coastguard Worker 
375*9880d681SAndroid Build Coastguard Worker   assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant");
376*9880d681SAndroid Build Coastguard Worker 
377*9880d681SAndroid Build Coastguard Worker   return dyn_cast<GetElementPtrInst>(Val);
378*9880d681SAndroid Build Coastguard Worker }
379*9880d681SAndroid Build Coastguard Worker 
380*9880d681SAndroid Build Coastguard Worker /// runOnFunction - Insert code to maintain the shadow stack.
runOnFunction(Function & F)381*9880d681SAndroid Build Coastguard Worker bool ShadowStackGCLowering::runOnFunction(Function &F) {
382*9880d681SAndroid Build Coastguard Worker   // Quick exit for functions that do not use the shadow stack GC.
383*9880d681SAndroid Build Coastguard Worker   if (!F.hasGC() ||
384*9880d681SAndroid Build Coastguard Worker       F.getGC() != std::string("shadow-stack"))
385*9880d681SAndroid Build Coastguard Worker     return false;
386*9880d681SAndroid Build Coastguard Worker 
387*9880d681SAndroid Build Coastguard Worker   LLVMContext &Context = F.getContext();
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker   // Find calls to llvm.gcroot.
390*9880d681SAndroid Build Coastguard Worker   CollectRoots(F);
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker   // If there are no roots in this function, then there is no need to add a
393*9880d681SAndroid Build Coastguard Worker   // stack map entry for it.
394*9880d681SAndroid Build Coastguard Worker   if (Roots.empty())
395*9880d681SAndroid Build Coastguard Worker     return false;
396*9880d681SAndroid Build Coastguard Worker 
397*9880d681SAndroid Build Coastguard Worker   // Build the constant map and figure the type of the shadow stack entry.
398*9880d681SAndroid Build Coastguard Worker   Value *FrameMap = GetFrameMap(F);
399*9880d681SAndroid Build Coastguard Worker   Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F);
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker   // Build the shadow stack entry at the very start of the function.
402*9880d681SAndroid Build Coastguard Worker   BasicBlock::iterator IP = F.getEntryBlock().begin();
403*9880d681SAndroid Build Coastguard Worker   IRBuilder<> AtEntry(IP->getParent(), IP);
404*9880d681SAndroid Build Coastguard Worker 
405*9880d681SAndroid Build Coastguard Worker   Instruction *StackEntry =
406*9880d681SAndroid Build Coastguard Worker       AtEntry.CreateAlloca(ConcreteStackEntryTy, nullptr, "gc_frame");
407*9880d681SAndroid Build Coastguard Worker 
408*9880d681SAndroid Build Coastguard Worker   while (isa<AllocaInst>(IP))
409*9880d681SAndroid Build Coastguard Worker     ++IP;
410*9880d681SAndroid Build Coastguard Worker   AtEntry.SetInsertPoint(IP->getParent(), IP);
411*9880d681SAndroid Build Coastguard Worker 
412*9880d681SAndroid Build Coastguard Worker   // Initialize the map pointer and load the current head of the shadow stack.
413*9880d681SAndroid Build Coastguard Worker   Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead");
414*9880d681SAndroid Build Coastguard Worker   Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
415*9880d681SAndroid Build Coastguard Worker                                        StackEntry, 0, 1, "gc_frame.map");
416*9880d681SAndroid Build Coastguard Worker   AtEntry.CreateStore(FrameMap, EntryMapPtr);
417*9880d681SAndroid Build Coastguard Worker 
418*9880d681SAndroid Build Coastguard Worker   // After all the allocas...
419*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = Roots.size(); I != E; ++I) {
420*9880d681SAndroid Build Coastguard Worker     // For each root, find the corresponding slot in the aggregate...
421*9880d681SAndroid Build Coastguard Worker     Value *SlotPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
422*9880d681SAndroid Build Coastguard Worker                                StackEntry, 1 + I, "gc_root");
423*9880d681SAndroid Build Coastguard Worker 
424*9880d681SAndroid Build Coastguard Worker     // And use it in lieu of the alloca.
425*9880d681SAndroid Build Coastguard Worker     AllocaInst *OriginalAlloca = Roots[I].second;
426*9880d681SAndroid Build Coastguard Worker     SlotPtr->takeName(OriginalAlloca);
427*9880d681SAndroid Build Coastguard Worker     OriginalAlloca->replaceAllUsesWith(SlotPtr);
428*9880d681SAndroid Build Coastguard Worker   }
429*9880d681SAndroid Build Coastguard Worker 
430*9880d681SAndroid Build Coastguard Worker   // Move past the original stores inserted by GCStrategy::InitRoots. This isn't
431*9880d681SAndroid Build Coastguard Worker   // really necessary (the collector would never see the intermediate state at
432*9880d681SAndroid Build Coastguard Worker   // runtime), but it's nicer not to push the half-initialized entry onto the
433*9880d681SAndroid Build Coastguard Worker   // shadow stack.
434*9880d681SAndroid Build Coastguard Worker   while (isa<StoreInst>(IP))
435*9880d681SAndroid Build Coastguard Worker     ++IP;
436*9880d681SAndroid Build Coastguard Worker   AtEntry.SetInsertPoint(IP->getParent(), IP);
437*9880d681SAndroid Build Coastguard Worker 
438*9880d681SAndroid Build Coastguard Worker   // Push the entry onto the shadow stack.
439*9880d681SAndroid Build Coastguard Worker   Instruction *EntryNextPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
440*9880d681SAndroid Build Coastguard Worker                                         StackEntry, 0, 0, "gc_frame.next");
441*9880d681SAndroid Build Coastguard Worker   Instruction *NewHeadVal = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
442*9880d681SAndroid Build Coastguard Worker                                       StackEntry, 0, "gc_newhead");
443*9880d681SAndroid Build Coastguard Worker   AtEntry.CreateStore(CurrentHead, EntryNextPtr);
444*9880d681SAndroid Build Coastguard Worker   AtEntry.CreateStore(NewHeadVal, Head);
445*9880d681SAndroid Build Coastguard Worker 
446*9880d681SAndroid Build Coastguard Worker   // For each instruction that escapes...
447*9880d681SAndroid Build Coastguard Worker   EscapeEnumerator EE(F, "gc_cleanup");
448*9880d681SAndroid Build Coastguard Worker   while (IRBuilder<> *AtExit = EE.Next()) {
449*9880d681SAndroid Build Coastguard Worker     // Pop the entry from the shadow stack. Don't reuse CurrentHead from
450*9880d681SAndroid Build Coastguard Worker     // AtEntry, since that would make the value live for the entire function.
451*9880d681SAndroid Build Coastguard Worker     Instruction *EntryNextPtr2 =
452*9880d681SAndroid Build Coastguard Worker         CreateGEP(Context, *AtExit, ConcreteStackEntryTy, StackEntry, 0, 0,
453*9880d681SAndroid Build Coastguard Worker                   "gc_frame.next");
454*9880d681SAndroid Build Coastguard Worker     Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2, "gc_savedhead");
455*9880d681SAndroid Build Coastguard Worker     AtExit->CreateStore(SavedHead, Head);
456*9880d681SAndroid Build Coastguard Worker   }
457*9880d681SAndroid Build Coastguard Worker 
458*9880d681SAndroid Build Coastguard Worker   // Delete the original allocas (which are no longer used) and the intrinsic
459*9880d681SAndroid Build Coastguard Worker   // calls (which are no longer valid). Doing this last avoids invalidating
460*9880d681SAndroid Build Coastguard Worker   // iterators.
461*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = Roots.size(); I != E; ++I) {
462*9880d681SAndroid Build Coastguard Worker     Roots[I].first->eraseFromParent();
463*9880d681SAndroid Build Coastguard Worker     Roots[I].second->eraseFromParent();
464*9880d681SAndroid Build Coastguard Worker   }
465*9880d681SAndroid Build Coastguard Worker 
466*9880d681SAndroid Build Coastguard Worker   Roots.clear();
467*9880d681SAndroid Build Coastguard Worker   return true;
468*9880d681SAndroid Build Coastguard Worker }
469