diff options
author | sivadeilra <ardavis@microsoft.com> | 2025-06-24 09:22:38 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-24 09:22:38 -0700 |
commit | 26d318e4a9437f95b6a2e7abace5f2b867c88a3e (patch) | |
tree | 1b4432f9b26dd01065941f1b83bbc466a2ea01b6 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | e175ecff936287823b5443d7b2d443fc6569f31f (diff) | |
download | llvm-26d318e4a9437f95b6a2e7abace5f2b867c88a3e.zip llvm-26d318e4a9437f95b6a2e7abace5f2b867c88a3e.tar.gz llvm-26d318e4a9437f95b6a2e7abace5f2b867c88a3e.tar.bz2 |
Add support for Windows Secure Hot-Patching (#138972)
This PR adds some of the support needed for Windows hot-patching.
Windows implements a form of hot-patching. This allows patches to be
applied to Windows apps, drivers, and the kernel, without rebooting or
restarting any of these components. Hot-patching is a complex technology
and requires coordination between the OS, compilers, linkers, and
additional tools.
This PR adds support to Clang and LLVM for part of the hot-patching
process. It enables LLVM to generate the required code changes and to
generate CodeView symbols which identify hot-patched functions. The PR
provides new command-line arguments to Clang which allow developers to
identify the list of functions that need to be hot-patched. This PR also
allows LLVM to directly receive the list of functions to be modified, so
that language front-ends which have not yet been modified (such as Rust)
can still make use of hot-patching.
This PR:
* Adds a `MarkedForWindowsHotPatching` LLVM function attribute. This
attribute indicates that a function should be _hot-patched_. This
generates a new CodeView symbol, `S_HOTPATCHFUNC`, which identifies any
function that has been hot-patched. This attribute also causes accesses
to global variables to be indirected through a `_ref_*` global variable.
This allows hot-patched functions to access the correct version of a
global variable; the hot-patched code needs to access the variable in
the _original_ image, not the patch image.
* Adds a `AllowDirectAccessInHotPatchFunction` LLVM attribute. This
attribute may be placed on global variable declarations. It indicates
that the variable may be safely accessed without the `_ref_*`
indirection.
* Adds two Clang command-line parameters: `-fms-hotpatch-functions-file`
and `-fms-hotpatch-functions-list`. The `-file` flag may point to a text
file, which contains a list of functions to be hot-patched (one function
name per line). The `-list` flag simply directly identifies functions to
be patched, using a comma-separated list. These two command-line
parameters may also be combined; the final set of functions to be
hot-patched is the union of the two sets.
* Adds similar LLVM command-line parameters:
`--ms-hotpatch-functions-file` and `--ms-hotpatch-functions-list`.
* Adds integration tests for both LLVM and Clang.
* Adds support for dumping the new `S_HOTPATCHFUNC` CodeView symbol.
Although the flags are redundant between Clang and LLVM, this allows
additional languages (such as Rust) to take advantage of hot-patching
support before they have been modified to generate the required
attributes.
Credit to @dpaoliello, who wrote the original form of this patch.
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 1668881..96fdab2 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -458,6 +458,35 @@ CodeGenModule::CodeGenModule(ASTContext &C, if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters", CodeGenOpts.NumRegisterParameters); + + // If there are any functions that are marked for Windows secure hot-patching, + // then build the list of functions now. + if (!CGO.MSSecureHotPatchFunctionsFile.empty() || + !CGO.MSSecureHotPatchFunctionsList.empty()) { + if (!CGO.MSSecureHotPatchFunctionsFile.empty()) { + auto BufOrErr = + llvm::MemoryBuffer::getFile(CGO.MSSecureHotPatchFunctionsFile); + if (BufOrErr) { + const llvm::MemoryBuffer &FileBuffer = **BufOrErr; + for (llvm::line_iterator I(FileBuffer.getMemBufferRef(), true), E; + I != E; ++I) + this->MSHotPatchFunctions.push_back(std::string{*I}); + } else { + auto &DE = Context.getDiagnostics(); + unsigned DiagID = + DE.getCustomDiagID(DiagnosticsEngine::Error, + "failed to open hotpatch functions file " + "(-fms-hotpatch-functions-file): %0 : %1"); + DE.Report(DiagID) << CGO.MSSecureHotPatchFunctionsFile + << BufOrErr.getError().message(); + } + } + + for (const auto &FuncName : CGO.MSSecureHotPatchFunctionsList) + this->MSHotPatchFunctions.push_back(FuncName); + + llvm::sort(this->MSHotPatchFunctions); + } } CodeGenModule::~CodeGenModule() {} |