30#define DEBUG_TYPE "cfguard"
32STATISTIC(CFGuardCounter,
"Number of Control Flow Guard checks added");
44 CFGuardImpl(Mechanism M) : GuardMechanism(M) {
46 switch (GuardMechanism) {
47 case Mechanism::Check:
48 GuardFnName =
"__guard_check_icall_fptr";
50 case Mechanism::Dispatch:
51 GuardFnName =
"__guard_dispatch_icall_fptr";
99 void insertCFGuardCheck(
CallBase *CB);
140 void insertCFGuardDispatch(
CallBase *CB);
142 bool doInitialization(
Module &M);
147 int cfguard_module_flag = 0;
149 Mechanism GuardMechanism = Mechanism::Check;
172void CFGuardImpl::insertCFGuardCheck(
CallBase *CB) {
175 "Only applicable for Windows targets");
177 "Control Flow Guard checks can only be added to indirect calls");
189 LoadInst *GuardCheckLoad =
B.CreateLoad(GuardFnPtrType, GuardFnGlobal);
194 B.CreateCall(GuardFnType, GuardCheckLoad, {CalledOperand}, Bundles);
201void CFGuardImpl::insertCFGuardDispatch(
CallBase *CB) {
204 "Only applicable for Windows targets");
206 "Control Flow Guard checks can only be added to indirect calls");
210 Type *CalledOperandType = CalledOperand->
getType();
213 LoadInst *GuardDispatchLoad =
B.CreateLoad(CalledOperandType, GuardFnGlobal);
221 assert((isa<CallInst>(CB) || isa<InvokeInst>(CB)) &&
222 "Unknown indirect call type");
235bool CFGuardImpl::doInitialization(
Module &M) {
239 mdconst::extract_or_null<ConstantInt>(
M.getModuleFlag(
"cfguard")))
240 cfguard_module_flag = MD->getZExtValue();
243 if (cfguard_module_flag != 2)
249 {PointerType::getUnqual(M.getContext())},
false);
250 GuardFnPtrType = PointerType::get(GuardFnType, 0);
252 GuardFnGlobal =
M.getOrInsertGlobal(GuardFnName, GuardFnPtrType, [&] {
254 GlobalVariable::ExternalLinkage,
nullptr,
256 Var->setDSOLocal(
true);
263bool CFGuardImpl::runOnFunction(
Function &
F) {
266 if (cfguard_module_flag != 2)
277 auto *CB = dyn_cast<CallBase>(&
I);
286 if (IndirectCalls.
empty()) {
291 if (GuardMechanism == Mechanism::Dispatch) {
292 for (
CallBase *CB : IndirectCalls) {
293 insertCFGuardDispatch(CB);
296 for (
CallBase *CB : IndirectCalls) {
297 insertCFGuardCheck(CB);
305 CFGuardImpl Impl(GuardMechanism);
306 bool Changed = Impl.doInitialization(*
F.getParent());
307 Changed |= Impl.runOnFunction(
F);
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
OperandBundleDefT< Value * > OperandBundleDef
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A container for analyses that lazily runs them and caches their results.
LLVM Basic Block Representation.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
bool isIndirectCall() const
Return true if the callsite is an indirect call.
Value * getCalledOperand() const
static CallBase * Create(CallBase *CB, ArrayRef< OperandBundleDef > Bundles, InsertPosition InsertPt=nullptr)
Create a clone of CB with a different set of operand bundles and insert it before InsertPt.
void setCalledOperand(Value *V)
This class represents a function call, abstracting a target machine's calling convention.
This is an important base class in LLVM.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
An instruction for reading from memory.
A Module instance is used to store all the information related to an LLVM module.
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
A container for an operand bundle being viewed as a set of values rather than a set of uses.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Triple - Helper class for working with autoconf configuration names.
bool isOSWindows() const
Tests whether the OS is Windows.
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getVoidTy(LLVMContext &C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createCFGuardDispatchPass()
Insert Control FLow Guard dispatches on indirect function calls.
void initializeCFGuardPass(PassRegistry &)
FunctionPass * createCFGuardCheckPass()
Insert Control FLow Guard checks on indirect function calls.