comparison lib/CodeGen/ShadowStackGCLowering.cpp @ 120:1172e4bd9c6f

update 4.0.0
author mir3636
date Fri, 25 Nov 2016 19:14:25 +0900
parents 7d135dc70f03
children 803732b1fca8
comparison
equal deleted inserted replaced
101:34baf5011add 120:1172e4bd9c6f
21 #include "llvm/CodeGen/GCStrategy.h" 21 #include "llvm/CodeGen/GCStrategy.h"
22 #include "llvm/IR/CallSite.h" 22 #include "llvm/IR/CallSite.h"
23 #include "llvm/IR/IRBuilder.h" 23 #include "llvm/IR/IRBuilder.h"
24 #include "llvm/IR/IntrinsicInst.h" 24 #include "llvm/IR/IntrinsicInst.h"
25 #include "llvm/IR/Module.h" 25 #include "llvm/IR/Module.h"
26 #include "llvm/Transforms/Utils/EscapeEnumerator.h"
26 27
27 using namespace llvm; 28 using namespace llvm;
28 29
29 #define DEBUG_TYPE "shadowstackgclowering" 30 #define DEBUG_TYPE "shadowstackgclowering"
30 31
78 ShadowStackGCLowering::ShadowStackGCLowering() 79 ShadowStackGCLowering::ShadowStackGCLowering()
79 : FunctionPass(ID), Head(nullptr), StackEntryTy(nullptr), 80 : FunctionPass(ID), Head(nullptr), StackEntryTy(nullptr),
80 FrameMapTy(nullptr) { 81 FrameMapTy(nullptr) {
81 initializeShadowStackGCLoweringPass(*PassRegistry::getPassRegistry()); 82 initializeShadowStackGCLoweringPass(*PassRegistry::getPassRegistry());
82 } 83 }
83
84 namespace {
85 /// EscapeEnumerator - This is a little algorithm to find all escape points
86 /// from a function so that "finally"-style code can be inserted. In addition
87 /// to finding the existing return and unwind instructions, it also (if
88 /// necessary) transforms any call instructions into invokes and sends them to
89 /// a landing pad.
90 ///
91 /// It's wrapped up in a state machine using the same transform C# uses for
92 /// 'yield return' enumerators, This transform allows it to be non-allocating.
93 class EscapeEnumerator {
94 Function &F;
95 const char *CleanupBBName;
96
97 // State.
98 int State;
99 Function::iterator StateBB, StateE;
100 IRBuilder<> Builder;
101
102 public:
103 EscapeEnumerator(Function &F, const char *N = "cleanup")
104 : F(F), CleanupBBName(N), State(0), Builder(F.getContext()) {}
105
106 IRBuilder<> *Next() {
107 switch (State) {
108 default:
109 return nullptr;
110
111 case 0:
112 StateBB = F.begin();
113 StateE = F.end();
114 State = 1;
115
116 case 1:
117 // Find all 'return', 'resume', and 'unwind' instructions.
118 while (StateBB != StateE) {
119 BasicBlock *CurBB = &*StateBB++;
120
121 // Branches and invokes do not escape, only unwind, resume, and return
122 // do.
123 TerminatorInst *TI = CurBB->getTerminator();
124 if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI))
125 continue;
126
127 Builder.SetInsertPoint(TI);
128 return &Builder;
129 }
130
131 State = 2;
132
133 // Find all 'call' instructions.
134 SmallVector<Instruction *, 16> Calls;
135 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
136 for (BasicBlock::iterator II = BB->begin(), EE = BB->end(); II != EE;
137 ++II)
138 if (CallInst *CI = dyn_cast<CallInst>(II))
139 if (!CI->getCalledFunction() ||
140 !CI->getCalledFunction()->getIntrinsicID())
141 Calls.push_back(CI);
142
143 if (Calls.empty())
144 return nullptr;
145
146 // Create a cleanup block.
147 LLVMContext &C = F.getContext();
148 BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F);
149 Type *ExnTy =
150 StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C), nullptr);
151 if (!F.hasPersonalityFn()) {
152 Constant *PersFn = F.getParent()->getOrInsertFunction(
153 "__gcc_personality_v0",
154 FunctionType::get(Type::getInt32Ty(C), true));
155 F.setPersonalityFn(PersFn);
156 }
157 LandingPadInst *LPad =
158 LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);
159 LPad->setCleanup(true);
160 ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);
161
162 // Transform the 'call' instructions into 'invoke's branching to the
163 // cleanup block. Go in reverse order to make prettier BB names.
164 SmallVector<Value *, 16> Args;
165 for (unsigned I = Calls.size(); I != 0;) {
166 CallInst *CI = cast<CallInst>(Calls[--I]);
167
168 // Split the basic block containing the function call.
169 BasicBlock *CallBB = CI->getParent();
170 BasicBlock *NewBB = CallBB->splitBasicBlock(
171 CI->getIterator(), CallBB->getName() + ".cont");
172
173 // Remove the unconditional branch inserted at the end of CallBB.
174 CallBB->getInstList().pop_back();
175 NewBB->getInstList().remove(CI);
176
177 // Create a new invoke instruction.
178 Args.clear();
179 CallSite CS(CI);
180 Args.append(CS.arg_begin(), CS.arg_end());
181
182 InvokeInst *II =
183 InvokeInst::Create(CI->getCalledValue(), NewBB, CleanupBB, Args,
184 CI->getName(), CallBB);
185 II->setCallingConv(CI->getCallingConv());
186 II->setAttributes(CI->getAttributes());
187 CI->replaceAllUsesWith(II);
188 delete CI;
189 }
190
191 Builder.SetInsertPoint(RI);
192 return &Builder;
193 }
194 }
195 };
196 }
197
198 84
199 Constant *ShadowStackGCLowering::GetFrameMap(Function &F) { 85 Constant *ShadowStackGCLowering::GetFrameMap(Function &F) {
200 // doInitialization creates the abstract type of this value. 86 // doInitialization creates the abstract type of this value.
201 Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); 87 Type *VoidPtr = Type::getInt8PtrTy(F.getContext());
202 88