25 #define DEBUG_TYPE "shadowstackgclowering"
41 std::vector<std::pair<CallInst *, AllocaInst *>> Roots;
45 ShadowStackGCLowering();
47 bool doInitialization(
Module &M)
override;
51 bool IsNullValue(
Value *V);
59 Type *Ty,
Value *BasePtr,
int Idx1,
int Idx2,
65 "Shadow Stack GC Lowering",
false,
false)
74 ShadowStackGCLowering::ShadowStackGCLowering()
89 class EscapeEnumerator {
91 const char *CleanupBBName;
99 EscapeEnumerator(
Function &
F,
const char *
N =
"cleanup")
100 : F(F), CleanupBBName(
N), State(0), Builder(F.getContext()) {}
114 while (StateBB != StateE) {
120 if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI))
123 Builder.SetInsertPoint(TI->
getParent(), TI);
134 if (
CallInst *CI = dyn_cast<CallInst>(II))
135 if (!CI->getCalledFunction() ||
136 !CI->getCalledFunction()->getIntrinsicID())
144 BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &
F);
146 StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C),
nullptr);
147 if (!
F.hasPersonalityFn()) {
148 Constant *PersFn =
F.getParent()->getOrInsertFunction(
149 "__gcc_personality_v0",
150 FunctionType::get(Type::getInt32Ty(C),
true));
151 F.setPersonalityFn(PersFn);
154 LandingPadInst::Create(ExnTy, 1,
"cleanup.lpad", CleanupBB);
156 ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);
161 for (
unsigned I = Calls.
size();
I != 0;) {
162 CallInst *CI = cast<CallInst>(Calls[--
I]);
187 Builder.SetInsertPoint(RI->
getParent(), RI);
200 unsigned NumMeta = 0;
202 for (
unsigned I = 0;
I != Roots.size(); ++
I) {
203 Constant *C = cast<Constant>(Roots[
I].first->getArgOperand(1));
206 Metadata.
push_back(ConstantExpr::getBitCast(C, VoidPtr));
213 ConstantInt::get(Int32Ty, Roots.size(),
false),
214 ConstantInt::get(Int32Ty, NumMeta,
false),
218 ConstantStruct::get(FrameMapTy, BaseElts),
219 ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), Metadata)};
224 Constant *FrameMap = ConstantStruct::get(STy, DescriptorElts);
240 GlobalVariable::InternalLinkage, FrameMap,
244 ConstantInt::get(Type::getInt32Ty(F.
getContext()), 0),
245 ConstantInt::get(Type::getInt32Ty(F.
getContext()), 0)};
246 return ConstantExpr::getGetElementPtr(FrameMap->getType(), GV, GEPIndices);
249 Type *ShadowStackGCLowering::GetConcreteStackEntryType(
Function &F) {
251 std::vector<Type *> EltTys;
252 EltTys.push_back(StackEntryTy);
253 for (
size_t I = 0;
I != Roots.size();
I++)
254 EltTys.push_back(Roots[
I].second->getAllocatedType());
256 return StructType::create(EltTys, (
"gc_stackentry." + F.
getName()).str());
261 bool ShadowStackGCLowering::doInitialization(
Module &M) {
264 if (F.
hasGC() && F.
getGC() == std::string(
"shadow-stack")) {
277 std::vector<Type *> EltTys;
279 EltTys.push_back(Type::getInt32Ty(M.getContext()));
281 EltTys.push_back(Type::getInt32Ty(M.getContext()));
282 FrameMapTy = StructType::create(EltTys,
"gc_map");
283 PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy);
291 StackEntryTy = StructType::create(M.getContext(),
"gc_stackentry");
294 EltTys.push_back(PointerType::getUnqual(StackEntryTy));
295 EltTys.push_back(FrameMapPtrTy);
296 StackEntryTy->setBody(EltTys);
297 PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy);
300 Head = M.getGlobalVariable(
"llvm_gc_root_chain");
305 M, StackEntryPtrTy,
false, GlobalValue::LinkOnceAnyLinkage,
306 Constant::getNullValue(StackEntryPtrTy),
"llvm_gc_root_chain");
307 }
else if (Head->hasExternalLinkage() && Head->isDeclaration()) {
308 Head->setInitializer(Constant::getNullValue(StackEntryPtrTy));
309 Head->setLinkage(GlobalValue::LinkOnceAnyLinkage);
315 bool ShadowStackGCLowering::IsNullValue(
Value *V) {
316 if (
Constant *C = dyn_cast<Constant>(V))
321 void ShadowStackGCLowering::CollectRoots(
Function &F) {
326 assert(Roots.empty() &&
"Not cleaned up?");
335 std::pair<CallInst *, AllocaInst *> Pair = std::make_pair(
339 Roots.push_back(Pair);
341 MetaRoots.push_back(Pair);
346 Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end());
351 Value *BasePtr,
int Idx,
354 Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
355 ConstantInt::get(Type::getInt32Ty(Context), Idx),
356 ConstantInt::get(Type::getInt32Ty(Context), Idx2)};
359 assert(isa<GetElementPtrInst>(Val) &&
"Unexpected folded constant");
366 int Idx,
const char *Name) {
367 Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
368 ConstantInt::get(Type::getInt32Ty(Context), Idx)};
371 assert(isa<GetElementPtrInst>(Val) &&
"Unexpected folded constant");
377 bool ShadowStackGCLowering::runOnFunction(
Function &F) {
380 F.
getGC() != std::string(
"shadow-stack"))
394 Value *FrameMap = GetFrameMap(F);
395 Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F);
402 AtEntry.CreateAlloca(ConcreteStackEntryTy,
nullptr,
"gc_frame");
404 while (isa<AllocaInst>(IP))
406 AtEntry.SetInsertPoint(IP->getParent(), IP);
409 Instruction *CurrentHead = AtEntry.CreateLoad(Head,
"gc_currhead");
410 Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
411 StackEntry, 0, 1,
"gc_frame.map");
412 AtEntry.CreateStore(FrameMap, EntryMapPtr);
415 for (
unsigned I = 0, E = Roots.size();
I != E; ++
I) {
417 Value *SlotPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
418 StackEntry, 1 +
I,
"gc_root");
430 while (isa<StoreInst>(IP))
432 AtEntry.SetInsertPoint(IP->getParent(), IP);
435 Instruction *EntryNextPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
436 StackEntry, 0, 0,
"gc_frame.next");
437 Instruction *NewHeadVal = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
438 StackEntry, 0,
"gc_newhead");
439 AtEntry.CreateStore(CurrentHead, EntryNextPtr);
440 AtEntry.CreateStore(NewHeadVal, Head);
443 EscapeEnumerator EE(F,
"gc_cleanup");
448 CreateGEP(Context, *AtExit, ConcreteStackEntryTy, StackEntry, 0, 0,
450 Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2,
"gc_savedhead");
451 AtExit->CreateStore(SavedHead, Head);
457 for (
unsigned I = 0, E = Roots.size();
I != E; ++
I) {
458 Roots[
I].first->eraseFromParent();
459 Roots[
I].second->eraseFromParent();
Value * CreateGEP(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
const Value * getCalledValue() const
getCalledValue - Get a pointer to the function that is invoked by this instruction.
void setAttributes(const AttributeSet &Attrs)
setAttributes - Set the parameter attributes for this invoke.
void push_back(const T &Elt)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
A Module instance is used to store all the information related to an LLVM module. ...
void initializeShadowStackGCLoweringPass(PassRegistry &)
const char * getGC() const
CallInst - This class represents a function call, abstracting a target machine's calling convention...
FunctionPass * createShadowStackGCLoweringPass()
ShadowStackGCLowering - Implements the custom lowering mechanism used by the shadow stack GC...
StringRef getName() const
Return a constant reference to the value's name.
iterator begin()
Instruction iterator methods.
#define INITIALIZE_PASS_DEPENDENCY(depName)
StructType - Class to represent struct types.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis pass which caches information about the entire Module.
void setCleanup(bool V)
setCleanup - Indicate that this landingpad instruction is a cleanup.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
static std::string utostr(uint64_t X, bool isNeg=false)
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void takeName(Value *V)
Transfer the name from V to this value.
PointerType - Class to represent pointers.
GetElementPtrInst - an instruction for type-safe pointer arithmetic to access elements of arrays and ...
LandingPadInst - The landingpad instruction holds all of the information necessary to generate correc...
Subclasses of this class are all able to terminate a basic block.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
This is an important base class in LLVM.
ResumeInst - Resume the propagation of an exception.
const InstListType & getInstList() const
Return the underlying instruction list container.
FunctionPass class - This class is used to implement most global optimizations.
rewrite statepoints for gc
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
shadow stack gc Shadow Stack GC Lowering
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Value * stripPointerCasts()
Strip off pointer casts, all-zero GEPs, and aliases.
Function * getCalledFunction() const
getCalledFunction - Return the function called, or null if this is an indirect function invocation...
const BasicBlock & getEntryBlock() const
bool isNullValue() const
isNullValue - Return true if this is the value that would be returned by getNullValue.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool hasGC() const
hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm to use during code generatio...
const AttributeSet & getAttributes() const
getAttributes - Return the parameter attributes for this call.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
INITIALIZE_PASS_BEGIN(ShadowStackGCLowering,"shadow-stack-gc-lowering","Shadow Stack GC Lowering", false, false) INITIALIZE_PASS_END(ShadowStackGCLowering
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
shadow stack gc Shadow Stack GC false
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
void setCallingConv(CallingConv::ID CC)
InvokeInst - Invoke instruction.
C - The default llvm calling convention, compatible with C.
CallingConv::ID getCallingConv() const
getCallingConv/setCallingConv - Get or set the calling convention of this function call...
NodeTy * remove(iterator &IT)
const BasicBlock * getParent() const
IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic functions.
AllocaInst - an instruction to allocate memory on the stack.