diff options
author | sivadeilra <ardavis@microsoft.com> | 2025-07-28 16:15:02 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-28 16:15:02 -0700 |
commit | 8ecbfa66cd314df805e2910783ded37f2f8621b4 (patch) | |
tree | 133a5c79cbe4efeecb760445c15da4dae5e43dad /llvm/lib | |
parent | ee63c1f3520bca0acb859fcb4da49d3eb667c1ad (diff) | |
download | llvm-8ecbfa66cd314df805e2910783ded37f2f8621b4.zip llvm-8ecbfa66cd314df805e2910783ded37f2f8621b4.tar.gz llvm-8ecbfa66cd314df805e2910783ded37f2f8621b4.tar.bz2 |
Hot-patch __ref_* variables should be placed in .rdata, not .data (#151008)
This is a refinment of #145565 . That PR added support for "Windows
Secure Hot-patching". In this design, functions that are compiled for
hot-patching need to be modified when they access mutable global
variables. The modification is to insert a level of indirection, the
so-called `__ref_*` variables.
Ref variables are supposed to be inserted into the `.rdata` section, not
`.data`. This provides a degree of protection against modification
(accidental or malicious) of ref variables during program execution.
When the Windows hot-patch subsystem loads a module as a hot-patch, it
finds all ref variables and changes the page protections for the pages
containing them to read/write. Then it sets the ref variables to point
to the real variable locations within the base image. Then it changes
page protections back to read-only.
This relies on the variables being placed in the `.rdata` section, not
`.data`.
However, it is still important that the LLVM `GlobalVariable` that is
created for the ref variable be created with `isConstant = false`. This
prevents LLVM from optimizing accesses to the `GlobalVariable`, i.e.
assuming that the variable can never change and thus inlining its value
into expressions that would ordinarily dereference it. That optimization
would defeat the purpose of hot-patching, so `isConstant = false` is
still the correct value for these ref variables.
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/WindowsSecureHotPatching.cpp | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp b/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp index 6267207..fd54190 100644 --- a/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp +++ b/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp @@ -369,6 +369,19 @@ static GlobalVariable *getOrCreateRefVariable( AddrOfOldGV, Twine("__ref_").concat(GV->getName()), nullptr, GlobalVariable::NotThreadLocal); + // RefGV is created with isConstant = false, but we want to place RefGV into + // .rdata, not .data. It is important that the GlobalVariable be mutable + // from the compiler's point of view, so that the optimizer does not remove + // the global variable entirely and replace all references to it with its + // initial value. + // + // When the Windows hot-patch loader applies a hot-patch, it maps the + // pages of .rdata as read/write so that it can set each __ref_* variable + // to point to the original variable in the base image. Afterward, pages in + // .rdata are remapped as read-only. This protects the __ref_* variables from + // being overwritten during execution. + RefGV->setSection(".rdata"); + // Create debug info for the replacement global variable. DataLayout Layout = M->getDataLayout(); DIType *DebugType = DebugInfo.createPointerType( |