rust-embedded / heapless

Heapless, `static` friendly data structures
Apache License 2.0
1.56k stars 185 forks source link

Debug build error: no_std + FnvIndexMap (linker err: `rust_eh_personality`) #510

Closed cjrh closed 2 months ago

cjrh commented 2 months ago

TL,DR, A debug build using FNVIndexMap fails linking with missing rust_eh_personality, but release build works.

Apologies if this is user error, I am new to no_std.

Environment

See details ``` $ rustc --version --verbose rustc 1.81.0 (eeb90cda1 2024-09-04) binary: rustc commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c commit-date: 2024-09-04 host: x86_64-unknown-linux-gnu release: 1.81.0 LLVM version: 18.1.7 $ cargo --version --verbose cargo 1.81.0 (2dbb1af80 2024-08-20) release: 1.81.0 commit-hash: 2dbb1af80a2914475ba76827a312e29cedfa6b2f commit-date: 2024-08-20 host: x86_64-unknown-linux-gnu libgit2: 1.8.1 (sys:0.19.0 vendored) libcurl: 8.8.0-DEV (sys:0.4.73+curl-8.8.0 vendored ssl:OpenSSL/1.1.1w) ssl: OpenSSL 1.1.1w 11 Sep 2023 os: Linux Mint 22.0.0 (wilma) [64-bit] $ rustup show Default host: x86_64-unknown-linux-gnu rustup home: /home/caleb/.rustup installed toolchains -------------------- stable-x86_64-unknown-linux-gnu (default) nightly-2024-06-08-x86_64-unknown-linux-gnu nightly-x86_64-unknown-linux-gnu 1.73.0-x86_64-unknown-linux-gnu 1.80.1-x86_64-unknown-linux-gnu 1.80-x86_64-unknown-linux-gnu installed targets for active toolchain -------------------------------------- x86_64-unknown-linux-gnu x86_64-unknown-linux-musl active toolchain ---------------- stable-x86_64-unknown-linux-gnu (default) rustc 1.81.0 (eeb90cda1 2024-09-04) $ uname -a Linux caleb-ThinkPad-X13-Gen-1 6.8.0-44-generic #44-Ubuntu SMP PREEMPT_DYNAMIC Tue Aug 13 13:35:26 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux ```

Reproducer

Here is a tiny project:

Cargo.toml:

[package]
name = "heapless_debug_err"
version = "0.1.0"
edition = "2021"

[dependencies]
heapless = "0.8.0"
libc = { version = "0.2.148", default-features = false }

[profile.dev]
panic = "abort"
debug-assertions = false

[profile.release]
panic = "abort"

[!NOTE]
default-features = false is required to disable linking to std

main.rs:

#![no_std]
#![no_main]

use core::panic::PanicInfo;
use libc;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
    let mut v = heapless::Vec::<i32, 16>::new();
    v.push(1).unwrap();

    let mut h = heapless::FnvIndexMap::<i32, i32, 16>::new();
    h.insert(1, 2).unwrap();
    0
}

Build in release mode is fine:

$ cargo build --release
warning: unused import: `libc`
 --> src/main.rs:5:5
  |
5 | use libc;
  |     ^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: `heapless_debug_err` (bin "heapless_debug_err") generated 1 warning (run `cargo fix --bin "heapless_debug_err"` to apply 1 suggestion)
    Finished `release` profile [optimized] target(s) in 0.00s

[!NOTE]
Removing the libc import from main.rs breaks it - it will complain about the entrypoint not being found.

