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 {
180 WindowsSecureHotPatching() : ModulePass(ID) {}
182 void getAnalysisUsage(AnalysisUsage &AU)
const override {
186 bool doInitialization(
Module &)
override;
187 bool runOnModule(
Module &M)
override {
return false; }
192 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping);
197char WindowsSecureHotPatching::ID = 0;
200 "Mark functions for Windows hot patch support",
false,
false)
202 return new WindowsSecureHotPatching();
210bool WindowsSecureHotPatching::doInitialization(
Module &M) {
217 std::vector<std::string> HotPatchFunctionsList;
222 const MemoryBuffer &FileBuffer = **BufOrErr;
225 HotPatchFunctionsList.push_back(std::string{*
I});
227 M.getContext().diagnose(DiagnosticInfoGeneric{
228 Twine(
"failed to open hotpatch functions file "
229 "(--ms-hotpatch-functions-file): ") +
231 BufOrErr.getError().message()});
237 HotPatchFunctionsList.push_back(FuncName);
241 SmallSet<StringRef, 16> HotPatchFunctionsSet;
242 for (
const auto &FuncName : HotPatchFunctionsList)
243 HotPatchFunctionsSet.
insert(StringRef{FuncName});
247 for (
auto &
F :
M.functions()) {
249 if (
F.isDeclarationForLinker())
252 if (HotPatchFunctionsSet.
contains(
F.getName()))
253 F.addFnAttr(
"marked_for_windows_hot_patching");
257 SmallDenseMap<GlobalVariable *, GlobalVariable *> RefMapping;
258 bool MadeChanges =
false;
259 for (
auto &
F :
M.functions()) {
260 if (
F.hasFnAttribute(
"marked_for_windows_hot_patching")) {
278 for (
unsigned I = 0;
I < NumElements; ++
I) {
295 if (GV->
hasAttribute(
"allow_direct_access_in_hot_patch_function"))
348 if (ReplaceWithRefGV !=
nullptr) {
350 return ReplaceWithRefGV;
356 DICompileUnit *Unit = Subprogram !=
nullptr ? Subprogram->getUnit() :
nullptr;
357 DIFile *File = Subprogram !=
nullptr ? Subprogram->
getFile() :
nullptr;
381 RefGV->setSection(
".rdata");
388 Unit, RefGV->getName(),
StringRef{}, File,
391 RefGV->addDebugInfo(GVE);
394 ReplaceWithRefGV = RefGV;
410 if (
C->getValueID() == Value::GlobalVariableVal) {
413 return GVLoadMap.
at(GV);
422 bool ReplacedAnyOperands =
false;
424 unsigned NumOperands =
C->getNumOperands();
427 Value *ReplacedValue =
nullptr;
433 ReplacedAnyOperands |= ReplacedValue !=
nullptr;
438 if (!ReplacedAnyOperands) {
447 if (ReplacedValue !=
nullptr) {
453 IRBuilderAtEntry.
Insert(NewInst);
464 GVLoadMap[GV] =
nullptr;
472 unsigned NumOperands = U->getNumOperands();
473 bool FoundAny =
false;
505bool WindowsSecureHotPatching::runOnFunction(
507 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping) {
515 SmallDenseMap<GlobalVariable *, Value *> GVLoadMap;
519 unsigned NumOperands =
I.getNumOperands();
523 bool FoundAnyGVUses =
false;
525 switch (
V->getValueID()) {
526 case Value::GlobalVariableVal: {
530 GVLoadMap.
insert(std::make_pair(GV,
nullptr));
531 FoundAnyGVUses =
true;
536 case Value::ConstantExprVal: {
539 FoundAnyGVUses =
true;
548 if (FoundAnyGVUses) {
556 if (GVUses.
empty()) {
571 auto &EntryBlock =
F.getEntryBlock();
572 IRBuilder<> IRBuilderAtEntry(&EntryBlock, EntryBlock.begin());
574 for (
auto &[GV, LoadValue] : GVLoadMap) {
575 assert(LoadValue ==
nullptr);
577 LoadValue = IRBuilderAtEntry.CreateLoad(RefGV->
getValueType(), RefGV);
580 const DISubprogram *Subprogram =
F.getSubprogram();
581 DICompileUnit *
Unit = Subprogram !=
nullptr ? Subprogram->getUnit() :
nullptr;
588 for (
auto &GVUse : GVUses) {
589 Value *OldOperandValue = GVUse.User->getOperand(GVUse.Op);
590 Value *NewOperandValue;
593 case Value::GlobalVariableVal: {
595 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
597 NewOperandValue = GVLoadMap.at(GV);
601 case Value::ConstantExprVal: {
606 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);
610 assert(NewOperandValue !=
nullptr);
618 "unexpected Value in second pass of hot-patching");
622 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 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)
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:
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 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<X> - 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...
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.
LLVM_ABI ModulePass * createWindowsSecureHotPatchingPass()
Creates Windows Secure Hot Patch pass.