jlb6740
jlb6740

Reputation: 79

How to troubleshoot why cargo/rustc links in rust standard library symbols even when no_std is used?

I am trying to create an embed-friendly executable (small footprint and without dependency on the Rust standard library) that uses a library (wasmi) that already has support for a no_std build. New to Rust, I am simply piecing together instructions, but the gist of it appears to be follow the steps.

For the executable:

#![no_std]
#![no_main]

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! {
    interpret(_argc, _argv);
    loop {}
}

That is to:

My Cargo file to compile this looks like this:

[package]
 name = "driver"
 version = "0.1.0"
 edition = "2018"

[dependencies.wasmi]
 path = "../../github_dev/wasmi" 
 features = ["core"]
 default-features = false
 test=false
 bench=false

 [profile.release]
 panic = "abort"
 lto = true
 incremental=false
 debug=true
 opt-level = "z"
 test=false
 bench=false

and produces a very small binary that excludes any standard library symbols (using nm to check) and runs as expected.

The problem occurs when I actually try to call a function from the wasmi library. It is built with no_std via the features=core line. Doing an nm on the files in release/deps/libwasmi-*.rlib shows no standard library symbols. However when linking occurs with this command:

rustc --release --verbose -- -C link-arg=-nostartfiles

it leads to:

   Compiling driver v0.1.0 (/home/my_home/wasmi_embed/driver)
     Running rustc --edition=2018 --crate-name driver src/main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C lto -C link-arg=-nostartfiles -C metadata=957eda2e590447ba -C extra-filename=-957eda2e590447ba --out-dir /home/my_home/wasmi_embed/driver/target/release/deps -L dependency=/home/my_home/wasmi_embed/driver/target/release/deps --extern libc=/home/my_home/wasmi_embed/driver/target/release/deps/liblibc-f7fb773c7b059a14.rlib --extern wasmi=/home/my_home/wasmi_embed/driver/target/release/deps/libwasmi-534aef1926b4eb6c.rlib

and an error occurs:

error[E0152]: duplicate lang item found: panic_impl.
  --> src/main.rs:31:1
   |
31 | / pub extern fn panic(_info: &PanicInfo) -> ! {
32 | |     loop {}
33 | | }
   | |_^
   |
   = note: first defined in crate `std`.

It seems Rust is trying to link in standard library support for at least panic handling, but I don't know why.

I would like help to understand why and to understand how to prevent it.

If I remove the panic_impl attribute then my executable compiles, but it includes a lot of standard library symbols that I am trying to prevent.

The example symbols I see are:

my_home@my_puter:~/wasmi_embed/driver/target/release$ nm --demangle -A -a -B -s --line-number test_2018 2>/dev/null | grep std
driver:00000000000264c0 t rust_begin_unwind  /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:311
driver:00000000000264a0 t rust_oom   /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/alloc.rs:203
driver:000000000001f490 t rust_panic /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:524
driver:0000000000025aa0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::get::he4f810e299a2e0b4    /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:372
driver:00000000000259a0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::box_me_up::hd8430725259668a8     /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:367
driver:0000000000021520 t _$LT$std..sys_common..process..DefaultEnvKey$u20$as$u20$core..borrow..Borrow$LT$std..ffi..os_str..OsStr$GT$$GT$::borrow::hbacd0cd7d7fbf1c1/rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/sys_common/process.rs:27
driver:0000000000021570 t _$LT$std..error..$LT$impl$u20$core..convert..From$LT$alloc..string..String$GT$$u20$for$u20$alloc..boxed..Box$LT$$LP$dyn$u20$std..error..Err
... plus more

The above symbols are not found in any of the rlib files under the dep directory including libwasmi, nor are they found in the driver executable when not calling libwasmi code.

I've read a similar issue (hence my test=false and bench=false in the Cargo.toml) but that did not help. I've tried to build with just rustc with varying commands (excluding Cargo) but the error is the same. I've tried to compile wasmi as a static library (ar) and link it in, but being new to Rust I was spending a lot of time trying to link it in and it just wasn't happening.

Upvotes: 5

Views: 1836

Answers (1)

jlb6740
jlb6740

Reputation: 79

I resolved this after seeking some help in the rust forums. enter link description here. Specifically, was not able to determine what was responsible for rust std lib being linked into my executable ... was it an issue with a crate or an issue with cargo or an issue with rustc or an issue with the linker. I did not know where the problem was born, but based on similar bugs filed I figured that somehow a crate was being compiled to bring in std lib unexpected. Turns out bug enter link description here was not related even though the error message was the same. I did not have an issue with unexpected propagations form different type of dependencies (dev-dependencies and build-dependencies). I tried all these techniques to pinpoint what was bringing in std lib:

  1. I tried using cargo tree to list dependencies to list all the crate dependencies:

    wasmi v0.4.3 (/home/jlb6740/github_dev/wasmi)
    ├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder)
    ├── hashbrown v0.1.8 (/home/jlb6740/github_dev/hashbrown)
    │ ├── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) ()
    │ └── scopeguard v0.3.3 (/home/jlb6740/github_dev/scopeguard)
    ├── libm v0.1.2
    ├── memory_units v0.3.0
    └── parity-wasm v0.31.0 (/home/jlb6740/github_dev/parity-wasm)
    └── byteorder v1.3.1 (/home/jlb6740/github_dev/byteorder) (
    )

  2. I tried using cargo rustc --verbose … but at this time verbose does not indicate anything was using default features which may include using std

  3. I tried using cargo metadata … this generated a long list of dependencies that was hard to parse, but I did see some instances where scopeguard and byteorder had default features requiring std support. I downloaded all of these crates and just hardcoded attributes so that the crates would only build with no_std support.

  4. I tried looking at the deps/ output and did an nm on all of the rlibs to see if any of the libraries used symbols found in std. I could not find that that was the case. I thought rlibs were like static libraries and that anything they used would be included in the rlib but apparently not.

  5. I looked at cargo rustc -- -C --print-link-args to check out linker flags but I could not find anything obvious telling me it was bringing in std lib.

None of these things helped me to pinpoint what was introducing std lib. Ultimately the suggestion at the rust forums was to use cargo check for a target that does not allow std lib at all. Those with a * listed here: enter link description here have only core support. I tried that, running with --target=thumbv7m-none-eabi and saw:

error[E0463]: can’t find crate for alloc
–> /home/jlb6740/github_dev/hashbrown/src/lib.rs:44:1
|
44 | extern crate std as alloc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ can’t find crate

Turns out it was hashbrown which was a dependency of a dependency of my executable. It built no_std by default but had an extern std linked under a different name and which was guarded by a feature called “nightly”. The guard was disabled in my efforts to not build anything but no_std. Nothing I’d tried alerted me to the crate which was responsible until this. Seems there should be a better way to get a more comprehensive list of crate dependencies than what cargo tree provided, but changing the wasmi cargo to make sure the nightly feature was set solved my issue.

Upvotes: -1

Related Questions