
(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.
40 lines
1.3 KiB
LLVM
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
|