diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index 019d5629d6d6e..f391f70594c8c 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -37,9 +37,12 @@ //! and the last personality routine transfers control to the catch block. #![forbid(unsafe_op_in_unsafe_fn)] +mod dwarf; +mod eh; + use unwind as uw; -use super::dwarf::eh::{self, EHAction, EHContext}; +use self::eh::{EHAction, EHContext}; use crate::ffi::c_int; // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister() @@ -332,8 +335,7 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result { - pub ip: *const u8, // Current instruction pointer - pub func_start: *const u8, // Pointer to the current function - pub get_text_start: &'a dyn Fn() -> *const u8, // Get pointer to the code section - pub get_data_start: &'a dyn Fn() -> *const u8, // Get pointer to the data section +pub struct EHContext { + pub(crate) ip: *const u8, // Current instruction pointer + pub(crate) func_start: *const u8, // Pointer to the current function + pub(crate) raw_context: *mut uw::_Unwind_Context, } /// Landing pad. @@ -63,7 +64,7 @@ pub enum EHAction { pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm")); -pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result { +pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> Result { if lsda.is_null() { return Ok(EHAction::None); } @@ -224,7 +225,7 @@ unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result< /// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html unsafe fn read_encoded_pointer( reader: &mut DwarfReader, - context: &EHContext<'_>, + context: &EHContext, encoding: u8, ) -> Result<*const u8, ()> { if encoding == DW_EH_PE_omit { @@ -241,8 +242,8 @@ unsafe fn read_encoded_pointer( } context.func_start } - DW_EH_PE_textrel => (*context.get_text_start)(), - DW_EH_PE_datarel => (*context.get_data_start)(), + DW_EH_PE_textrel => unsafe { uw::_Unwind_GetTextRelBase(context.raw_context) }, + DW_EH_PE_datarel => unsafe { uw::_Unwind_GetDataRelBase(context.raw_context) }, // aligned means the value is aligned to the size of a pointer DW_EH_PE_aligned => { reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), size_of::<*const u8>())?); diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs index eabef92244d01..c883ee86ea1c3 100644 --- a/library/std/src/sys/personality/mod.rs +++ b/library/std/src/sys/personality/mod.rs @@ -10,8 +10,6 @@ //! Additionally, ARM EHABI uses the personality function when generating //! backtraces. -mod dwarf; - #[cfg(not(any(test, doctest)))] cfg_select! { target_os = "emscripten" => { diff --git a/tests/run-make-cargo/panic-free-cdylib/Cargo.toml b/tests/run-make-cargo/panic-free-cdylib/Cargo.toml new file mode 100644 index 0000000000000..b65f570a315a9 --- /dev/null +++ b/tests/run-make-cargo/panic-free-cdylib/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "add" +version = "0.1.0" +edition = "2024" + +[lib] +path = "lib.rs" +crate-type = ["cdylib"] + +[profile.release] +lto = "fat" diff --git a/tests/run-make-cargo/panic-free-cdylib/lib.rs b/tests/run-make-cargo/panic-free-cdylib/lib.rs new file mode 100644 index 0000000000000..94bcf336d71af --- /dev/null +++ b/tests/run-make-cargo/panic-free-cdylib/lib.rs @@ -0,0 +1,5 @@ +#![crate_type = "cdylib"] + +pub extern "C" fn add(a: u64, b: u64) -> u64 { + a + b +} diff --git a/tests/run-make-cargo/panic-free-cdylib/rmake.rs b/tests/run-make-cargo/panic-free-cdylib/rmake.rs new file mode 100644 index 0000000000000..f8aa18fea4497 --- /dev/null +++ b/tests/run-make-cargo/panic-free-cdylib/rmake.rs @@ -0,0 +1,43 @@ +// This ensures that a cdylib that uses std and panic=unwind but does not +// have any panics itself will not have *any* panic-related code in the final +// binary, at least when using fat LTO +// (since all the necessary nounwind propagation requires fat LTO). +// +// This code used to be pulled in via a landing pad in the personality function, +// (since that is `extern "C"` and therefore panics if something unwinds), so +// if this failed because you modified the personality function, ensure it contains +// no potentially unwinding calls. + +use run_make_support::{cargo, dynamic_lib_name, llvm_nm, path, rustc, target}; + +fn main() { + let target_dir = path("target"); + + // We use build-std to ensure that the sysroot does not have debug assertions, + // as this doesn't work with debug assertions. + cargo() + .args(&[ + "build", + "--manifest-path", + "Cargo.toml", + "--release", + "-Zbuild-std=std", + "--target", + &target(), + ]) + .env("CARGO_TARGET_DIR", &target_dir) + .env("RUSTC_BOOTSTRAP", "1") + .run(); + + let output_path = target_dir.join(target()).join("release").join(dynamic_lib_name("add")); + + llvm_nm() + .input(output_path) + .run() + // a collection of panic-related strings. if this appears in the output + // for other reasons than having panic symbols, I am sorry. + .assert_stdout_not_contains("panic") + .assert_stdout_not_contains("addr2line") + .assert_stdout_not_contains("backtrace") + .assert_stdout_not_contains("gimli"); +}