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.