LLVM 23.0.0git
WindowsSecureHotPatching.cpp
Go to the documentation of this file.
1//===------ WindowsHotPatch.cpp - Support for Windows hotpatching ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Provides support for the Windows "Secure Hot-Patching" feature.
10//
11// Windows contains technology, called "Secure Hot-Patching" (SHP), for securely
12// applying hot-patches to a running system. Hot-patches may be applied to the
13// kernel, kernel-mode components, device drivers, user-mode system services,
14// etc.
15//
16// SHP relies on integration between many tools, including compiler, linker,
17// hot-patch generation tools, and the Windows kernel. This file implements that
18// part of the workflow needed in compilers / code generators.
19//
20// SHP is not intended for productivity scenarios such as Edit-and-Continue or
21// interactive development. SHP is intended to minimize downtime during
22// installation of Windows OS patches.
23//
24// In order to work with SHP, LLVM must do all of the following:
25//
26// * On some architectures (X86, AMD64), the function prolog must begin with
27// hot-patchable instructions. This is handled by the MSVC `/hotpatch` option
28// and the equivalent `-fms-hotpatch` function. This is necessary because we
29// generally cannot anticipate which functions will need to be patched in the
30// future. This option ensures that a function can be hot-patched in the
31// future, but does not actually generate any hot-patch for it.
32//
33// * For a selected set of functions that are being hot-patched (which are
34// identified using command-line options), LLVM must generate the
35// `S_HOTPATCHFUNC` CodeView record (symbol). This record indicates that a
36// function was compiled with hot-patching enabled.
37//
38// This implementation uses the `MarkedForWindowsHotPatching` attribute to
39// annotate those functions that were marked for hot-patching by command-line
40// parameters. The attribute may be specified by a language front-end by
41// setting an attribute when a function is created in LLVM IR, or it may be
42// set by passing LLVM arguments.
43//
44// * For those functions that are hot-patched, LLVM must rewrite references to
45// global variables so that they are indirected through a `__ref_*` pointer
46// variable. For each global variable, that is accessed by a hot-patched
47// function, e.g. `FOO`, a `__ref_FOO` global pointer variable is created and
48// all references to the original `FOO` are rewritten as dereferences of the
49// `__ref_FOO` pointer.
50//
51// Some globals do not need `__ref_*` indirection. The pointer indirection
52// behavior can be disabled for these globals by marking them with the
53// `AllowDirectAccessInHotPatchFunction`.
54//
55// Rewriting references to global variables has some complexity.
56//
57// For ordinary instructions that reference GlobalVariables, we rewrite the
58// operand of the instruction to a Load of the __ref_* variable.
59//
60// For constant expressions, we have to convert the constant expression (and
61// transitively all constant expressions in its parent chain) to non-constant
62// expressions, i.e. to a sequence of instructions.
63//
64// Pass 1:
65// * Enumerate all instructions in all basic blocks.
66//
67// * If an instruction references a GlobalVariable (and it is not marked
68// as being ignored), then we create (if necessary) the __ref_* variable
69// for the GlobalVariable reference. However, we do not yet modify the
70// Instruction.
71//
72// * If an instruction has an operand that is a ConstantExpr and the
73// ConstantExpression tree contains a reference to a GlobalVariable, then
74// we similarly create __ref_*. Similarly, we do not yet modify the
75// Instruction or the ConstantExpr tree.
76//
77// After Pass 1 completes, we will know whether we found any references to
78// globals in this pass. If the function does not use any globals (and most
79// functions do not use any globals), then we return immediately.
80//
81// If a function does reference globals, then we iterate the list of globals
82// used by this function and we generate Load instructions for each (unique)
83// global.
84//
85// Next, we do another pass over all instructions:
86//
87// Pass 2:
88// * Re-visit the instructions that were found in Pass 1.
89//
90// * If an instruction operand is a GlobalVariable, then look up the
91// replacement
92// __ref_* global variable and the Value that came from the Load instruction
93// for it. Replace the operand of the GlobalVariable with the Load Value.
94//
95// * If an instruction operand is a ConstantExpr, then recursively examine the
96// operands of all instructions in the ConstantExpr tree. If an operand is
97// a GlobalVariable, then replace the operand with the result of the load
98// *and* convert the ConstantExpr to a non-constant instruction. This
99// instruction will need to be inserted into the BB of the instruction whose
100// operand is being modified, ideally immediately before the instruction
101// being modified.
102//
103// Limitations
104//
105// This feature is not intended to work in every situation. There are many
106// legitimate code changes (patches) for which it is not possible to generate
107// a hot-patch. Developers who are writing hot-patches are expected to
108// understand the limitations.
109//
110// Tools which generate hot-patch metadata may also check that certain
111// variables are upheld, and some of these invariants may be global (may require
112// whole-program knowledge, not available in any single compiland). However,
113// such tools are not required to be perfect; they are also best-effort.
114//
115// For these reasons, the hot-patching support implemented in this file is
116// "best effort". It does not recognize every possible code pattern that could
117// be patched, nor does it generate diagnostics for certain code patterns that
118// could result in a binary that does not work with hot-patching. For example,
119// const GlobalVariables that point to other non-const GlobalVariables are not
120// compatible with hot-patching because they cannot use __ref_*-based
121// redirection.
122//
123// References
124//
125// * "Hotpatching on Windows":
126// https://techcommunity.microsoft.com/blog/windowsosplatform/hotpatching-on-windows/2959541
127//
128// * "Hotpatch for Windows client now available":
129// https://techcommunity.microsoft.com/blog/windows-itpro-blog/hotpatch-for-windows-client-now-available/4399808
130//
131// * "Get hotpatching for Windows Server":
132// https://www.microsoft.com/en-us/windows-server/blog/2025/04/24/tired-of-all-the-restarts-get-hotpatching-for-windows-server/
133//
134//===----------------------------------------------------------------------===//
135
136#include "llvm/ADT/SmallSet.h"
137#include "llvm/CodeGen/Passes.h"
138#include "llvm/IR/Attributes.h"
139#include "llvm/IR/DIBuilder.h"
141#include "llvm/IR/Function.h"
142#include "llvm/IR/IRBuilder.h"
143#include "llvm/IR/InstIterator.h"
144#include "llvm/IR/Module.h"
146#include "llvm/Pass.h"
150
151using namespace llvm;
152
153#define DEBUG_TYPE "windows-secure-hot-patch"
154
155// A file containing list of mangled function names to mark for hot patching.
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// A list of mangled function names to mark for hot patching.
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 // GlobalVariable *GV;
173 unsigned Op;
174};
175
176class WindowsSecureHotPatching : public ModulePass {
177public:
178 static char ID;
179
180 WindowsSecureHotPatching() : ModulePass(ID) {}
181
182 void getAnalysisUsage(AnalysisUsage &AU) const override {
183 AU.setPreservesCFG();
184 }
185
186 bool doInitialization(Module &) override;
187 bool runOnModule(Module &M) override { return false; }
188
189private:
190 bool
191 runOnFunction(Function &F,
192 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping);
193};
194
195} // end anonymous namespace
196
197char WindowsSecureHotPatching::ID = 0;
198
199INITIALIZE_PASS(WindowsSecureHotPatching, "windows-secure-hot-patch",
200 "Mark functions for Windows hot patch support", false, false)
202 return new WindowsSecureHotPatching();
203}
204
205// Find functions marked with Attribute::MarkedForWindowsHotPatching and modify
206// their code (if necessary) to account for accesses to global variables.
207//
208// This runs during doInitialization() instead of runOnModule() because it needs
209// to run before CodeViewDebug::collectGlobalVariableInfo().
210bool WindowsSecureHotPatching::doInitialization(Module &M) {
211 // The front end may have already marked functions for hot-patching. However,
212 // we also allow marking functions by passing -ms-hotpatch-functions-file or
213 // -ms-hotpatch-functions-list directly to LLVM. This allows hot-patching to
214 // work with languages that have not yet updated their front-ends.
217 std::vector<std::string> HotPatchFunctionsList;
218
221 if (BufOrErr) {
222 const MemoryBuffer &FileBuffer = **BufOrErr;
223 for (line_iterator I(FileBuffer.getMemBufferRef(), true), E; I != E;
224 ++I)
225 HotPatchFunctionsList.push_back(std::string{*I});
226 } else {
227 M.getContext().diagnose(DiagnosticInfoGeneric{
228 Twine("failed to open hotpatch functions file "
229 "(--ms-hotpatch-functions-file): ") +
230 LLVMMSSecureHotPatchFunctionsFile + Twine(" : ") +
231 BufOrErr.getError().message()});
232 }
233 }
234
236 for (const auto &FuncName : LLVMMSSecureHotPatchFunctionsList)
237 HotPatchFunctionsList.push_back(FuncName);
238
239 // Build a set for quick lookups. This points into HotPatchFunctionsList, so
240 // HotPatchFunctionsList must live longer than HotPatchFunctionsSet.
241 SmallSet<StringRef, 16> HotPatchFunctionsSet;
242 for (const auto &FuncName : HotPatchFunctionsList)
243 HotPatchFunctionsSet.insert(StringRef{FuncName});
244
245 // Iterate through all of the functions and check whether they need to be
246 // marked for hotpatching using the list provided directly to LLVM.
247 for (auto &F : M.functions()) {
248 // Ignore declarations that are not definitions.
249 if (F.isDeclarationForLinker())
250 continue;
251
252 if (HotPatchFunctionsSet.contains(F.getName()))
253 F.addFnAttr("marked_for_windows_hot_patching");
254 }
255 }
256
257 SmallDenseMap<GlobalVariable *, GlobalVariable *> RefMapping;
258 bool MadeChanges = false;
259 for (auto &F : M.functions()) {
260 if (F.hasFnAttribute("marked_for_windows_hot_patching")) {
261 if (runOnFunction(F, RefMapping))
262 MadeChanges = true;
263 }
264 }
265 return MadeChanges;
266}
267
268static bool TypeContainsPointers(Type *ty) {
269 switch (ty->getTypeID()) {
271 return true;
272
273 case Type::ArrayTyID:
275
276 case Type::StructTyID: {
277 unsigned NumElements = ty->getStructNumElements();
278 for (unsigned I = 0; I < NumElements; ++I) {
280 return true;
281 }
282 }
283 return false;
284 }
285
286 default:
287 return false;
288 }
289}
290
291// Returns true if GV needs redirection through a __ref_* variable.
293 // If a global variable is explictly marked as allowing access in hot-patched
294 // functions, then do not redirect it.
295 if (GV->hasAttribute("allow_direct_access_in_hot_patch_function"))
296 return false;
297
298 // If the global variable is not a constant, then we want to redirect it.
299 if (!GV->isConstant()) {
300 if (GV->getName().starts_with("??_R")) {
301 // This is the name mangling prefix that MSVC uses for RTTI data.
302 // Clang is currently generating RTTI data that is marked non-constant.
303 // We override that and treat it like it is constant.
304 return false;
305 }
306
307 // In general, if a global variable is not a constant, then redirect it.
308 return true;
309 }
310
311 // If the type of GV cannot contain pointers, then it cannot point to
312 // other global variables. In this case, there is no need for redirects.
313 // For example, string literals do not contain pointers.
315}
316
317// Get or create a new global variable that points to the old one and whose
318// name begins with `__ref_`.
319//
320// In hot-patched images, the __ref_* variables point to global variables in
321// the original (unpatched) image. Hot-patched functions in the hot-patch
322// image use these __ref_* variables to access global variables. This ensures
323// that all code (both unpatched and patched) is using the same instances of
324// global variables.
325//
326// The Windows hot-patch infrastructure handles modifying these __ref_*
327// variables. By default, they are initialized with pointers to the equivalent
328// global variables, so when a hot-patch module is loaded *as* a base image
329// (such as after a system reboot), hot-patch functions will access the
330// instances of global variables that are compiled into the hot-patch image.
331// This is the desired outcome, since in this situation (normal boot) the
332// hot-patch image *is* the base image.
333//
334// When we create the GlobalVariable for the __ref_* variable, we must create
335// it as a *non-constant* global variable. The __ref_* pointers will not change
336// during the runtime of the program, so it is tempting to think that they
337// should be constant. However, they still need to be updateable by the
338// hot-patching infrastructure. Also, if the GlobalVariable is created as a
339// constant, then the LLVM optimizer will assume that it can dereference the
340// definition of the __ref_* variable at compile time, which defeats the
341// purpose of the indirection (pointer).
342//
343// The RefMapping table spans the entire module, not just a single function.
346 GlobalVariable *GV) {
347 GlobalVariable *&ReplaceWithRefGV = RefMapping.try_emplace(GV).first->second;
348 if (ReplaceWithRefGV != nullptr) {
349 // We have already created a __ref_* pointer for this GlobalVariable.
350 return ReplaceWithRefGV;
351 }
352
353 Module *M = F.getParent();
354
355 const DISubprogram *Subprogram = F.getSubprogram();
356 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr;
357 DIFile *File = Subprogram != nullptr ? Subprogram->getFile() : nullptr;
358 DIBuilder DebugInfo{*F.getParent(), true, Unit};
359
360 auto PtrTy = PointerType::get(M->getContext(), 0);
361
362 Constant *AddrOfOldGV =
364
365 GlobalVariable *RefGV =
367 AddrOfOldGV, Twine("__ref_").concat(GV->getName()),
369
370 // RefGV is created with isConstant = false, but we want to place RefGV into
371 // .rdata, not .data. It is important that the GlobalVariable be mutable
372 // from the compiler's point of view, so that the optimizer does not remove
373 // the global variable entirely and replace all references to it with its
374 // initial value.
375 //
376 // When the Windows hot-patch loader applies a hot-patch, it maps the
377 // pages of .rdata as read/write so that it can set each __ref_* variable
378 // to point to the original variable in the base image. Afterward, pages in
379 // .rdata are remapped as read-only. This protects the __ref_* variables from
380 // being overwritten during execution.
381 RefGV->setSection(".rdata");
382
383 // Create debug info for the replacement global variable.
384 DataLayout Layout = M->getDataLayout();
385 DIType *DebugType = DebugInfo.createPointerType(
386 nullptr, Layout.getTypeSizeInBits(GV->getValueType()));
387 DIGlobalVariableExpression *GVE = DebugInfo.createGlobalVariableExpression(
388 Unit, RefGV->getName(), StringRef{}, File,
389 /*LineNo*/ 0, DebugType,
390 /*IsLocalToUnit*/ false);
391 RefGV->addDebugInfo(GVE);
392
393 // Store the __ref_* in RefMapping so that future calls use the same RefGV.
394 ReplaceWithRefGV = RefGV;
395
396 return RefGV;
397}
398
399// Given a ConstantExpr, this searches for GlobalVariable references within
400// the expression tree. If found, it will generate instructions and will
401// return a non-null Value* that points to the new root instruction.
402//
403// If C does not contain any GlobalVariable references, this returns nullptr.
404//
405// If this function creates new instructions, then it will insert them
406// before InsertionPoint.
409 IRBuilder<> &IRBuilderAtEntry) {
410 if (C->getValueID() == Value::GlobalVariableVal) {
413 return GVLoadMap.at(GV);
414 } else {
415 return nullptr;
416 }
417 }
418
419 // Scan the operands of this expression.
420
421 SmallVector<Value *, 8> ReplacedValues;
422 bool ReplacedAnyOperands = false;
423
424 unsigned NumOperands = C->getNumOperands();
425 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) {
426 Value *OldValue = C->getOperand(OpIndex);
427 Value *ReplacedValue = nullptr;
428 if (Constant *OldConstant = dyn_cast<Constant>(OldValue)) {
429 ReplacedValue = rewriteGlobalVariablesInConstant(OldConstant, GVLoadMap,
430 IRBuilderAtEntry);
431 }
432 // Do not use short-circuiting, here. We need to traverse the whole tree.
433 ReplacedAnyOperands |= ReplacedValue != nullptr;
434 ReplacedValues.push_back(ReplacedValue);
435 }
436
437 // If none of our operands were replaced, then don't rewrite this expression.
438 if (!ReplacedAnyOperands) {
439 return nullptr;
440 }
441
442 // We need to rewrite this expression. Convert this constant expression
443 // to an instruction, then replace any operands as needed.
444 Instruction *NewInst = cast<ConstantExpr>(C)->getAsInstruction();
445 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) {
446 Value *ReplacedValue = ReplacedValues[OpIndex];
447 if (ReplacedValue != nullptr) {
448 NewInst->setOperand(OpIndex, ReplacedValue);
449 }
450 }
451
452 // Insert the new instruction before the reference instruction.
453 IRBuilderAtEntry.Insert(NewInst);
454
455 return NewInst;
456}
457
461
464 GVLoadMap[GV] = nullptr;
465 return true;
466 } else {
467 return false;
468 }
469 }
470
471 if (User *U = dyn_cast<User>(V)) {
472 unsigned NumOperands = U->getNumOperands();
473 bool FoundAny = false;
474 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) {
475 Value *Op = U->getOperand(OpIndex);
476 // Do not use short-circuiting, here. We need to traverse the whole tree.
477 FoundAny |= searchConstantExprForGlobalVariables(Op, GVLoadMap, GVUses);
478 }
479 return FoundAny;
480 } else {
481 return false;
482 }
483}
484
485// Processes a function that is marked for hot-patching.
486//
487// If a function is marked for hot-patching, we generate an S_HOTPATCHFUNC
488// CodeView debug symbol. Tools that generate hot-patches look for
489// S_HOTPATCHFUNC in final PDBs so that they can find functions that have been
490// hot-patched and so that they can distinguish hot-patched functions from
491// non-hot-patched functions.
492//
493// Also, in functions that are hot-patched, we must indirect all access to
494// (mutable) global variables through a pointer. This pointer may point into the
495// unpatched ("base") binary or may point into the patched image, depending on
496// whether a hot-patch was loaded as a patch or as a base image. These
497// indirections go through a new global variable, named `__ref_<Foo>` where
498// `<Foo>` is the original symbol name of the global variable.
499//
500// This function handles rewriting accesses to global variables, but the
501// generation of S_HOTPATCHFUNC occurs in
502// CodeViewDebug::emitHotPatchInformation().
503//
504// Returns true if any global variable references were found and rewritten.
505bool WindowsSecureHotPatching::runOnFunction(
506 Function &F,
507 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping) {
508 // Scan the function for references to global variables. If we find such a
509 // reference, create (if necessary) the __ref_* variable, then add an entry
510 // to the GVUses table.
511 //
512 // We ignore references to global variables if the variable is marked with
513 // AllowDirectAccessInHotPatchFunction.
514
515 SmallDenseMap<GlobalVariable *, Value *> GVLoadMap;
517
518 for (auto &I : instructions(F)) {
519 unsigned NumOperands = I.getNumOperands();
520 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) {
521 Value *V = I.getOperand(OpIndex);
522
523 bool FoundAnyGVUses = false;
524
525 switch (V->getValueID()) {
526 case Value::GlobalVariableVal: {
527 // Discover all uses of GlobalVariable, these will need to be replaced.
528 GlobalVariable *GV = cast<GlobalVariable>(V);
530 GVLoadMap.insert(std::make_pair(GV, nullptr));
531 FoundAnyGVUses = true;
532 }
533 break;
534 }
535
536 case Value::ConstantExprVal: {
537 ConstantExpr *CE = cast<ConstantExpr>(V);
538 if (searchConstantExprForGlobalVariables(CE, GVLoadMap, GVUses)) {
539 FoundAnyGVUses = true;
540 }
541 break;
542 }
543
544 default:
545 break;
546 }
547
548 if (FoundAnyGVUses) {
549 GVUses.push_back(GlobalVariableUse{&I, OpIndex});
550 }
551 }
552 }
553
554 // If this function did not reference any global variables then we have no
555 // work to do. Most functions do not access global variables.
556 if (GVUses.empty()) {
557 return false;
558 }
559
560 // We know that there is at least one instruction that needs to be rewritten.
561 // Generate a Load instruction for each unique GlobalVariable used by this
562 // function. The Load instructions are inserted at the beginning of the
563 // entry block. Since entry blocks cannot contain PHI instructions, there is
564 // no need to skip PHI instructions.
565
566 // We use a single IRBuilder for inserting Load instructions as well as the
567 // constants that we convert to instructions. Because constants do not
568 // depend on any dynamic values (they're constant, after all!), it is safe
569 // to move them to the start of entry BB.
570
571 auto &EntryBlock = F.getEntryBlock();
572 IRBuilder<> IRBuilderAtEntry(&EntryBlock, EntryBlock.begin());
573
574 for (auto &[GV, LoadValue] : GVLoadMap) {
575 assert(LoadValue == nullptr);
576 GlobalVariable *RefGV = getOrCreateRefVariable(F, RefMapping, GV);
577 LoadValue = IRBuilderAtEntry.CreateLoad(RefGV->getValueType(), RefGV);
578 }
579
580 const DISubprogram *Subprogram = F.getSubprogram();
581 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr;
582 DIBuilder DebugInfo{*F.getParent(), true, Unit};
583
584 // Go back to the instructions and rewrite their uses of GlobalVariable.
585 // Because a ConstantExpr can be a tree, it may reference more than one
586 // GlobalVariable.
587
588 for (auto &GVUse : GVUses) {
589 Value *OldOperandValue = GVUse.User->getOperand(GVUse.Op);
590 Value *NewOperandValue;
591
592 switch (OldOperandValue->getValueID()) {
593 case Value::GlobalVariableVal: {
594 // This is easy. Look up the replacement value and store the operand.
595 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
596 GlobalVariable *GV = cast<GlobalVariable>(OperandValue);
597 NewOperandValue = GVLoadMap.at(GV);
598 break;
599 }
600
601 case Value::ConstantExprVal: {
602 // Walk the recursive tree of the ConstantExpr. If we find a
603 // GlobalVariable then replace it with the loaded value and rewrite
604 // the ConstantExpr to an Instruction and insert it before the
605 // current instruction.
606 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
607 ConstantExpr *CE = cast<ConstantExpr>(OperandValue);
608 NewOperandValue =
609 rewriteGlobalVariablesInConstant(CE, GVLoadMap, IRBuilderAtEntry);
610 assert(NewOperandValue != nullptr);
611 break;
612 }
613
614 default:
615 // We should only ever get here because a GVUse was created in the first
616 // pass, and this only happens for GlobalVariableVal and ConstantExprVal.
618 "unexpected Value in second pass of hot-patching");
619 break;
620 }
621
622 GVUse.User->setOperand(GVUse.Op, NewOperandValue);
623 }
624
625 return true;
626}
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.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
unsigned OpIndex
This file defines the SmallSet class.
static GlobalVariable * getOrCreateRefVariable(Function &F, SmallDenseMap< GlobalVariable *, GlobalVariable * > &RefMapping, GlobalVariable *GV)
static bool globalVariableNeedsRedirect(GlobalVariable *GV)
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)
static Value * rewriteGlobalVariablesInConstant(Constant *C, SmallDenseMap< GlobalVariable *, Value * > &GVLoadMap, IRBuilder<> &IRBuilderAtEntry)
static bool TypeContainsPointers(Type *ty)
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:
Definition Pass.cpp:270
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
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.
Definition Constants.h:1284
This is an important base class in LLVM.
Definition Constant.h:43
A pair of DIGlobalVariable and DIExpression.
DIFile * getFile() const
Subprogram description. Uses SubclassData1.
Base class for types.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
Definition DataLayout.h:771
ValueT & at(const_arg_type_t< KeyT > Val)
at - Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:224
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:256
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:241
@ LinkOnceAnyLinkage
Keep one copy of function when linking (inline)
Definition GlobalValue.h:55
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.
Definition IRBuilder.h:172
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2776
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...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
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.
Definition SmallSet.h:228
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:183
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.
Definition StringRef.h:55
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:261
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM_ABI Type * getStructElementType(unsigned N) const
Type * getArrayElementType() const
Definition Type.h:408
LLVM_ABI unsigned getStructNumElements() const
@ ArrayTyID
Arrays.
Definition Type.h:74
@ StructTyID
Structures.
Definition Type.h:73
@ PointerTyID
Pointers.
Definition Type.h:72
TypeID getTypeID() const
Return the type id for the type.
Definition Type.h:136
void setOperand(unsigned i, Value *Val)
Definition User.h:212
LLVM Value Representation.
Definition Value.h:75
unsigned getValueID() const
Return an ID for the concrete type of this object.
Definition Value.h:543
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:48
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1150
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...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI ModulePass * createWindowsSecureHotPatchingPass()
Creates Windows Secure Hot Patch pass.