LLVM: lib/Transforms/CFGuard/CFGuard.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
25
26using namespace llvm;
27
29
30#define DEBUG_TYPE "cfguard"
31
32STATISTIC(CFGuardCounter, "Number of Control Flow Guard checks added");
33
36
37namespace {
38
39
40
41
42
43class CFGuardImpl {
44public:
46
47 CFGuardImpl(Mechanism M) : GuardMechanism(M) {
48
49 switch (GuardMechanism) {
50 case Mechanism::Check:
52 break;
53 case Mechanism::Dispatch:
55 break;
56 }
57 }
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 void insertCFGuardCheck(CallBase *CB);
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 void insertCFGuardDispatch(CallBase *CB);
144
145 bool doInitialization(Module &M);
147
148private:
149
150 int CFGuardModuleFlag = 0;
152 Mechanism GuardMechanism = Mechanism::Check;
155 Constant *GuardFnGlobal = nullptr;
156};
157
159 CFGuardImpl Impl;
160
161public:
162 static char ID;
163
164
165 CFGuard(CFGuardImpl::Mechanism M) : FunctionPass(ID), Impl(M) {}
166
169};
170
171}
172
173void CFGuardImpl::insertCFGuardCheck(CallBase *CB) {
175 "Only applicable for Windows targets");
177 "Control Flow Guard checks can only be added to indirect calls");
178
181
182
183
187
188
189 LoadInst *GuardCheckLoad = B.CreateLoad(GuardFnPtrType, GuardFnGlobal);
190
191
192
193 CallInst *GuardCheck =
194 B.CreateCall(GuardFnType, GuardCheckLoad, {CalledOperand}, Bundles);
195
196
197
198 GuardCheck->setCallingConv(CallingConv::CFGuard_Check);
199}
200
201void CFGuardImpl::insertCFGuardDispatch(CallBase *CB) {
203 "Only applicable for Windows targets");
205 "Control Flow Guard checks can only be added to indirect calls");
206
209 Type *CalledOperandType = CalledOperand->getType();
210
211
212 LoadInst *GuardDispatchLoad = B.CreateLoad(CalledOperandType, GuardFnGlobal);
213
214
217 Bundles.emplace_back("cfguardtarget", CalledOperand);
218
219
221 "Unknown indirect call type");
223
224
226
227
229
230
232}
233
234bool CFGuardImpl::doInitialization(Module &M) {
235
236 if (auto *MD =
238 CFGuardModuleFlag = MD->getZExtValue();
239
240
241 if (CFGuardModuleFlag != 2)
242 return false;
243
244
245 GuardFnType =
246 FunctionType::get(Type::getVoidTy(M.getContext()),
247 {PointerType::getUnqual(M.getContext())}, false);
248 GuardFnPtrType = PointerType::get(M.getContext(), 0);
249
250 GuardFnGlobal = M.getOrInsertGlobal(GuardFnName, GuardFnPtrType, [&] {
251 auto *Var = new GlobalVariable(M, GuardFnPtrType, false,
252 GlobalVariable::ExternalLinkage, nullptr,
253 GuardFnName);
254 Var->setDSOLocal(true);
255 return Var;
256 });
257
258 return true;
259}
260
261bool CFGuardImpl::runOnFunction(Function &F) {
262
263 if (CFGuardModuleFlag != 2)
264 return false;
265
267
268
269
270
271
272 for (BasicBlock &BB : F) {
273 for (Instruction &I : BB) {
277 CFGuardCounter++;
278 }
279 }
280 }
281
282
283 if (IndirectCalls.empty())
284 return false;
285
286
287 if (GuardMechanism == Mechanism::Dispatch) {
288 for (CallBase *CB : IndirectCalls)
289 insertCFGuardDispatch(CB);
290 } else {
291 for (CallBase *CB : IndirectCalls)
292 insertCFGuardCheck(CB);
293 }
294
295 return true;
296}
297
299 CFGuardImpl Impl(GuardMechanism);
300 bool Changed = Impl.doInitialization(*F.getParent());
301 Changed |= Impl.runOnFunction(F);
303}
304
305char CFGuard::ID = 0;
306INITIALIZE_PASS(CFGuard, "CFGuard", "CFGuard", false, false)
307
311
315
318 return false;
319
322}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
constexpr StringRef GuardCheckFunctionName
Definition CFGuard.cpp:34
constexpr StringRef GuardDispatchFunctionName
Definition CFGuard.cpp:35
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
FunctionAnalysisManager FAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Definition CFGuard.cpp:298
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
LLVM_ABI 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.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
Value * getCalledOperand() const
static LLVM_ABI 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 is an important base class in LLVM.
FunctionPass class - This class is used to implement most global optimizations.
LinkageTypes getLinkage() const
@ ExternalLinkage
Externally visible function.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A Module instance is used to store all the information related to an LLVM module.
const Triple & 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.
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)
StringRef - Represent a constant reference to a string, i.e.
bool isOSWindows() const
Tests whether the OS is Windows.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
bool isCFGuardFunction(const GlobalValue *GV)
Definition CFGuard.cpp:316
FunctionPass * createCFGuardDispatchPass()
Insert Control FLow Guard dispatches on indirect function calls.
Definition CFGuard.cpp:312
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
OperandBundleDefT< Value * > OperandBundleDef
FunctionPass * createCFGuardCheckPass()
Insert Control FLow Guard checks on indirect function calls.
Definition CFGuard.cpp:308
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.