-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add x86 specific hotpatch flag to rustc #124966
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 7 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
b473e9c
Add hotpatch flag. Proof of concept only working on x86/x64.
nebulark ef9f88f
tidy
nebulark 068ecd4
Added tests to validate functions are hotpatchable
nebulark 8d9009f
seperated hotpatch test types, improved tests
nebulark 06b559a
simplified tests
nebulark 13bc998
automatically set hotpatch for aarch64 as it already fulfils the cond…
nebulark 8764e73
added new test. Adjusted test as we dropped the 'no jump to first ins…
nebulark 4f2ba9c
fixed/cleaned up tests
nebulark 963919a
adjusted tests
nebulark d898368
improved variable name
nebulark File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
//@ revisions: x32 x64 | ||
//@[x32] only-x86 | ||
//@[x64] only-x86_64 | ||
//@ compile-flags: -Z hotpatch | ||
|
||
#![crate_type = "lib"] | ||
|
||
#[no_mangle] | ||
pub fn foo() {} | ||
|
||
// CHECK: @foo() unnamed_addr #0 | ||
// CHECK: attributes #0 = { {{.*}} "patchable-function"="prologue-short-redirect" {{.*}}} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// hotpatch has two requirements: | ||
// 1. the first instruction of a functin must be at least two bytes long | ||
// 2. there must not be a jump to the first instruction | ||
|
||
// the functions in this file already fulfill the conditions so hotpatch should not affect them | ||
|
||
// -------------------------------------------------------------------------------------------- | ||
|
||
#[no_mangle] | ||
#[inline(never)] | ||
pub fn return_42() -> i32 { | ||
42 | ||
} | ||
|
||
// -------------------------------------------------------------------------------------------- | ||
// This tailcall does not jump to the first instruction so hotpatch should leave it unaffected | ||
|
||
#[no_mangle] | ||
pub fn tailcall(a: i32) -> i32 { | ||
if a > 10000 { | ||
return a; | ||
} | ||
|
||
if a % 2 == 0 { tailcall(a / 2) } else { tailcall(a * 3 + 1) } | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Check if hotpatch leaves the functions that are already hotpatchable untouched | ||
|
||
//@ revisions: x32 x64 aarch64 | ||
//@[x32] only-x86 | ||
//@[x64] only-x86_64 | ||
//@[aarch64] only-aarch64 | ||
jieyouxu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Reason: hotpatch is only implemented for X86 and aarch64 | ||
|
||
use run_make_support::{assertion_helpers, llvm, rustc}; | ||
|
||
fn main() { | ||
fn base_rustc() -> rustc::Rustc { | ||
let mut rustc = rustc(); | ||
rustc.input("lib.rs").crate_type("lib").opt_level("3"); | ||
rustc | ||
} | ||
|
||
fn dump_lib(libname: &str) -> String { | ||
llvm::llvm_objdump() | ||
.arg("--disassemble-symbols=return_42,tailcall") | ||
.input(libname) | ||
.run() | ||
.stdout_utf8() | ||
} | ||
|
||
base_rustc().crate_name("regular").run(); | ||
let regular_dump = dump_lib("libregular.rlib"); | ||
|
||
base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); | ||
let hotpatch_dump = dump_lib("libhotpatch.rlib"); | ||
|
||
{ | ||
let mut lines_regular = regular_dump.lines(); | ||
let mut lines_hotpatch = hotpatch_dump.lines(); | ||
|
||
loop { | ||
match (lines_regular.next(), lines_hotpatch.next()) { | ||
(None, None) => break, | ||
(Some(r), Some(h)) => { | ||
if r.contains("libregular.rlib") { | ||
assertion_helpers::assert_contains(h, "libhotpatch.rlib") | ||
} else { | ||
assertion_helpers::assert_equals(&r, &h) | ||
} | ||
} | ||
_ => panic!("expected files to have equal number of lines"), | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// hotpatch has two requirements: | ||
// 1) the first instruction of a functin must be at least two bytes long | ||
// 2) there must not be a jump to the first instruction | ||
|
||
// The LLVM attribute we use '"patchable-function", "prologue-short-redirect"' only ensures 1) | ||
// However in practice 2) rarely matters. Its rare that it occurs and the problems it caused can be | ||
// avoided by the hotpatch tool. | ||
// In this test we check if 1) is ensured by inserted nops as needed | ||
|
||
// ---------------------------------------------------------------------------------------------- | ||
|
||
// empty_fn just returns. Note that 'ret' is a single byte instruction, but hotpatch requires | ||
// a two or more byte instructions to be at the start of the functions. | ||
// Preferably we would also tests a different single byte instruction, | ||
// but I was not able to find an example with another one byte intstruction. | ||
|
||
// check that if the first instruction is just a single byte, so our test is valid | ||
// CHECK-LABEL: <empty_fn>: | ||
// CHECK-NOT: 0: {{[0-9a-f][0-9a-f]}} {{[0-9a-f][0-9a-f]}} {{.*}} | ||
|
||
// check that the first instruction is at least 2 bytes long | ||
// HOTPATCH-LABEL: <empty_fn>: | ||
// HOTPATCH-NEXT: 0: {{[0-9a-f][0-9a-f]}} {{[0-9a-f][0-9a-f]}} {{.*}} | ||
|
||
#[no_mangle] | ||
#[inline(never)] | ||
pub fn empty_fn() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Check if hotpatch makes the functions hotpachable that were not | ||
// More details in lib.rs | ||
|
||
//@ revisions: x32 x64 | ||
//@[x32] only-x86 | ||
//@[x64] only-x86_64 | ||
jieyouxu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Reason: hotpatch is only implemented for x86 and aarch64, but for aarch64 they | ||
// are always hotpatchable so we don't need to check it | ||
|
||
use run_make_support::{llvm, rustc}; | ||
|
||
fn main() { | ||
fn base_rustc() -> rustc::Rustc { | ||
let mut rustc = rustc(); | ||
rustc.input("lib.rs").crate_type("lib").opt_level("3"); | ||
rustc | ||
} | ||
|
||
fn dump_lib(libname: &str) -> String { | ||
llvm::llvm_objdump() | ||
.arg("--disassemble-symbols=empty_fn") | ||
.input(libname) | ||
.run() | ||
.stdout_utf8() | ||
} | ||
|
||
{ | ||
base_rustc().crate_name("regular").run(); | ||
let regular_dump = dump_lib("libregular.rlib"); | ||
llvm::llvm_filecheck().patterns("lib.rs").stdin_buf(regular_dump).run(); | ||
} | ||
|
||
{ | ||
base_rustc().crate_name("hotpatch").arg("-Zhotpatch").run(); | ||
let hotpatch_dump = dump_lib("libhotpatch.rlib"); | ||
|
||
llvm::llvm_filecheck() | ||
.patterns("lib.rs") | ||
.check_prefix("HOTPATCH") | ||
.stdin_buf(hotpatch_dump) | ||
.run(); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// CHECK: S_OBJNAME{{.*}}hotpatch_pdb{{.*}}.o | ||
// CHECK: S_COMPILE3 | ||
// CHECK-NOT: S_ | ||
// CHECK: flags = {{.*}}hot patchable | ||
|
||
pub fn main() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Check if hotpatch flag is present in the Codeview. | ||
// This is need so linkers actually pad functions when given the functionpadmin arg. | ||
|
||
//@ revisions: x32 x64 aarch64 | ||
//@[x32] only-x86 | ||
//@[x64] only-x86_64 | ||
//@[aarch64] only-aarch64 | ||
jieyouxu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Reason: Hotpatch is only implemented for x86 and aarch64 | ||
|
||
use run_make_support::{llvm, rustc}; | ||
|
||
fn main() { | ||
let output = rustc() | ||
.input("main.rs") | ||
.arg("-g") | ||
.arg("-Zhotpatch") | ||
.crate_name("hotpatch_pdb") | ||
.crate_type("bin") | ||
.run(); | ||
|
||
let pdbutil_output = llvm::llvm_pdbutil() | ||
.arg("dump") | ||
.arg("-symbols") | ||
.input("hotpatch_pdb.pdb") | ||
.run() | ||
.stdout_utf8(); | ||
|
||
llvm::llvm_filecheck().patterns("main.rs").stdin_buf(&pdbutil_output).run(); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.