[llvm] Hot-patch __ref_* variables should be placed in .rdata, not .data (PR #151008)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 28 11:09:27 PDT 2025


https://github.com/sivadeilra created https://github.com/llvm/llvm-project/pull/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.


>From d17d0ddda3d2ac74d5005f539fb28c97e41de781 Mon Sep 17 00:00:00 2001
From: Arlie Davis <ardavis at microsoft.com>
Date: Mon, 28 Jul 2025 11:03:33 -0700
Subject: [PATCH] Hot-patch __ref_* variables should be placed in .rdata, not
 .data

---
 llvm/lib/CodeGen/WindowsSecureHotPatching.cpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp b/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp
index 6267207dbcbff..fd54190b04468 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(



More information about the llvm-commits mailing list