Rust for Linux List
 help / color / mirror / Atom feed
* [PATCH v5] rust: compiler_builtins: Fix silent trap in prohibited intrinsics
@ 2026-11-04 23:10 FUJITA Tomonori
  0 siblings, 0 replies; only message in thread
From: FUJITA Tomonori @ 2026-11-04 23:10 UTC (permalink / raw)
  To: ojeda
  Cc: a.hindborg, acourbot, aliceryhl, bjorn3_gh, boqun, dakr,
	daniel.almeida, gary, jpoimboe, lossin, tamird, tmgross, work,
	rust-for-linux, FUJITA Tomonori

From: FUJITA Tomonori <fujita.tomonori@gmail.com>

When core calls one of the stubs for builtins that should not be used,
the stub runs a trap instruction that prints no message, and the Oops
shows a wrong name. For example, when __rust__udivti3() is called on
x86_64, the Oops shows:

  Oops: invalid opcode: 0000 [#1] SMP
  RIP: 0010:__rust__adddf3+0x0/0x10

The stubs call panic!(), but since Rust 1.79, rustc converts calls to
panic!() in a `#![compiler_builtins]` crate into
core::intrinsics::abort(), i.e. a trap that prints no message [1][2].
In addition, all the stubs have the same code, so LLVM merges them into
one function.

Move the stubs to a new small crate, core_builtins, where panic!() works
as usual. Add the name of each stub to the panic message, so the stubs
are no longer merged:

  rust_kernel: panicked at rust/core_builtins.rs:64:1:
  __udivti3 called: `u128` should not be used
  kernel BUG at rust/helpers/bug.c:7!

Weaken the stubs in core_builtins.o, as was done in compiler_builtins.o.
Otherwise objtool treats them as noreturn functions and warns.

compiler_builtins.rs is now empty, but the crate is still needed because
rustc requires a `#![compiler_builtins]` crate. Remove the weakening of
compiler_builtins.o, as it has no symbols now.

Link: https://github.com/rust-lang/rust/pull/122580 [1]
Link: https://github.com/rust-lang/rust/issues/165399 [2]
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
v5:
- Move the stubs to a new crate, core_builtins, instead of the kernel
  crate (Miguel)
- Remove the weakening of compiler_builtins.o (Miguel)
- Explain why the stubs are weakened in core_builtins.rs (Miguel)
- Reword why the stubs are not in compiler_builtins and add links (Miguel)
v4: https://lore.kernel.org/rust-for-linux/20261009224626.1331914-1-tomo@flapping.org/
- Weaken the stubs in kernel.o to fix an objtool warning
  https://lore.kernel.org/oe-kbuild-all/202610100054.UyoZyPQ5-lkp@intel.com/
v3: https://lore.kernel.org/rust-for-linux/20261008114717.992497-1-tomo@flapping.org/
- Rename rust/kernel/intrinsics.rs to rust/kernel/core_builtins.rs (Gary)
- Reword the doc of compiler_builtins.rs (Gary)
v2: https://lore.kernel.org/rust-for-linux/20261003124828.119912-1-tomo@flapping.org/
- Move the stubs to the kernel crate and use panic!() there (Gary)
v1: https://lore.kernel.org/rust-for-linux/20261002014739.2566289-1-tomo@flapping.org/
---
 rust/Makefile                                 |  8 +-
 rust/compiler_builtins.rs                     | 98 +------------------
 ...{compiler_builtins.rs => core_builtins.rs} | 28 +++---
 3 files changed, 23 insertions(+), 111 deletions(-)
 copy rust/{compiler_builtins.rs => core_builtins.rs} (73%)

diff --git a/rust/Makefile b/rust/Makefile
index 0ac9ab28cc2b..8eec45636062 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -6,7 +6,7 @@ rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc
 # Clean generated host directory
 clean-files := host/
 
-obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o
+obj-$(CONFIG_RUST) += core.o compiler_builtins.o core_builtins.o ffi.o
 always-$(CONFIG_RUST) += exports_core_generated.h
 
 obj-$(CONFIG_RUST) += zerocopy.o
@@ -745,10 +745,14 @@ endif
 KCOV_INSTRUMENT_core.o := n
 
 $(obj)/compiler_builtins.o: private skip_gendwarfksyms = 1
-$(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*'
 $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE
 	+$(call if_changed_rule,rustc_library)
 
+$(obj)/core_builtins.o: private skip_gendwarfksyms = 1
+$(obj)/core_builtins.o: private rustc_objcopy = -w -W '__rust__*'
+$(obj)/core_builtins.o: $(src)/core_builtins.rs $(obj)/compiler_builtins.o FORCE
+	+$(call if_changed_rule,rustc_library)
+
 $(obj)/zerocopy.o: private skip_clippy = 1
 $(obj)/zerocopy.o: private skip_gendwarfksyms = 1
 $(obj)/zerocopy.o: private rustc_target_envs := $(zerocopy-envs)
diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs
index fc6b54636dd5..467020fac09e 100644
--- a/rust/compiler_builtins.rs
+++ b/rust/compiler_builtins.rs
@@ -3,18 +3,11 @@
 //! Our own `compiler_builtins`.
 //!
 //! Rust provides [`compiler_builtins`] as a port of LLVM's [`compiler-rt`].
-//! Since we do not need the vast majority of them, we avoid the dependency
-//! by providing this file.
-//!
-//! At the moment, some builtins are required that should not be. For instance,
-//! [`core`] has 128-bit integers functionality which we should not be compiling
-//! in. We will work with upstream [`core`] to provide feature flags to disable
-//! the parts we do not need. For the moment, we define them to [`panic!`] at
-//! runtime for simplicity to catch mistakes, instead of performing surgery
-//! on `core.o`.
-//!
-//! In any case, all these symbols are weakened to ensure we do not override
-//! those that may be provided by the rest of the kernel.
+//! Since we do not need the vast majority of them, we avoid the dependency.
+//! But `rustc` still needs a `#![compiler_builtins]` crate for every crate it
+//! builds, so this crate is provided and left empty. The few builtins that
+//! `core` needs are in the `core_builtins` crate (`rust/core_builtins.rs`).
+//! Please see the details there.
 //!
 //! [`compiler_builtins`]: https://github.com/rust-lang/compiler-builtins
 //! [`compiler-rt`]: https://compiler-rt.llvm.org/
@@ -24,84 +17,3 @@
 #![compiler_builtins]
 #![no_builtins]
 #![no_std]
-
-macro_rules! define_panicking_intrinsics(
-    ($reason: tt, { $($ident: ident, )* }) => {
-        $(
-            #[doc(hidden)]
-            #[export_name = concat!("__rust", stringify!($ident))]
-            pub extern "C" fn $ident() {
-                panic!($reason);
-            }
-        )*
-    }
-);
-
-define_panicking_intrinsics!("`f32` should not be used", {
-    __addsf3,
-    __eqsf2,
-    __extendsfdf2,
-    __gesf2,
-    __lesf2,
-    __ltsf2,
-    __mulsf3,
-    __nesf2,
-    __truncdfsf2,
-    __unordsf2,
-});
-
-define_panicking_intrinsics!("`f64` should not be used", {
-    __adddf3,
-    __eqdf2,
-    __ledf2,
-    __ltdf2,
-    __muldf3,
-    __unorddf2,
-});
-
-define_panicking_intrinsics!("`i128` should not be used", {
-    __ashrti3,
-    __muloti4,
-    __multi3,
-});
-
-define_panicking_intrinsics!("`u128` should not be used", {
-    __ashlti3,
-    __lshrti3,
-    __udivmodti4,
-    __udivti3,
-    __umodti3,
-});
-
-#[cfg(target_arch = "arm")]
-define_panicking_intrinsics!("`f32` should not be used", {
-    __aeabi_fadd,
-    __aeabi_fmul,
-    __aeabi_fcmpeq,
-    __aeabi_fcmple,
-    __aeabi_fcmplt,
-    __aeabi_fcmpun,
-});
-
-#[cfg(target_arch = "arm")]
-define_panicking_intrinsics!("`f64` should not be used", {
-    __aeabi_dadd,
-    __aeabi_dmul,
-    __aeabi_dcmple,
-    __aeabi_dcmplt,
-    __aeabi_dcmpun,
-});
-
-#[cfg(target_arch = "arm")]
-define_panicking_intrinsics!("`u64` division/modulo should not be used", {
-    __aeabi_uldivmod,
-});
-
-#[cfg(target_arch = "powerpc")]
-define_panicking_intrinsics!("`u64` division/modulo should not be used", {
-    __udivdi3,
-    __umoddi3,
-});
-
-// NOTE: if you are adding a new intrinsic here, you should also add it to
-// `redirect-intrinsics` in `rust/Makefile`.
diff --git a/rust/compiler_builtins.rs b/rust/core_builtins.rs
similarity index 73%
copy from rust/compiler_builtins.rs
copy to rust/core_builtins.rs
index fc6b54636dd5..4ca92e69a7f3 100644
--- a/rust/compiler_builtins.rs
+++ b/rust/core_builtins.rs
@@ -1,10 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 
-//! Our own `compiler_builtins`.
-//!
-//! Rust provides [`compiler_builtins`] as a port of LLVM's [`compiler-rt`].
-//! Since we do not need the vast majority of them, we avoid the dependency
-//! by providing this file.
+//! Builtins that `core` needs.
 //!
 //! At the moment, some builtins are required that should not be. For instance,
 //! [`core`] has 128-bit integers functionality which we should not be compiling
@@ -13,25 +9,25 @@
 //! runtime for simplicity to catch mistakes, instead of performing surgery
 //! on `core.o`.
 //!
-//! In any case, all these symbols are weakened to ensure we do not override
-//! those that may be provided by the rest of the kernel.
+//! The stubs are here and not in `compiler_builtins`, because the compiler
+//! would otherwise decide to convert calls to [`panic!`] into
+//! `core::intrinsics::abort`, i.e. a trap that would print no message -- please
+//! see https://github.com/rust-lang/rust/pull/122580 and
+//! https://github.com/rust-lang/rust/issues/165399.
 //!
-//! [`compiler_builtins`]: https://github.com/rust-lang/compiler-builtins
-//! [`compiler-rt`]: https://compiler-rt.llvm.org/
+//! The stubs are weakened in `rust/Makefile`. Otherwise, when `objtool` checks
+//! `vmlinux.o` (e.g. with `CONFIG_X86_KERNEL_IBT`), it finds that the stubs do
+//! not return and warns that they are not marked as noreturn. `objtool` does
+//! not do this check for weak functions.
 
-#![allow(internal_features)]
-#![feature(compiler_builtins)]
-#![compiler_builtins]
-#![no_builtins]
 #![no_std]
 
 macro_rules! define_panicking_intrinsics(
     ($reason: tt, { $($ident: ident, )* }) => {
         $(
-            #[doc(hidden)]
             #[export_name = concat!("__rust", stringify!($ident))]
-            pub extern "C" fn $ident() {
-                panic!($reason);
+            extern "C" fn $ident() {
+                panic!(concat!(stringify!($ident), " called: ", $reason));
             }
         )*
     }

base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
-- 
2.43.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-04 23:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04 23:10 [PATCH v5] rust: compiler_builtins: Fix silent trap in prohibited intrinsics FUJITA Tomonori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox