153#define DEBUG_TYPE "windows-secure-hot-patch"
158 cl::desc(
"A file containing list of mangled function names to mark for "
159 "Windows Secure Hot-Patching"));
164 cl::desc(
"A list of mangled function names to mark for Windows Secure "
170struct GlobalVariableUse {
176class WindowsSecureHotPatching :
public ModulePass {
199char WindowsSecureHotPatching::ID = 0;
202 "Mark functions for Windows hot patch support",
false,
false)
204 return new WindowsSecureHotPatching();
212bool WindowsSecureHotPatching::doInitialization(
Module &M) {
219 std::vector<std::string> HotPatchFunctionsList;
227 HotPatchFunctionsList.push_back(std::string{*
I});
230 Twine(
"failed to open hotpatch functions file "
231 "(--ms-hotpatch-functions-file): ") +
233 BufOrErr.getError().message()});
239 HotPatchFunctionsList.push_back(FuncName);
244 for (
const auto &FuncName : HotPatchFunctionsList)
249 for (
auto &
F :
M.functions()) {
251 if (
F.isDeclarationForLinker())
254 if (HotPatchFunctionsSet.
contains(
F.getName()))
255 F.addFnAttr(
"marked_for_windows_hot_patching");
260 bool MadeChanges =
false;
261 for (
auto &
F :
M.functions()) {
262 if (
F.hasFnAttribute(
"marked_for_windows_hot_patching")) {
280 for (
unsigned I = 0;
I < NumElements; ++
I) {
297 if (GV->
hasAttribute(
"allow_direct_access_in_hot_patch_function"))
350 if (ReplaceWithRefGV !=
nullptr) {
352 return ReplaceWithRefGV;
358 DICompileUnit *Unit = Subprogram !=
nullptr ? Subprogram->getUnit() :
nullptr;
359 DIFile *File = Subprogram !=
nullptr ? Subprogram->
getFile() :
nullptr;
362 auto PtrTy = PointerType::get(M->getContext(), 0);
370 nullptr, GlobalVariable::NotThreadLocal);
383 RefGV->setSection(
".rdata");
390 Unit, RefGV->getName(),
StringRef{}, File,
393 RefGV->addDebugInfo(GVE);
396 ReplaceWithRefGV = RefGV;
412 if (
C->getValueID() == Value::GlobalVariableVal) {
415 return GVLoadMap.
at(GV);
424 bool ReplacedAnyOperands =
false;
426 unsigned NumOperands =
C->getNumOperands();
429 Value *ReplacedValue =
nullptr;
430 if (
Constant *OldConstant = dyn_cast<Constant>(OldValue)) {
435 ReplacedAnyOperands |= ReplacedValue !=
nullptr;
440 if (!ReplacedAnyOperands) {
446 Instruction *NewInst = cast<ConstantExpr>(
C)->getAsInstruction();
449 if (ReplacedValue !=
nullptr) {
455 IRBuilderAtEntry.
Insert(NewInst);
468 GVLoadMap[GV] =
nullptr;
475 if (
User *U = dyn_cast<User>(V)) {
476 unsigned NumOperands = U->getNumOperands();
477 bool FoundAny =
false;
509bool WindowsSecureHotPatching::runOnFunction(
523 unsigned NumOperands =
I.getNumOperands();
527 bool FoundAnyGVUses =
false;
529 switch (
V->getValueID()) {
530 case Value::GlobalVariableVal: {
534 GVLoadMap.
insert(std::make_pair(GV,
nullptr));
535 FoundAnyGVUses =
true;
540 case Value::ConstantExprVal: {
543 FoundAnyGVUses =
true;
552 if (FoundAnyGVUses) {
560 if (GVUses.
empty()) {
575 auto &EntryBlock =
F.getEntryBlock();
576 IRBuilder<> IRBuilderAtEntry(&EntryBlock, EntryBlock.begin());
578 for (
auto &[GV,
LoadValue] : GVLoadMap) {
585 DICompileUnit *Unit = Subprogram !=
nullptr ? Subprogram->getUnit() :
nullptr;
592 for (
auto &GVUse : GVUses) {
593 Value *OldOperandValue = GVUse.User->getOperand(GVUse.Op);
594 Value *NewOperandValue;
597 case Value::GlobalVariableVal: {
599 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
601 NewOperandValue = GVLoadMap.at(GV);
605 case Value::ConstantExprVal: {
610 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
614 assert(NewOperandValue !=
nullptr);
622 "unexpected Value in second pass of hot-patching");
626 GVUse.User->setOperand(GVUse.Op, NewOperandValue);
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 bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
#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)
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"))
Represent the analysis usage information of a pass.
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),...
A constant value that is initialized with an expression using other constant values.
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.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
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...
This interface provides simple read-only access to a block of memory, and provides simple methods for...
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...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
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...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
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.
Type * getArrayElementType() const
TypeID getTypeID() const
Return the type id for the type.
LLVM_ABI Type * getStructElementType(unsigned N) const
LLVM_ABI unsigned getStructNumElements() const
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.
A forward iterator which reads text lines from a buffer.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
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.
LLVM_ABI void initializeWindowsSecureHotPatchingPass(PassRegistry &)
LLVM_ABI ModulePass * createWindowsSecureHotPatchingPass()
Creates Windows Secure Hot Patch pass.