Build in debug mode fails. This is the linker error:

  = note: /bin/ld: /home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-500f37ee5bcf0ffe.rlib(core-500f37ee5bcf0ffe.core.3cad2706d8bdcdc4-cgu.0.rcgu.o):(.data.DW.ref.rust_eh_personality[DW.ref.rust_eh_personality]+0x0): undefined reference to `rust_eh_personality'
          collect2: error: ld returned 1 exit status
See the full details from cargo build ``` $ cargo build Compiling heapless_debug_err v0.1.0 (/home/caleb/tmp/no_std_heapless/libc_print_how) warning: unused import: `libc` --> src/main.rs:5:5 | 5 | use libc; | ^^^^ | = note: `#[warn(unused_imports)]` on by default error: linking with `cc` failed: exit status: 1 | = note: LC_ALL="C" PATH="/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/caleb/.modular/pkg/packages.modular.com_mojo/bin:/run/user/1000/fnm_multishells/45691_1726058239106/bin:/usr/local/sbin:/usr/local/bin:/home/caleb/.local/share/JetBrains/Toolbox/scripts/:/snap/bin:/home/caleb/go/bin:/usr/sbin:/home/caleb/Dropbox/Technical/codelibs/bin:/home/caleb/bin:/home/caleb/.cargo/bin:/home/caleb/.local/bin:/home/caleb/Downloads/zig-linux-x86_64-0.12.0:/bin:/usr/bin" VSLANG="1033" "cc" "-m64" "/tmp/rustcgoHT0r/symbols.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.103qnko1lohuvkimci0fd7g72.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.1mfnq4h650ety896dtrpo3e0p.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.1nqtj657kao438xyq70kqirmo.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.375t1g7ov8ily1i3ywelm0xvt.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.43o13xbntrfzp2zyp2epr9eod.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.4nv1v0pbeucefmivuvf4mhrsx.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.65apesuvfc1piaqeuivcqrn15.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.6c0f4mdpjijwbixka0s9l2s4i.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.6lebqev3orvw3j4ipox6ftibv.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.6p7l92m0wk5t6bmfmtzdkb7d4.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.6z7dzm2mrt6hhspnadyyri1xf.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.7a2991n0u41g4rg6btp4ti0va.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.7hbfh1d1s047grr47rgukotho.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.8oqrttr9rssx7gr6cwg12wkmb.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.8so8mqosyn0tvy5hnj9g1ku9l.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.9gfl301xa7po0lxeqey8da6j3.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.9rkp0grqz0ks6z6ovu4n2nyfy.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.ar8mdmmannklqyz3rmf2bw2ub.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.auhbm9uwrtb32xam9donklqn5.rcgu.o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef.b862efaqf6ajkags50mtv2haw.rcgu.o" "-Wl,--as-needed" "-L" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps" "-L" "/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/libheapless-c0cbae0f547a8105.rlib" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/libhash32-a0bd382e6ff2493a.rlib" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/libbyteorder-2df7e366e369b3b1.rlib" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/liblibc-99893e597621ca51.rlib" "/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-2a862c0b1c86f483.rlib" "/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-500f37ee5bcf0ffe.rlib" "/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-06dfbf1de02fde3b.rlib" "-Wl,-Bdynamic" "-lc" "-lm" "-lrt" "-lpthread" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/caleb/tmp/no_std_heapless/libc_print_how/target/debug/deps/heapless_debug_err-aef797243ee916ef" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" = note: /bin/ld: /home/caleb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-500f37ee5bcf0ffe.rlib(core-500f37ee5bcf0ffe.core.3cad2706d8bdcdc4-cgu.0.rcgu.o):(.data.DW.ref.rust_eh_personality[DW.ref.rust_eh_personality]+0x0): undefined reference to `rust_eh_personality' collect2: error: ld returned 1 exit status = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified = note: use the `-l` flag to specify native libraries to link = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib) warning: `heapless_debug_err` (bin "heapless_debug_err") generated 1 warning error: could not compile `heapless_debug_err` (bin "heapless_debug_err") due to 1 previous error; 1 warning emitted ```

Discussion

The issue happens with the FnvIndexMap, not with the Vec. Commenting out the hashmap resolves it:

#![no_std]
#![no_main]

use core::panic::PanicInfo;
use libc;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
    let mut v = heapless::Vec::<i32, 16>::new();
    v.push(1).unwrap();

    // let mut h = heapless::FnvIndexMap::<i32, i32, 16>::new();
    // h.insert(1, 2).unwrap();
    0
}
$ cargo build
   Compiling heapless_debug_err v0.1.0 (/home/caleb/tmp/no_std_heapless/libc_print_how)
warning: unused import: `libc`
 --> src/main.rs:5:5
  |
5 | use libc;
  |     ^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: `heapless_debug_err` (bin "heapless_debug_err") generated 1 warning (run `cargo fix --bin "heapless_debug_err"` to apply 1 suggestion)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s

The complaint about rust_eh_personality is something I've seen before, in a different library that supports no_std. In that case, it turned out that a macro using format_args! was somehow causing a debug_assert to get compiled in. Even though my crate specifes panic = "abort", nevertheless somehow the debug_assert was bringing in panic unwinding code. For that library, I could resolve the problem with debug-assertions = false, which is why I have that set here. However, with the heapless hashmap shown here it seems to be a different issue.

So my guess is that there is something in heapless::FnvIndexMap that is somehow including panic code but only in debug mode.

rjsberry commented 2 months ago

The issue here is that the stock libcore is built with panic=unwind.

If you want to stay on stable you could try bumping the opt level:

[profile.dev]
opt-level = 1
panic = "abort"

[profile.release]
panic = "abort"

Or if you can use a nightly toolchain compile libcore yourself with panic=abort:

cargo +nightly -Zbuild-std build --target x86_64-unknown-linux-gnu

Related: https://github.com/rust-lang/rust/issues/56152

Dirbaio commented 2 months ago

closing, not a bug in heapless as per the above comment.