Skip to content

Commit 4422b3c

Browse files
committed
Add -Zindirect-branch-cs-prefix option
This is intended to be used for Linux kernel RETPOLINE builds. Co-developed-by: Alice Ryhl <[email protected]> Signed-off-by: Miguel Ojeda <[email protected]>
1 parent fcb32d7 commit 4422b3c

File tree

11 files changed

+114
-0
lines changed

11 files changed

+114
-0
lines changed

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,15 @@ pub(crate) unsafe fn create_module<'ll>(
443443
}
444444
}
445445

446+
if sess.opts.unstable_opts.indirect_branch_cs_prefix {
447+
llvm::add_module_flag_u32(
448+
llmod,
449+
llvm::ModuleFlagMergeBehavior::Override,
450+
"indirect_branch_cs_prefix",
451+
1,
452+
);
453+
}
454+
446455
match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
447456
{
448457
// Set up the small-data optimization limit for architectures that use

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ fn test_unstable_options_tracking_hash() {
802802
tracked!(function_sections, Some(false));
803803
tracked!(human_readable_cgu_names, true);
804804
tracked!(incremental_ignore_spans, true);
805+
tracked!(indirect_branch_cs_prefix, true);
805806
tracked!(inline_mir, Some(true));
806807
tracked!(inline_mir_hint_threshold, Some(123));
807808
tracked!(inline_mir_threshold, Some(123));

compiler/rustc_session/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ session_hexadecimal_float_literal_not_supported = hexadecimal float literal is n
4949
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
5050
.note = compatible flavors are: {$compatible_list}
5151
52+
session_indirect_branch_cs_prefix_requires_x86_or_x86_64 = `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64
53+
5254
session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
5355
5456
session_int_literal_too_large = integer literal is too large

compiler/rustc_session/src/errors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,10 @@ pub(crate) struct FunctionReturnRequiresX86OrX8664;
471471
#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
472472
pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
473473

474+
#[derive(Diagnostic)]
475+
#[diag(session_indirect_branch_cs_prefix_requires_x86_or_x86_64)]
476+
pub(crate) struct IndirectBranchCsPrefixRequiresX86OrX8664;
477+
474478
#[derive(Diagnostic)]
475479
#[diag(session_unsupported_regparm)]
476480
pub(crate) struct UnsupportedRegparm {

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,6 +2286,8 @@ options! {
22862286
- hashes of green query instances
22872287
- hash collisions of query keys
22882288
- hash collisions when creating dep-nodes"),
2289+
indirect_branch_cs_prefix: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2290+
"add `cs` prefix to `call` and `jmp` to indirect thunk (default: no)"),
22892291
inline_llvm: bool = (true, parse_bool, [TRACKED],
22902292
"enable LLVM inlining (default: yes)"),
22912293
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],

compiler/rustc_session/src/session.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
13761376
}
13771377
}
13781378

1379+
if sess.opts.unstable_opts.indirect_branch_cs_prefix {
1380+
if sess.target.arch != "x86" && sess.target.arch != "x86_64" {
1381+
sess.dcx().emit_err(errors::IndirectBranchCsPrefixRequiresX86OrX8664);
1382+
}
1383+
}
1384+
13791385
if let Some(regparm) = sess.opts.unstable_opts.regparm {
13801386
if regparm > 3 {
13811387
sess.dcx().emit_err(errors::UnsupportedRegparm { regparm });
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# `indirect-branch-cs-prefix`
2+
3+
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116852.
4+
5+
------------------------
6+
7+
Option `-Zindirect-branch-cs-prefix` controls whether a `cs` prefix is added to
8+
`call` and `jmp` to indirect thunks.
9+
10+
It is equivalent to [Clang]'s and [GCC]'s `-mindirect-branch-cs-prefix`. The
11+
Linux kernel uses it for RETPOLINE builds. For details, see
12+
[LLVM commit 6f867f910283]("[X86] Support ``-mindirect-branch-cs-prefix`` for
13+
call and jmp to indirect thunk") which introduces the feature.
14+
15+
Only x86 is supported.
16+
17+
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mindirect-branch-cs-prefix
18+
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mindirect-branch-cs-prefix
19+
[LLVM commit 6f867f910283]: https://github.com/llvm/llvm-project/commit/6f867f9102838ebe314c1f3661fdf95700386e5a
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Test that the `cs` prefix is (not) added into a `call` and a `jmp` to the
2+
// indirect thunk when the `-Zindirect-branch-cs-prefix` flag is (not) set.
3+
4+
//@ revisions: unset set
5+
//@ assembly-output: emit-asm
6+
//@ compile-flags: -Copt-level=3 -Cunsafe-allow-abi-mismatch=retpoline,retpoline-external-thunk,indirect-branch-cs-prefix -Zretpoline-external-thunk
7+
//@ [set] compile-flags: -Zindirect-branch-cs-prefix
8+
//@ only-x86_64
9+
// TODO: This may be required here too: ignore-apple Symbol is called `___x86_return_thunk` (Darwin's extra underscore)
10+
// TODO: This may be required here too: ignore-sgx Tests incompatible with LVI mitigations
11+
12+
#![crate_type = "lib"]
13+
14+
// CHECK-LABEL: foo:
15+
#[no_mangle]
16+
pub fn foo(_: i32, _: i32, _: i32, _: i32, g: fn()) {
17+
// unset-NOT: cs
18+
// unset: callq {{__x86_indirect_thunk.*}}
19+
// set: cs
20+
// set: callq {{__x86_indirect_thunk.*}}
21+
g();
22+
23+
// unset-NOT: cs
24+
// unset: jmp {{__x86_indirect_thunk.*}}
25+
// set: cs
26+
// set: jmp {{__x86_indirect_thunk.*}}
27+
g();
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Test that the `indirect_branch_cs_prefix` module attribute is (not)
2+
// emitted when the `-Zindirect-branch-cs-prefix` flag is (not) set.
3+
4+
//@ add-core-stubs
5+
//@ revisions: unset set
6+
//@ needs-llvm-components: x86
7+
//@ compile-flags: --target x86_64-unknown-linux-gnu
8+
//@ [set] compile-flags: -Zindirect-branch-cs-prefix
9+
10+
#![crate_type = "lib"]
11+
#![feature(no_core, lang_items)]
12+
#![no_core]
13+
14+
extern crate minicore;
15+
use minicore::*;
16+
17+
// unset-NOT: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
18+
// set: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64
2+
3+
error: aborting due to 1 previous error
4+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ revisions: x86 x86_64 aarch64
2+
3+
//@ compile-flags: -Zindirect-branch-cs-prefix
4+
5+
//@[x86] check-pass
6+
//@[x86] needs-llvm-components: x86
7+
//@[x86] compile-flags: --target i686-unknown-linux-gnu
8+
9+
//@[x86_64] check-pass
10+
//@[x86_64] needs-llvm-components: x86
11+
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
12+
13+
//@[aarch64] check-fail
14+
//@[aarch64] needs-llvm-components: aarch64
15+
//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
16+
17+
#![feature(no_core)]
18+
#![no_core]
19+
#![no_main]
20+
21+
//[aarch64]~? ERROR `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64

0 commit comments

Comments
 (0)