From 36a669570af2d0e08199249a6195d655ba2275f5 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Thu, 28 Aug 2025 14:44:34 -0500 Subject: [PATCH 1/3] Rename -Zno-jump-tables to -Zjump-tables= Both gcc and llvm accept -fjump-tables as well as -fno-jump-tables. For consistency, allow rustc to accept -Zjump-tables=yes too. --- compiler/rustc_codegen_llvm/src/attributes.rs | 2 +- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/options.rs | 4 ++-- .../src/compiler-flags/jump-tables.md | 19 +++++++++++++++++++ .../src/compiler-flags/no-jump-tables.md | 19 ------------------- tests/assembly-llvm/x86_64-no-jump-tables.rs | 4 ++-- tests/codegen-llvm/no-jump-tables.rs | 10 ++++++---- 7 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/jump-tables.md delete mode 100644 src/doc/unstable-book/src/compiler-flags/no-jump-tables.md diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 8070ea0b3e927..f37468b745802 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -228,7 +228,7 @@ fn instrument_function_attr<'ll>( } fn nojumptables_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll Attribute> { - if !sess.opts.unstable_opts.no_jump_tables { + if sess.opts.unstable_opts.jump_tables { return None; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 7e5186db4eafe..09610d4601035 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -815,6 +815,7 @@ fn test_unstable_options_tracking_hash() { tracked!(inline_mir_threshold, Some(123)); tracked!(instrument_mcount, true); tracked!(instrument_xray, Some(InstrumentXRay::default())); + tracked!(jump_tables, false); tracked!(link_directives, false); tracked!(link_only, true); tracked!(lint_llvm_ir, true); @@ -832,7 +833,6 @@ fn test_unstable_options_tracking_hash() { tracked!(mutable_noalias, false); tracked!(next_solver, NextSolverConfig { coherence: true, globally: true }); tracked!(no_generate_arange_section, true); - tracked!(no_jump_tables, true); tracked!(no_link, true); tracked!(no_profiler_runtime, true); tracked!(no_trait_vptr, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6dd90546de1b0..93c6405d950e7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2395,6 +2395,8 @@ options! { `=skip-entry` `=skip-exit` Multiple options can be combined with commas."), + jump_tables: bool = (true, parse_bool, [TRACKED], + "allow jump table and lookup table generation from switch case lowering (default: yes)"), layout_seed: Option = (None, parse_opt_number, [TRACKED], "seed layout randomization"), link_directives: bool = (true, parse_bool, [TRACKED], @@ -2475,8 +2477,6 @@ options! { "omit DWARF address ranges that give faster lookups"), no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED], "disable the compatibility version of the `implied_bounds_ty` query"), - no_jump_tables: bool = (false, parse_no_value, [TRACKED], - "disable the jump tables and lookup tables that can be generated from a switch case lowering"), no_leak_check: bool = (false, parse_no_value, [UNTRACKED], "disable the 'leak check' for subtyping; unsound, but useful for tests"), no_link: bool = (false, parse_no_value, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/jump-tables.md b/src/doc/unstable-book/src/compiler-flags/jump-tables.md new file mode 100644 index 0000000000000..3abf703cd361a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/jump-tables.md @@ -0,0 +1,19 @@ +# `jump-tables` + +The tracking issue for this feature is [#116592](https://github.com/rust-lang/rust/issues/116592) + +--- + +When set to no, this option enables the `-fno-jump-tables` flag for LLVM, which makes the +codegen backend avoid generating jump tables when lowering switches. + +When set to no, this option adds the LLVM `no-jump-tables=true` attribute to every function. + +Disabling jump tables can be used to help provide protection against +jump-oriented-programming (JOP) attacks, such as with the linux kernel's [IBT]. + +```sh +RUSTFLAGS="-Zjump-tables=no" cargo +nightly build -Z build-std +``` + +[IBT]: https://www.phoronix.com/news/Linux-IBT-By-Default-Tip diff --git a/src/doc/unstable-book/src/compiler-flags/no-jump-tables.md b/src/doc/unstable-book/src/compiler-flags/no-jump-tables.md deleted file mode 100644 index f096c20f4bd54..0000000000000 --- a/src/doc/unstable-book/src/compiler-flags/no-jump-tables.md +++ /dev/null @@ -1,19 +0,0 @@ -# `no-jump-tables` - -The tracking issue for this feature is [#116592](https://github.com/rust-lang/rust/issues/116592) - ---- - -This option enables the `-fno-jump-tables` flag for LLVM, which makes the -codegen backend avoid generating jump tables when lowering switches. - -This option adds the LLVM `no-jump-tables=true` attribute to every function. - -The option can be used to help provide protection against -jump-oriented-programming (JOP) attacks, such as with the linux kernel's [IBT]. - -```sh -RUSTFLAGS="-Zno-jump-tables" cargo +nightly build -Z build-std -``` - -[IBT]: https://www.phoronix.com/news/Linux-IBT-By-Default-Tip diff --git a/tests/assembly-llvm/x86_64-no-jump-tables.rs b/tests/assembly-llvm/x86_64-no-jump-tables.rs index bb10042d8f629..0108c8817e350 100644 --- a/tests/assembly-llvm/x86_64-no-jump-tables.rs +++ b/tests/assembly-llvm/x86_64-no-jump-tables.rs @@ -1,10 +1,10 @@ -// Test that jump tables are (not) emitted when the `-Zno-jump-tables` +// Test that jump tables are (not) emitted when the `-Zjump-tables=no` // flag is (not) set. //@ revisions: unset set //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 -//@ [set] compile-flags: -Zno-jump-tables +//@ [set] compile-flags: -Zjump-tables=no //@ only-x86_64 //@ ignore-sgx diff --git a/tests/codegen-llvm/no-jump-tables.rs b/tests/codegen-llvm/no-jump-tables.rs index e49de7e9dc1e9..3271a673e35b4 100644 --- a/tests/codegen-llvm/no-jump-tables.rs +++ b/tests/codegen-llvm/no-jump-tables.rs @@ -1,11 +1,12 @@ // Test that the `no-jump-tables` function attribute are (not) emitted when -// the `-Zno-jump-tables` flag is (not) set. +// the `-Zjump-tables=no` flag is (not) set. //@ add-core-stubs -//@ revisions: unset set +//@ revisions: unset set_no set_yes //@ needs-llvm-components: x86 //@ compile-flags: --target x86_64-unknown-linux-gnu -//@ [set] compile-flags: -Zno-jump-tables +//@ [set_no] compile-flags: -Zjump-tables=no +//@ [set_yes] compile-flags: -Zjump-tables=yes #![crate_type = "lib"] #![feature(no_core, lang_items)] @@ -19,5 +20,6 @@ pub fn foo() { // CHECK: @foo() unnamed_addr #0 // unset-NOT: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} } - // set: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} } + // set_yes-NOT: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} } + // set_no: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} } } From 7c76a867ab3098312616c74fd3b4ad99ed6155c8 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Thu, 28 Aug 2025 15:22:35 -0500 Subject: [PATCH 2/3] Stabilize -Zjump-tables= into -Cjump-table= --- compiler/rustc_codegen_llvm/src/attributes.rs | 2 +- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/options.rs | 4 ++-- src/doc/rustc/src/codegen-options/index.md | 13 +++++++++++++ .../src/compiler-flags/jump-tables.md | 19 ------------------- tests/assembly-llvm/x86_64-no-jump-tables.rs | 4 ++-- tests/codegen-llvm/no-jump-tables.rs | 6 +++--- 7 files changed, 22 insertions(+), 28 deletions(-) delete mode 100644 src/doc/unstable-book/src/compiler-flags/jump-tables.md diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index f37468b745802..ec8a51a0872bd 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -228,7 +228,7 @@ fn instrument_function_attr<'ll>( } fn nojumptables_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll Attribute> { - if sess.opts.unstable_opts.jump_tables { + if sess.opts.cg.jump_tables { return None; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 09610d4601035..4c790df77b40a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -621,6 +621,7 @@ fn test_codegen_options_tracking_hash() { tracked!(force_frame_pointers, FramePointer::Always); tracked!(force_unwind_tables, Some(true)); tracked!(instrument_coverage, InstrumentCoverage::Yes); + tracked!(jump_tables, false); tracked!(link_dead_code, Some(true)); tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto); tracked!(llvm_args, vec![String::from("1"), String::from("2")]); @@ -815,7 +816,6 @@ fn test_unstable_options_tracking_hash() { tracked!(inline_mir_threshold, Some(123)); tracked!(instrument_mcount, true); tracked!(instrument_xray, Some(InstrumentXRay::default())); - tracked!(jump_tables, false); tracked!(link_directives, false); tracked!(link_only, true); tracked!(lint_llvm_ir, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 93c6405d950e7..9010f1e91d0a9 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2093,6 +2093,8 @@ options! { "instrument the generated code to support LLVM source-based code coverage reports \ (note, the compiler build config must include `profiler = true`); \ implies `-C symbol-mangling-version=v0`"), + jump_tables: bool = (true, parse_bool, [TRACKED], + "allow jump table and lookup table generation from switch case lowering (default: yes)"), link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED], "a single extra argument to append to the linker invocation (can be used several times)"), link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], @@ -2395,8 +2397,6 @@ options! { `=skip-entry` `=skip-exit` Multiple options can be combined with commas."), - jump_tables: bool = (true, parse_bool, [TRACKED], - "allow jump table and lookup table generation from switch case lowering (default: yes)"), layout_seed: Option = (None, parse_opt_number, [TRACKED], "seed layout randomization"), link_directives: bool = (true, parse_bool, [TRACKED], diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 0e340de4daa27..c64a8727b085e 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -209,6 +209,19 @@ Note that while the `-C instrument-coverage` option is stable, the profile data format produced by the resulting instrumentation may change, and may not work with coverage tools other than those built and shipped with the compiler. +## jump-tables + +This option is used to allow or prevent the LLVM codegen backend from creating +jump tables when lowering switches. + +* `y`, `yes`, `on`, `true` or no value: allow jump tables (the default). +* `n`, `no`, `off` or `false`: disable jump tables. + +Disabling jump tables can be used to help provide protection against +jump-oriented-programming (JOP) attacks. However, this option makes +no guarantee any precompiled or external dependencies are compiled +with or without jump tables. + ## link-arg This flag lets you append a single extra argument to the linker invocation. diff --git a/src/doc/unstable-book/src/compiler-flags/jump-tables.md b/src/doc/unstable-book/src/compiler-flags/jump-tables.md deleted file mode 100644 index 3abf703cd361a..0000000000000 --- a/src/doc/unstable-book/src/compiler-flags/jump-tables.md +++ /dev/null @@ -1,19 +0,0 @@ -# `jump-tables` - -The tracking issue for this feature is [#116592](https://github.com/rust-lang/rust/issues/116592) - ---- - -When set to no, this option enables the `-fno-jump-tables` flag for LLVM, which makes the -codegen backend avoid generating jump tables when lowering switches. - -When set to no, this option adds the LLVM `no-jump-tables=true` attribute to every function. - -Disabling jump tables can be used to help provide protection against -jump-oriented-programming (JOP) attacks, such as with the linux kernel's [IBT]. - -```sh -RUSTFLAGS="-Zjump-tables=no" cargo +nightly build -Z build-std -``` - -[IBT]: https://www.phoronix.com/news/Linux-IBT-By-Default-Tip diff --git a/tests/assembly-llvm/x86_64-no-jump-tables.rs b/tests/assembly-llvm/x86_64-no-jump-tables.rs index 0108c8817e350..e469aee7ed945 100644 --- a/tests/assembly-llvm/x86_64-no-jump-tables.rs +++ b/tests/assembly-llvm/x86_64-no-jump-tables.rs @@ -1,10 +1,10 @@ -// Test that jump tables are (not) emitted when the `-Zjump-tables=no` +// Test that jump tables are (not) emitted when the `-Cjump-tables=no` // flag is (not) set. //@ revisions: unset set //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 -//@ [set] compile-flags: -Zjump-tables=no +//@ [set] compile-flags: -Cjump-tables=no //@ only-x86_64 //@ ignore-sgx diff --git a/tests/codegen-llvm/no-jump-tables.rs b/tests/codegen-llvm/no-jump-tables.rs index 3271a673e35b4..92f9c1f204a64 100644 --- a/tests/codegen-llvm/no-jump-tables.rs +++ b/tests/codegen-llvm/no-jump-tables.rs @@ -1,12 +1,12 @@ // Test that the `no-jump-tables` function attribute are (not) emitted when -// the `-Zjump-tables=no` flag is (not) set. +// the `-Cjump-tables=no` flag is (not) set. //@ add-core-stubs //@ revisions: unset set_no set_yes //@ needs-llvm-components: x86 //@ compile-flags: --target x86_64-unknown-linux-gnu -//@ [set_no] compile-flags: -Zjump-tables=no -//@ [set_yes] compile-flags: -Zjump-tables=yes +//@ [set_no] compile-flags: -Cjump-tables=no +//@ [set_yes] compile-flags: -Cjump-tables=yes #![crate_type = "lib"] #![feature(no_core, lang_items)] From 0a7de2f96a6e91878d877bdb975063452364c642 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Thu, 11 Sep 2025 11:56:27 -0500 Subject: [PATCH 3/3] Improve documentation of -Cjump-tables Be more verbose about what this option can and cannot do. --- src/doc/rustc/src/codegen-options/index.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index c64a8727b085e..cfb6ad038963a 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -212,15 +212,23 @@ with coverage tools other than those built and shipped with the compiler. ## jump-tables This option is used to allow or prevent the LLVM codegen backend from creating -jump tables when lowering switches. +jump tables when lowering switches from Rust code. * `y`, `yes`, `on`, `true` or no value: allow jump tables (the default). * `n`, `no`, `off` or `false`: disable jump tables. +To prevent jump tables being created from Rust code, a target must ensure +all crates are compiled with jump tables disabled. + +Note, in many cases the rust toolchain is distributed with precompiled +crates, such as the core and std crates, which could possibly include +jump tables. Furthermore, this option does not guarantee a target will +be free of jump tables. They could arise from external dependencies, +inline asm, or other complicated interactions when using crates which +are compiled with jump table support. + Disabling jump tables can be used to help provide protection against -jump-oriented-programming (JOP) attacks. However, this option makes -no guarantee any precompiled or external dependencies are compiled -with or without jump tables. +jump-oriented-programming (JOP) attacks. ## link-arg