llvm-project/llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-file.ll
sivadeilra 0a3c5c42a1
Add support for Windows Secure Hot-Patching (redo) (#145565)
(This is a re-do of #138972, which had a minor warning in `Clang.cpp`.)

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.
2025-06-24 14:56:55 -07:00

40 lines
1.3 KiB
LLVM

; This tests annotating a function with marked_for_windows_hot_patching by using --ms-hotpatch-functions-file.
;
; RUN: echo this_gets_hotpatched > %t.patch-functions.txt
; RUN: llc -mtriple=x86_64-windows --ms-secure-hotpatch-functions-file=%t.patch-functions.txt < %s | FileCheck %s
source_filename = ".\\ms-secure-hotpatch-functions-file.ll"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.36.32537"
@some_global_var = external global i32
define noundef i32 @this_gets_hotpatched() #0 {
%1 = load i32, ptr @some_global_var
%2 = add i32 %1, 1
ret i32 %2
}
attributes #0 = { mustprogress noinline nounwind optnone uwtable }
; CHECK: this_gets_hotpatched: # @this_gets_hotpatched
; CHECK-NEXT: bb.0:
; CHECK-NEXT: movq __ref_some_global_var(%rip), %rax
; CHECK-NEXT: movl (%rax), %eax
; CHECK-NEXT: addl $1, %eax
; CHECK-NEXT: retq
define noundef i32 @this_does_not_get_hotpatched() #1 {
%1 = load i32, ptr @some_global_var
%2 = add i32 %1, 1
ret i32 %2
}
attributes #1 = { mustprogress noinline nounwind optnone uwtable }
; CHECK: this_does_not_get_hotpatched: # @this_does_not_get_hotpatched
; CHECK-NEXT: bb.0:
; CHECK-NEXT: movl some_global_var(%rip), %eax
; CHECK-NEXT: addl $1, %eax
; CHECK-NEXT: retq