* [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