@@ -34,25 +34,22 @@ namespace {
34
34
35
35
// / Adds Control Flow Guard (CFG) checks on indirect function calls/invokes.
36
36
// / These checks ensure that the target address corresponds to the start of an
37
- // / address-taken function. X86_64 targets use the CF_Dispatch mechanism. X86,
38
- // / ARM, and AArch64 targets use the CF_Check machanism.
39
- class CFGuard : public FunctionPass {
37
+ // / address-taken function. X86_64 targets use the Mechanism::Dispatch
38
+ // / mechanism. X86, ARM, and AArch64 targets use the Mechanism::Check machanism.
39
+ class CFGuardImpl {
40
40
public:
41
- static char ID;
42
-
43
- enum Mechanism { CF_Check, CF_Dispatch };
44
-
45
- // Default constructor required for the INITIALIZE_PASS macro.
46
- CFGuard () : FunctionPass(ID) {
47
- initializeCFGuardPass (*PassRegistry::getPassRegistry ());
48
- // By default, use the guard check mechanism.
49
- GuardMechanism = CF_Check;
50
- }
51
-
52
- // Recommended constructor used to specify the type of guard mechanism.
53
- CFGuard (Mechanism Var) : FunctionPass(ID) {
54
- initializeCFGuardPass (*PassRegistry::getPassRegistry ());
55
- GuardMechanism = Var;
41
+ using Mechanism = CFGuardPass::Mechanism;
42
+
43
+ CFGuardImpl (Mechanism M) : GuardMechanism(M) {
44
+ // Get or insert the guard check or dispatch global symbols.
45
+ switch (GuardMechanism) {
46
+ case Mechanism::Check:
47
+ GuardFnName = " __guard_check_icall_fptr" ;
48
+ break ;
49
+ case Mechanism::Dispatch:
50
+ GuardFnName = " __guard_dispatch_icall_fptr" ;
51
+ break ;
52
+ }
56
53
}
57
54
58
55
// / Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG
@@ -141,21 +138,37 @@ class CFGuard : public FunctionPass {
141
138
// / \param CB indirect call to instrument.
142
139
void insertCFGuardDispatch (CallBase *CB);
143
140
144
- bool doInitialization (Module &M) override ;
145
- bool runOnFunction (Function &F) override ;
141
+ bool doInitialization (Module &M);
142
+ bool runOnFunction (Function &F);
146
143
147
144
private:
148
145
// Only add checks if the module has the cfguard=2 flag.
149
146
int cfguard_module_flag = 0 ;
150
- Mechanism GuardMechanism = CF_Check;
147
+ StringRef GuardFnName;
148
+ Mechanism GuardMechanism = Mechanism::Check;
151
149
FunctionType *GuardFnType = nullptr ;
152
150
PointerType *GuardFnPtrType = nullptr ;
153
151
Constant *GuardFnGlobal = nullptr ;
154
152
};
155
153
154
+ class CFGuard : public FunctionPass {
155
+ CFGuardImpl Impl;
156
+
157
+ public:
158
+ static char ID;
159
+
160
+ // Default constructor required for the INITIALIZE_PASS macro.
161
+ CFGuard (CFGuardImpl::Mechanism M) : FunctionPass(ID), Impl(M) {
162
+ initializeCFGuardPass (*PassRegistry::getPassRegistry ());
163
+ }
164
+
165
+ bool doInitialization (Module &M) override { return Impl.doInitialization (M); }
166
+ bool runOnFunction (Function &F) override { return Impl.runOnFunction (F); }
167
+ };
168
+
156
169
} // end anonymous namespace
157
170
158
- void CFGuard ::insertCFGuardCheck (CallBase *CB) {
171
+ void CFGuardImpl ::insertCFGuardCheck (CallBase *CB) {
159
172
160
173
assert (Triple (CB->getModule ()->getTargetTriple ()).isOSWindows () &&
161
174
" Only applicable for Windows targets" );
@@ -184,7 +197,7 @@ void CFGuard::insertCFGuardCheck(CallBase *CB) {
184
197
GuardCheck->setCallingConv (CallingConv::CFGuard_Check);
185
198
}
186
199
187
- void CFGuard ::insertCFGuardDispatch (CallBase *CB) {
200
+ void CFGuardImpl ::insertCFGuardDispatch (CallBase *CB) {
188
201
189
202
assert (Triple (CB->getModule ()->getTargetTriple ()).isOSWindows () &&
190
203
" Only applicable for Windows targets" );
@@ -218,7 +231,7 @@ void CFGuard::insertCFGuardDispatch(CallBase *CB) {
218
231
CB->eraseFromParent ();
219
232
}
220
233
221
- bool CFGuard ::doInitialization (Module &M) {
234
+ bool CFGuardImpl ::doInitialization (Module &M) {
222
235
223
236
// Check if this module has the cfguard flag and read its value.
224
237
if (auto *MD =
@@ -235,15 +248,6 @@ bool CFGuard::doInitialization(Module &M) {
235
248
{PointerType::getUnqual (M.getContext ())}, false );
236
249
GuardFnPtrType = PointerType::get (GuardFnType, 0 );
237
250
238
- // Get or insert the guard check or dispatch global symbols.
239
- llvm::StringRef GuardFnName;
240
- if (GuardMechanism == CF_Check) {
241
- GuardFnName = " __guard_check_icall_fptr" ;
242
- } else if (GuardMechanism == CF_Dispatch) {
243
- GuardFnName = " __guard_dispatch_icall_fptr" ;
244
- } else {
245
- assert (false && " Invalid CFGuard mechanism" );
246
- }
247
251
GuardFnGlobal = M.getOrInsertGlobal (GuardFnName, GuardFnPtrType, [&] {
248
252
auto *Var = new GlobalVariable (M, GuardFnPtrType, false ,
249
253
GlobalVariable::ExternalLinkage, nullptr ,
@@ -255,7 +259,7 @@ bool CFGuard::doInitialization(Module &M) {
255
259
return true ;
256
260
}
257
261
258
- bool CFGuard ::runOnFunction (Function &F) {
262
+ bool CFGuardImpl ::runOnFunction (Function &F) {
259
263
260
264
// Skip modules for which CFGuard checks have been disabled.
261
265
if (cfguard_module_flag != 2 )
@@ -283,7 +287,7 @@ bool CFGuard::runOnFunction(Function &F) {
283
287
}
284
288
285
289
// For each indirect call/invoke, add the appropriate dispatch or check.
286
- if (GuardMechanism == CF_Dispatch ) {
290
+ if (GuardMechanism == Mechanism::Dispatch ) {
287
291
for (CallBase *CB : IndirectCalls) {
288
292
insertCFGuardDispatch (CB);
289
293
}
@@ -296,13 +300,20 @@ bool CFGuard::runOnFunction(Function &F) {
296
300
return true ;
297
301
}
298
302
303
+ PreservedAnalyses CFGuardPass::run (Function &F, FunctionAnalysisManager &FAM) {
304
+ CFGuardImpl Impl (GuardMechanism);
305
+ bool Changed = Impl.doInitialization (*F.getParent ());
306
+ Changed |= Impl.runOnFunction (F);
307
+ return Changed ? PreservedAnalyses::none () : PreservedAnalyses::all ();
308
+ }
309
+
299
310
char CFGuard::ID = 0 ;
300
311
INITIALIZE_PASS (CFGuard, " CFGuard" , " CFGuard" , false , false )
301
312
302
313
FunctionPass *llvm::createCFGuardCheckPass() {
303
- return new CFGuard (CFGuard::CF_Check );
314
+ return new CFGuard (CFGuardPass::Mechanism::Check );
304
315
}
305
316
306
317
FunctionPass *llvm::createCFGuardDispatchPass () {
307
- return new CFGuard (CFGuard::CF_Dispatch );
318
+ return new CFGuard (CFGuardPass::Mechanism::Dispatch );
308
319
}
0 commit comments