30 #define DEBUG_TYPE "shadowstackgclowering"
46 std::vector<std::pair<CallInst *, AllocaInst *>> Roots;
50 ShadowStackGCLowering();
52 bool doInitialization(
Module &M)
override;
56 bool IsNullValue(
Value *V);
64 Type *Ty,
Value *BasePtr,
int Idx1,
int Idx2,
70 "Shadow Stack GC Lowering",
false,
false)
79 ShadowStackGCLowering::ShadowStackGCLowering()
92 for (
unsigned I = 0;
I != Roots.size(); ++
I) {
93 Constant *
C = cast<Constant>(Roots[
I].first->getArgOperand(1));
96 Metadata.
push_back(ConstantExpr::getBitCast(C, VoidPtr));
103 ConstantInt::get(Int32Ty, Roots.size(),
false),
104 ConstantInt::get(Int32Ty, NumMeta,
false),
108 ConstantStruct::get(FrameMapTy, BaseElts),
109 ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), Metadata)};
114 Constant *FrameMap = ConstantStruct::get(STy, DescriptorElts);
130 GlobalVariable::InternalLinkage, FrameMap,
134 ConstantInt::get(Type::getInt32Ty(F.
getContext()), 0),
135 ConstantInt::get(Type::getInt32Ty(F.
getContext()), 0)};
136 return ConstantExpr::getGetElementPtr(FrameMap->getType(), GV, GEPIndices);
139 Type *ShadowStackGCLowering::GetConcreteStackEntryType(
Function &F) {
141 std::vector<Type *> EltTys;
142 EltTys.push_back(StackEntryTy);
143 for (
size_t I = 0;
I != Roots.size();
I++)
144 EltTys.push_back(Roots[
I].second->getAllocatedType());
146 return StructType::create(EltTys, (
"gc_stackentry." + F.
getName()).str());
151 bool ShadowStackGCLowering::doInitialization(
Module &M) {
154 if (F.
hasGC() && F.
getGC() == std::string(
"shadow-stack")) {
167 std::vector<Type *> EltTys;
169 EltTys.push_back(Type::getInt32Ty(M.getContext()));
171 EltTys.push_back(Type::getInt32Ty(M.getContext()));
172 FrameMapTy = StructType::create(EltTys,
"gc_map");
173 PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy);
181 StackEntryTy = StructType::create(M.getContext(),
"gc_stackentry");
184 EltTys.push_back(PointerType::getUnqual(StackEntryTy));
185 EltTys.push_back(FrameMapPtrTy);
186 StackEntryTy->setBody(EltTys);
187 PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy);
190 Head = M.getGlobalVariable(
"llvm_gc_root_chain");
195 M, StackEntryPtrTy,
false, GlobalValue::LinkOnceAnyLinkage,
196 Constant::getNullValue(StackEntryPtrTy),
"llvm_gc_root_chain");
197 }
else if (Head->hasExternalLinkage() && Head->isDeclaration()) {
198 Head->setInitializer(Constant::getNullValue(StackEntryPtrTy));
199 Head->setLinkage(GlobalValue::LinkOnceAnyLinkage);
205 bool ShadowStackGCLowering::IsNullValue(
Value *V) {
206 if (
Constant *C = dyn_cast<Constant>(V))
211 void ShadowStackGCLowering::CollectRoots(
Function &F) {
216 assert(Roots.empty() &&
"Not cleaned up?");
223 if (
Function *F = CI->getCalledFunction())
225 std::pair<CallInst *, AllocaInst *> Pair = std::make_pair(
227 cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts()));
228 if (IsNullValue(CI->getArgOperand(1)))
229 Roots.push_back(Pair);
231 MetaRoots.push_back(Pair);
236 Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end());
241 Value *BasePtr,
int Idx,
244 Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
245 ConstantInt::get(Type::getInt32Ty(Context), Idx),
246 ConstantInt::get(Type::getInt32Ty(Context), Idx2)};
249 assert(isa<GetElementPtrInst>(Val) &&
"Unexpected folded constant");
256 int Idx,
const char *Name) {
257 Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
258 ConstantInt::get(Type::getInt32Ty(Context), Idx)};
261 assert(isa<GetElementPtrInst>(Val) &&
"Unexpected folded constant");
267 bool ShadowStackGCLowering::runOnFunction(
Function &F) {
270 F.
getGC() != std::string(
"shadow-stack"))
284 Value *FrameMap = GetFrameMap(F);
285 Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F);
292 AtEntry.CreateAlloca(ConcreteStackEntryTy,
nullptr,
"gc_frame");
294 while (isa<AllocaInst>(IP))
296 AtEntry.SetInsertPoint(IP->getParent(), IP);
299 Instruction *CurrentHead = AtEntry.CreateLoad(Head,
"gc_currhead");
300 Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
301 StackEntry, 0, 1,
"gc_frame.map");
302 AtEntry.CreateStore(FrameMap, EntryMapPtr);
305 for (
unsigned I = 0,
E = Roots.size();
I !=
E; ++
I) {
307 Value *SlotPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
308 StackEntry, 1 +
I,
"gc_root");
320 while (isa<StoreInst>(IP))
322 AtEntry.SetInsertPoint(IP->getParent(), IP);
325 Instruction *EntryNextPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
326 StackEntry, 0, 0,
"gc_frame.next");
327 Instruction *NewHeadVal = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
328 StackEntry, 0,
"gc_newhead");
329 AtEntry.CreateStore(CurrentHead, EntryNextPtr);
330 AtEntry.CreateStore(NewHeadVal, Head);
338 CreateGEP(Context, *AtExit, ConcreteStackEntryTy, StackEntry, 0, 0,
340 Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2,
"gc_savedhead");
341 AtExit->CreateStore(SavedHead, Head);
347 for (
unsigned I = 0,
E = Roots.size();
I !=
E; ++
I) {
348 Roots[
I].first->eraseFromParent();
349 Roots[
I].second->eraseFromParent();
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 &)
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.
EscapeEnumerator - This is a little algorithm to find all escape points from a function so that "fina...
#define INITIALIZE_PASS_DEPENDENCY(depName)
bool hasGC() const
hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm to use during code generatio...
Class to represent struct types.
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.
static std::string utostr(uint64_t X, bool isNeg=false)
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
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.
Class to represent pointers.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
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.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
rewrite statepoints for gc
Iterator for intrusive lists based on ilist_node.
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.
const BasicBlock & getEntryBlock() const
bool isNullValue() const
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...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
Value * CreateGEP(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
const std::string & getGC() const
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
INITIALIZE_PASS_BEGIN(ShadowStackGCLowering,"shadow-stack-gc-lowering","Shadow Stack GC Lowering", false, false) INITIALIZE_PASS_END(ShadowStackGCLowering
shadow stack gc Shadow Stack GC false
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
A wrapper class for inspecting calls to intrinsic functions.
an instruction to allocate memory on the stack