LLVM: lib/CodeGen/WindowsSecureHotPatching.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
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
150
151using namespace llvm;
152
153#define DEBUG_TYPE "windows-secure-hot-patch"
154
155
157 "ms-secure-hotpatch-functions-file", cl::value_desc("filename"),
158 cl::desc("A file containing list of mangled function names to mark for "
159 "Windows Secure Hot-Patching"));
160
161
163 "ms-secure-hotpatch-functions-list", cl::value_desc("list"),
164 cl::desc("A list of mangled function names to mark for Windows Secure "
165 "Hot-Patching"),
167
168namespace {
169
170struct GlobalVariableUse {
171
173 unsigned Op;
174};
175
176class WindowsSecureHotPatching : public ModulePass {
177public:
178 static char ID;
179
180 WindowsSecureHotPatching() : ModulePass(ID) {
182 }
183
184 void getAnalysisUsage(AnalysisUsage &AU) const override {
186 }
187
188 bool doInitialization(Module &) override;
189 bool runOnModule(Module &M) override { return false; }
190
191private:
192 bool
194 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping);
195};
196
197}
198
199char WindowsSecureHotPatching::ID = 0;
200
202 "Mark functions for Windows hot patch support", false, false)
204 return new WindowsSecureHotPatching();
205}
206
207
208
209
210
211
212bool WindowsSecureHotPatching::doInitialization(Module &M) {
213
214
215
216
219 std::vectorstd::string HotPatchFunctionsList;
220
223 if (BufOrErr) {
224 const MemoryBuffer &FileBuffer = **BufOrErr;
226 ++I)
227 HotPatchFunctionsList.push_back(std::string{*I});
228 } else {
229 M.getContext().diagnose(DiagnosticInfoGeneric{
230 Twine("failed to open hotpatch functions file "
231 "(--ms-hotpatch-functions-file): ") +
233 BufOrErr.getError().message()});
234 }
235 }
236
239 HotPatchFunctionsList.push_back(FuncName);
240
241
242
243 SmallSet<StringRef, 16> HotPatchFunctionsSet;
244 for (const auto &FuncName : HotPatchFunctionsList)
245 HotPatchFunctionsSet.insert(StringRef{FuncName});
246
247
248
249 for (auto &F : M.functions()) {
250
251 if (F.isDeclarationForLinker())
252 continue;
253
254 if (HotPatchFunctionsSet.contains(F.getName()))
255 F.addFnAttr("marked_for_windows_hot_patching");
256 }
257 }
258
259 SmallDenseMap<GlobalVariable *, GlobalVariable *> RefMapping;
260 bool MadeChanges = false;
261 for (auto &F : M.functions()) {
262 if (F.hasFnAttribute("marked_for_windows_hot_patching")) {
264 MadeChanges = true;
265 }
266 }
267 return MadeChanges;
268}
269
273 return true;
274
277
280 for (unsigned I = 0; I < NumElements; ++I) {
282 return true;
283 }
284 }
285 return false;
286 }
287
288 default:
289 return false;
290 }
291}
292
293
295
296
297 if (GV->hasAttribute("allow_direct_access_in_hot_patch_function"))
298 return false;
299
300
303
304
305
306 return false;
307 }
308
309
310 return true;
311 }
312
313
314
315
317}
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
350 if (ReplaceWithRefGV != nullptr) {
351
352 return ReplaceWithRefGV;
353 }
354
355 Module *M = F.getParent();
356
357 const DISubprogram *Subprogram = F.getSubprogram();
358 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr;
359 DIFile *File = Subprogram != nullptr ? Subprogram->getFile() : nullptr;
361
363
366
371
372
373
374
375
376
377
378
379
380
381
382
383 RefGV->setSection(".rdata");
384
385
386 DataLayout Layout = M->getDataLayout();
390 Unit, RefGV->getName(), StringRef{}, File,
391 0, DebugType,
392 false);
393 RefGV->addDebugInfo(GVE);
394
395
396 ReplaceWithRefGV = RefGV;
397
398 return RefGV;
399}
400
401
402
403
404
405
406
407
408
412 if (C->getValueID() == Value::GlobalVariableVal) {
415 return GVLoadMap.at(GV);
416 } else {
417 return nullptr;
418 }
419 }
420
421
422
424 bool ReplacedAnyOperands = false;
425
426 unsigned NumOperands = C->getNumOperands();
429 Value *ReplacedValue = nullptr;
432 IRBuilderAtEntry);
433 }
434
435 ReplacedAnyOperands |= ReplacedValue != nullptr;
436 ReplacedValues.push_back(ReplacedValue);
437 }
438
439
440 if (!ReplacedAnyOperands) {
441 return nullptr;
442 }
443
444
445
448 Value *ReplacedValue = ReplacedValues[OpIndex];
449 if (ReplacedValue != nullptr) {
451 }
452 }
453
454
455 IRBuilderAtEntry.Insert(NewInst);
456
457 return NewInst;
458}
459
463
466 GVLoadMap[GV] = nullptr;
467 return true;
468 } else {
469 return false;
470 }
471 }
472
474 unsigned NumOperands = U->getNumOperands();
475 bool FoundAny = false;
478
480 }
481 return FoundAny;
482 } else {
483 return false;
484 }
485}
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507bool WindowsSecureHotPatching::runOnFunction(
508 Function &F,
509 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping) {
510
511
512
513
514
515
516
517 SmallDenseMap<GlobalVariable *, Value *> GVLoadMap;
519
521 unsigned NumOperands = I.getNumOperands();
524
525 bool FoundAnyGVUses = false;
526
527 switch (V->getValueID()) {
528 case Value::GlobalVariableVal: {
529
532 GVLoadMap.insert(std::make_pair(GV, nullptr));
533 FoundAnyGVUses = true;
534 }
535 break;
536 }
537
538 case Value::ConstantExprVal: {
541 FoundAnyGVUses = true;
542 }
543 break;
544 }
545
546 default:
547 break;
548 }
549
550 if (FoundAnyGVUses) {
552 }
553 }
554 }
555
556
557
558 if (GVUses.empty()) {
559 return false;
560 }
561
562
563
564
565
566
567
568
569
570
571
572
573 auto &EntryBlock = F.getEntryBlock();
574 IRBuilder<> IRBuilderAtEntry(&EntryBlock, EntryBlock.begin());
575
576 for (auto &[GV, LoadValue] : GVLoadMap) {
577 assert(LoadValue == nullptr);
579 LoadValue = IRBuilderAtEntry.CreateLoad(RefGV->getValueType(), RefGV);
580 }
581
582 const DISubprogram *Subprogram = F.getSubprogram();
583 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr;
585
586
587
588
589
590 for (auto &GVUse : GVUses) {
591 Value *OldOperandValue = GVUse.User->getOperand(GVUse.Op);
592 Value *NewOperandValue;
593
594 switch (OldOperandValue->getValueID()) {
595 case Value::GlobalVariableVal: {
596
597 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
599 NewOperandValue = GVLoadMap.at(GV);
600 break;
601 }
602
603 case Value::ConstantExprVal: {
604
605
606
607
608 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
610 NewOperandValue =
612 assert(NewOperandValue != nullptr);
613 break;
614 }
615
616 default:
617
618
620 "unexpected Value in second pass of hot-patching");
621 break;
622 }
623
624 GVUse.User->setOperand(GVUse.Op, NewOperandValue);
625 }
626
627 return true;
628}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallSet class.
static GlobalVariable * getOrCreateRefVariable(Function &F, SmallDenseMap< GlobalVariable *, GlobalVariable * > &RefMapping, GlobalVariable *GV)
Definition WindowsSecureHotPatching.cpp:346
static bool globalVariableNeedsRedirect(GlobalVariable *GV)
Definition WindowsSecureHotPatching.cpp:294
static cl::list< std::string > LLVMMSSecureHotPatchFunctionsList("ms-secure-hotpatch-functions-list", cl::value_desc("list"), cl::desc("A list of mangled function names to mark for Windows Secure " "Hot-Patching"), cl::CommaSeparated)
static bool searchConstantExprForGlobalVariables(Value *V, SmallDenseMap< GlobalVariable *, Value * > &GVLoadMap, SmallVector< GlobalVariableUse > &GVUses)
Definition WindowsSecureHotPatching.cpp:460
static Value * rewriteGlobalVariablesInConstant(Constant *C, SmallDenseMap< GlobalVariable *, Value * > &GVLoadMap, IRBuilder<> &IRBuilderAtEntry)
Definition WindowsSecureHotPatching.cpp:409
static bool TypeContainsPointers(Type *ty)
Definition WindowsSecureHotPatching.cpp:270
static cl::opt< std::string > LLVMMSSecureHotPatchFunctionsFile("ms-secure-hotpatch-functions-file", cl::value_desc("filename"), cl::desc("A file containing list of mangled function names to mark for " "Windows Secure Hot-Patching"))
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
This is an important base class in LLVM.
A pair of DIGlobalVariable and DIExpression.
Subprogram description. Uses SubclassData1.
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
ValueT & at(const_arg_type_t< KeyT > Val)
at - Return the entry for the specified key, or abort if no such entry exists.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
@ LinkOnceAnyLinkage
Keep one copy of function when linking (inline)
Type * getValueType() const
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
MemoryBufferRef getMemBufferRef() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
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.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI Type * getStructElementType(unsigned N) const
Type * getArrayElementType() const
LLVM_ABI unsigned getStructNumElements() const
TypeID getTypeID() const
Return the type id for the type.
void setOperand(unsigned i, Value *Val)
LLVM Value Representation.
unsigned getValueID() const
Return an ID for the concrete type of this object.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
@ C
The default llvm calling convention, compatible with C.
@ CE
Windows NT (Windows on ARM)
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.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
LLVM_ABI void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)
This function calls abort(), and prints the optional message to stderr.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI void initializeWindowsSecureHotPatchingPass(PassRegistry &)
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
LLVM_ABI ModulePass * createWindowsSecureHotPatchingPass()
Creates Windows Secure Hot Patch pass.