From be1cdad72ce313c19c8a67e6d7f3444852ccef84 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 20 Oct 2024 07:49:24 -0700 Subject: [PATCH 1/3] Make the unwinding dependency conditional on `panic = "unwind"`. Similar to sunfishcode/origin#149, make the unwinding dependency conditional on `panic = "unwind"`. --- c-scape/Cargo.toml | 2 +- c-scape/src/unwind.rs | 104 ------------------ .../c-scape-example-panic-abort/.gitignore | 2 + .../c-scape-example-panic-abort/Cargo.toml | 34 ++++++ .../c-scape-example-panic-abort/README.md | 3 + .../c-scape-example-panic-abort/build.rs | 4 + .../c-scape-example-panic-abort/src/main.rs | 22 ++++ tests/example_crates.rs | 12 ++ 8 files changed, 78 insertions(+), 105 deletions(-) delete mode 100644 c-scape/src/unwind.rs create mode 100644 example-crates/c-scape-example-panic-abort/.gitignore create mode 100644 example-crates/c-scape-example-panic-abort/Cargo.toml create mode 100644 example-crates/c-scape-example-panic-abort/README.md create mode 100644 example-crates/c-scape-example-panic-abort/build.rs create mode 100644 example-crates/c-scape-example-panic-abort/src/main.rs diff --git a/c-scape/Cargo.toml b/c-scape/Cargo.toml index 3234015..35d8b7b 100644 --- a/c-scape/Cargo.toml +++ b/c-scape/Cargo.toml @@ -46,7 +46,7 @@ alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-all # TODO: Eventually, we should propose a `fde-phdr-rustix` backend option to # upstream `unwinding` so that it doesn't need to go through `dl_iterate_phdr`, # but `fde-phdr-dl` works for now. -[target.'cfg(not(target_arch = "arm"))'.dependencies.unwinding] +[target.'cfg(all(panic = "unwind", not(target_arch = "arm")))'.dependencies.unwinding] version = "0.2.3" default-features = false features = [ diff --git a/c-scape/src/unwind.rs b/c-scape/src/unwind.rs deleted file mode 100644 index a0baf23..0000000 --- a/c-scape/src/unwind.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! Stub libunwind implementation on platforms where we don't have real -//! unwind support. -//! -//! Entirely `unimplemented!`. Don't panic. - -#[no_mangle] -unsafe extern "C" fn _Unwind_Backtrace() { - unimplemented!("_Unwind_Backtrace") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_DeleteException() { - unimplemented!("_Unwind_DeleteException") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_GetDataRelBase() { - unimplemented!("_Unwind_GetDataRelBase") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_GetIP() { - unimplemented!("_Unwind_GetIP") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_GetIPInfo() { - unimplemented!("_Unwind_GetIPInfo") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_GetLanguageSpecificData() { - unimplemented!("_Unwind_GetLanguageSpecificData") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_GetRegionStart() { - unimplemented!("_Unwind_GetRegionStart") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_GetTextRelBase() { - unimplemented!("_Unwind_GetTextRelBase") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_RaiseException() { - unimplemented!("_Unwind_RaiseException") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_Resume() { - unimplemented!("_Unwind_Resume") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_SetGR() { - unimplemented!("_Unwind_SetGR") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_SetIP() { - unimplemented!("_Unwind_SetIP") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_FindEnclosingFunction() { - unimplemented!("_Unwind_FindEnclosingFunction") -} - -#[no_mangle] -unsafe extern "C" fn _Unwind_GetCFA() { - unimplemented!("_Unwind_GetCFA") -} - -#[cfg(target_arch = "arm")] -#[no_mangle] -unsafe extern "C" fn _Unwind_VRS_Get() { - unimplemented!("_Unwind_VRS_Get") -} - -#[cfg(target_arch = "arm")] -#[no_mangle] -unsafe extern "C" fn _Unwind_VRS_Set() { - unimplemented!("_Unwind_VRS_Set") -} - -#[cfg(target_arch = "arm")] -#[no_mangle] -unsafe extern "C" fn __aeabi_unwind_cpp_pr0() { - unimplemented!("__aeabi_unwind_cpp_pr0") -} - -#[cfg(target_arch = "arm")] -#[no_mangle] -unsafe extern "C" fn __aeabi_unwind_cpp_pr1() { - unimplemented!("__aeabi_unwind_cpp_pr1") -} - -#[cfg(target_arch = "arm")] -#[no_mangle] -unsafe extern "C" fn __gnu_unwind_frame() { - unimplemented!("__gnu_unwind_frame") -} diff --git a/example-crates/c-scape-example-panic-abort/.gitignore b/example-crates/c-scape-example-panic-abort/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/example-crates/c-scape-example-panic-abort/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/example-crates/c-scape-example-panic-abort/Cargo.toml b/example-crates/c-scape-example-panic-abort/Cargo.toml new file mode 100644 index 0000000..903618a --- /dev/null +++ b/example-crates/c-scape-example-panic-abort/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "c-scape-example" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies.libc] +path = "../../c-scape" +# Disable the default features, and enable "take-charge" mode. +default-features = false +features = [ + "take-charge", + "thread", + "call-main", + "malloc-via-rust-global-alloc", + "threadsafe-setenv", + # This simple example will never unwind. + "eh-personality-continue", + # This simple example will never panic. + "panic-handler-trap", + "global-allocator", +] +package = "c-scape" + +[dependencies] +errno = { version = "0.3.3", default-features = false } + +[profile.dev] +panic = "abort" +[profile.release] +panic = "abort" + +# This is just an example crate, and not part of the c-ward workspace. +[workspace] diff --git a/example-crates/c-scape-example-panic-abort/README.md b/example-crates/c-scape-example-panic-abort/README.md new file mode 100644 index 0000000..2cf6798 --- /dev/null +++ b/example-crates/c-scape-example-panic-abort/README.md @@ -0,0 +1,3 @@ +Like the [c-scape-example example], but uses panic=abort in Cargo.toml. + +[c-scape-example example]: https://github.com/sunfishcode/c-ward/blob/main/example-crates/c-scape-example/README.md diff --git a/example-crates/c-scape-example-panic-abort/build.rs b/example-crates/c-scape-example-panic-abort/build.rs new file mode 100644 index 0000000..ccccd22 --- /dev/null +++ b/example-crates/c-scape-example-panic-abort/build.rs @@ -0,0 +1,4 @@ +fn main() { + // Pass -nostartfiles to the linker. + println!("cargo:rustc-link-arg=-nostartfiles"); +} diff --git a/example-crates/c-scape-example-panic-abort/src/main.rs b/example-crates/c-scape-example-panic-abort/src/main.rs new file mode 100644 index 0000000..8ae9aae --- /dev/null +++ b/example-crates/c-scape-example-panic-abort/src/main.rs @@ -0,0 +1,22 @@ +//! A simple example using `no_main`, `no_std`, and "take-charge" mode. + +#![no_std] +#![no_main] + +#[no_mangle] +unsafe extern "C" fn main(_argc: i32, _argv: *const *const u8, _envp: *const *const u8) -> i32 { + // Call functions declared in the `libc` crate, which will be resolved by + // c-scape. c-scape doesn't have `printf`, so we do it by hand. + let message = b"Hello, world!\n"; + let mut remaining = &message[..]; + while !remaining.is_empty() { + match libc::write(libc::STDOUT_FILENO, message.as_ptr().cast(), message.len()) { + -1 => match errno::errno().0 { + libc::EINTR => continue, + _ => panic!(), + }, + n => remaining = &remaining[n as usize..], + } + } + libc::exit(0); +} diff --git a/tests/example_crates.rs b/tests/example_crates.rs index 40d92f8..84f6f24 100644 --- a/tests/example_crates.rs +++ b/tests/example_crates.rs @@ -102,6 +102,18 @@ fn example_crate_c_scape_example() { test_crate("c-scape-example", &[], &[], "Hello, world!\n", "", None); } +#[test] +fn example_crate_c_scape_example_panic_abort() { + test_crate( + "c-scape-example-panic-abort", + &[], + &[], + "Hello, world!\n", + "", + None, + ); +} + #[test] fn example_crate_c_scape_unwinding() { test_crate( From cb6562cbbf6b66ac8da8bf1962cd56fb731a87e7 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 20 Oct 2024 08:31:39 -0700 Subject: [PATCH 2/3] Add an example using c-gull and std::unwind::catch_unwind. --- example-crates/c-gull-unwinding/.gitignore | 2 ++ example-crates/c-gull-unwinding/Cargo.toml | 21 +++++++++++++++++++++ example-crates/c-gull-unwinding/README.md | 6 ++++++ example-crates/c-gull-unwinding/build.rs | 4 ++++ example-crates/c-gull-unwinding/src/main.rs | 19 +++++++++++++++++++ example-crates/c-scape-unwinding/README.md | 2 +- tests/example_crates.rs | 12 ++++++++++++ 7 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 example-crates/c-gull-unwinding/.gitignore create mode 100644 example-crates/c-gull-unwinding/Cargo.toml create mode 100644 example-crates/c-gull-unwinding/README.md create mode 100644 example-crates/c-gull-unwinding/build.rs create mode 100644 example-crates/c-gull-unwinding/src/main.rs diff --git a/example-crates/c-gull-unwinding/.gitignore b/example-crates/c-gull-unwinding/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/example-crates/c-gull-unwinding/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/example-crates/c-gull-unwinding/Cargo.toml b/example-crates/c-gull-unwinding/Cargo.toml new file mode 100644 index 0000000..ed25fdb --- /dev/null +++ b/example-crates/c-gull-unwinding/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "c-gull-unwinding" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies.libc] +path = "../../c-gull" +default-features = false +features = [ + "take-charge", + "std", + "thread", + "call-main", + "malloc-via-crates", + "threadsafe-setenv" +] +package = "c-gull" + +# This is just an example crate, and not part of the c-ward workspace. +[workspace] diff --git a/example-crates/c-gull-unwinding/README.md b/example-crates/c-gull-unwinding/README.md new file mode 100644 index 0000000..fe54f8e --- /dev/null +++ b/example-crates/c-gull-unwinding/README.md @@ -0,0 +1,6 @@ +This crate demonstrates the use of c-gull in "take-charge" mode, and includes +unwinding panic support. + +It's the same as [c-gull-example], but it performs an unwind. + +[c-gull-example]: https://github.com/sunfishcode/c-ward/tree/main/example-crates/c-gull-example#readme diff --git a/example-crates/c-gull-unwinding/build.rs b/example-crates/c-gull-unwinding/build.rs new file mode 100644 index 0000000..ccccd22 --- /dev/null +++ b/example-crates/c-gull-unwinding/build.rs @@ -0,0 +1,4 @@ +fn main() { + // Pass -nostartfiles to the linker. + println!("cargo:rustc-link-arg=-nostartfiles"); +} diff --git a/example-crates/c-gull-unwinding/src/main.rs b/example-crates/c-gull-unwinding/src/main.rs new file mode 100644 index 0000000..8e5c6b6 --- /dev/null +++ b/example-crates/c-gull-unwinding/src/main.rs @@ -0,0 +1,19 @@ +//! A simple example using `std::panic::catch_unwind`. + +fn main() { + // Panic and catch it. + std::panic::catch_unwind(|| call_do_panic()).unwrap_err(); + + println!("Hello, world!"); + unsafe { + libc::printf("Hello world using libc `printf`!\n\0".as_ptr().cast()); + } +} + +fn call_do_panic() { + do_panic() +} + +fn do_panic() { + panic!("catch me!"); +} diff --git a/example-crates/c-scape-unwinding/README.md b/example-crates/c-scape-unwinding/README.md index da75eff..9dd2d5f 100644 --- a/example-crates/c-scape-unwinding/README.md +++ b/example-crates/c-scape-unwinding/README.md @@ -3,6 +3,6 @@ and `no_std`, and includes unwinding panic support. It's the same as [c-scape-example], but enables the "eh-personality" and "panic-handler" features instead of defining stub `#[panic_handler]` and -`#[lang = "eh_personality"]` functions, and performs an unwind. +`#[lang = "eh_personality"]` functions, and it performs an unwind. [c-scape-example]: https://github.com/sunfishcode/c-ward/tree/main/example-crates/c-scape-example#readme diff --git a/tests/example_crates.rs b/tests/example_crates.rs index 84f6f24..80ee010 100644 --- a/tests/example_crates.rs +++ b/tests/example_crates.rs @@ -126,6 +126,18 @@ fn example_crate_c_scape_unwinding() { ); } +#[test] +fn example_crate_c_gull_unwinding() { + test_crate( + "c-gull-unwinding", + &[], + &[("RUST_BACKTRACE", "0")], + "Hello, world!\nHello world using libc `printf`!\n", + "thread 'main' panicked at src/main.rs:18:5:\ncatch me!\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n", + None, + ); +} + #[test] fn example_crate_dns() { test_crate( From 4a3669f13a51e06cf75097938c732d4b9433a563 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 20 Oct 2024 08:50:00 -0700 Subject: [PATCH 3/3] Add an example using c-gull and `panic = "abort"`. --- .../c-gull-example-panic-abort/.gitignore | 2 ++ .../c-gull-example-panic-abort/Cargo.toml | 26 +++++++++++++++++++ .../c-gull-example-panic-abort/README.md | 3 +++ .../c-gull-example-panic-abort/build.rs | 4 +++ .../c-gull-example-panic-abort/src/main.rs | 8 ++++++ tests/example_crates.rs | 12 +++++++++ 6 files changed, 55 insertions(+) create mode 100644 example-crates/c-gull-example-panic-abort/.gitignore create mode 100644 example-crates/c-gull-example-panic-abort/Cargo.toml create mode 100644 example-crates/c-gull-example-panic-abort/README.md create mode 100644 example-crates/c-gull-example-panic-abort/build.rs create mode 100644 example-crates/c-gull-example-panic-abort/src/main.rs diff --git a/example-crates/c-gull-example-panic-abort/.gitignore b/example-crates/c-gull-example-panic-abort/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/example-crates/c-gull-example-panic-abort/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/example-crates/c-gull-example-panic-abort/Cargo.toml b/example-crates/c-gull-example-panic-abort/Cargo.toml new file mode 100644 index 0000000..005746a --- /dev/null +++ b/example-crates/c-gull-example-panic-abort/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "c-gull-example-panic-abort" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies.libc] +path = "../../c-gull" +default-features = false +features = [ + "take-charge", + "std", + "thread", + "call-main", + "malloc-via-crates", + "threadsafe-setenv" +] +package = "c-gull" + +[profile.dev] +panic = "abort" +[profile.release] +panic = "abort" + +# This is just an example crate, and not part of the c-ward workspace. +[workspace] diff --git a/example-crates/c-gull-example-panic-abort/README.md b/example-crates/c-gull-example-panic-abort/README.md new file mode 100644 index 0000000..ca16608 --- /dev/null +++ b/example-crates/c-gull-example-panic-abort/README.md @@ -0,0 +1,3 @@ +Like the [c-gull-example example], but uses panic=abort in Cargo.toml. + +[c-gull-example example]: https://github.com/sunfishcode/c-ward/blob/main/example-crates/c-gull-example/README.md diff --git a/example-crates/c-gull-example-panic-abort/build.rs b/example-crates/c-gull-example-panic-abort/build.rs new file mode 100644 index 0000000..ccccd22 --- /dev/null +++ b/example-crates/c-gull-example-panic-abort/build.rs @@ -0,0 +1,4 @@ +fn main() { + // Pass -nostartfiles to the linker. + println!("cargo:rustc-link-arg=-nostartfiles"); +} diff --git a/example-crates/c-gull-example-panic-abort/src/main.rs b/example-crates/c-gull-example-panic-abort/src/main.rs new file mode 100644 index 0000000..0cc190a --- /dev/null +++ b/example-crates/c-gull-example-panic-abort/src/main.rs @@ -0,0 +1,8 @@ +//! A simple example using "take-charge" mode. + +fn main() { + println!("Hello world using Rust `println!`!"); + unsafe { + libc::printf("Hello world using libc `printf`!\n\0".as_ptr().cast()); + } +} diff --git a/tests/example_crates.rs b/tests/example_crates.rs index 80ee010..f0756af 100644 --- a/tests/example_crates.rs +++ b/tests/example_crates.rs @@ -73,6 +73,18 @@ fn example_crate_c_gull_example() { ); } +#[test] +fn example_crate_c_gull_example_panic_abort() { + test_crate( + "c-gull-example-panic-abort", + &[], + &[], + "Hello world using Rust `println!`!\nHello world using libc `printf`!\n", + "", + None, + ); +} + #[test] fn example_crate_c_gull_lto() { test_crate(