New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building `no_std` binary fails with link error "undefined reference to `__rust_probestack" #43264

Open
ranweiler opened this Issue Jul 16, 2017 · 7 comments

Comments

Projects
None yet
4 participants
@ranweiler
Contributor

ranweiler commented Jul 16, 2017

Platform

  • Rust nightly, version: rustc 1.20.0-nightly (086eaa78e 2017-07-15)
  • OS: Linux 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) x86_64 GNU/Linux

Summary

Compilation of a no_std binary on nightly fails with a linking error about the new stack probe feature.

Expected: The binary builds successfully, and rustc links to the new __rust_probestack implementation for my platform.

Observed: Building fails with a link error: undefined reference to `__rust_probestack'

Comments

I poked around the Rust source and recent PRs around stack probes, and the feature didn't seem to be configurable. Things that would be nice: the ability to toggle stack probes with a -C flag, or to have a configurable language item, like we do for eh_personality and panic_fmt. I have not yet tried to work around this with linker arguments, as it is more of a weird edge case I ran into in some throwaway example code.

Question

Is there a reason this behavior is expected, and linking shouldn't just work?

Test case

The issue can be reproduced using the following project:

Cargo.toml:

[package]
name = "example"
version = "0.1.0"

[dependencies]
libc = { version = "0.2.11", default-features = false }

and src/main.rs:

#![feature(lang_items)]
#![feature(start)]
#![no_std]
extern crate libc;

// const SIZE: usize = 2008; // This is a threshold. The project successfully builds.
const SIZE: usize = 2009; // This is the smallest array size which triggered a failure.

struct S { data: [u8; SIZE] }

#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
    let s = S { data: [0; SIZE] };
    0
}

#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] extern fn panic_fmt() -> ! { loop {} }

Output

Full error from cargo build:

$ cargo build --verbose
       Fresh libc v0.2.26
   Compiling example v0.1.0 (file:///home/joe/src/example)
     Running `rustc --crate-name example src/main.rs --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=9cb543322668ed58 -C extra-filename=-9cb543322668ed58 --out-dir /home/joe/src/example/target/debug/deps -L dependency=/home/joe/src/example/target/debug/deps --extern libc=/home/joe/src/example/target/debug/deps/liblibc-d2ff9e092d4e994b.rlib`
warning: field is never used: `data`
 --> src/main.rs:9:12
  |
9 | struct S { data: [u8; SIZE] }
  |            ^^^^^^^^^^^^^^^^
  |
  = note: #[warn(dead_code)] on by default

warning: unused variable: `s`
  --> src/main.rs:13:9
   |
13 |     let s = S { data: [0; SIZE] };
   |         ^
   |
   = note: #[warn(unused_variables)] on by default

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/joe/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/joe/src/example/target/debug/deps/example-9cb543322668ed58.0.o" "-o" "/home/joe/src/example/target/debug/deps/example-9cb543322668ed58" "-Wl,--gc-sections" "-pie" "-nodefaultlibs" "-L" "/home/joe/src/example/target/debug/deps" "-L" "/home/joe/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/joe/src/example/target/debug/deps/liblibc-d2ff9e092d4e994b.rlib" "/home/joe/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-225cf0734ab321d6.rlib" "-Wl,-Bdynamic" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util"
  = note: /home/joe/src/example/target/debug/deps/example-9cb543322668ed58.0.o: In function `example::start':
          /home/joe/src/example/src/main.rs:12: undefined reference to `__rust_probestack'
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

error: Could not compile `example`.

Caused by:
  process didn't exit successfully: `rustc --crate-name example src/main.rs --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=9cb543322668ed58 -C extra-filename=-9cb543322668ed58 --out-dir /home/joe/src/example/target/debug/deps -L dependency=/home/joe/src/example/target/debug/deps --extern libc=/home/joe/src/example/target/debug/deps/liblibc-d2ff9e092d4e994b.rlib` (exit code: 101)
@Mark-Simulacrum

This comment has been minimized.

Show comment
Hide comment
@Mark-Simulacrum
Member

Mark-Simulacrum commented Jul 19, 2017

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 19, 2017

Member

@ranweiler as a no_std binary this is missing the compiler_builtins crate which is where these intrinsics come from.

If you follow these instructions does that solve your problem?

Member

alexcrichton commented Jul 19, 2017

@ranweiler as a no_std binary this is missing the compiler_builtins crate which is where these intrinsics come from.

If you follow these instructions does that solve your problem?

@ranweiler

This comment has been minimized.

Show comment
Hide comment
@ranweiler

ranweiler Jul 19, 2017

Contributor

@alexcrichton, yes, the instructions at your link resolved the link error. Thank you!

Also, looks like it is sufficient to add #![feature(compiler_builtins_lib)] and extern crate compiler_builtins; to my main.rs. Adding the explicit Cargo dependency is not necessary. I'm assuming this just uses the active toolchain's version of compiler_builtins.

For the reference of others, I've found (indirect) documentation for the reported situation here: https://doc.rust-lang.org/unstable-book/library-features/compiler-builtins-lib.html

The documentation I was working from included this section of the Unstable Book: "Writing an executable without stdlib", which doesn't mention this feature at all.

  1. Should users writing no_std binaries always use this feature/crate?
  2. Should we add a comment about the compiler_builtins_lib feature to the above docs on writing a no_std executable?
Contributor

ranweiler commented Jul 19, 2017

@alexcrichton, yes, the instructions at your link resolved the link error. Thank you!

Also, looks like it is sufficient to add #![feature(compiler_builtins_lib)] and extern crate compiler_builtins; to my main.rs. Adding the explicit Cargo dependency is not necessary. I'm assuming this just uses the active toolchain's version of compiler_builtins.

For the reference of others, I've found (indirect) documentation for the reported situation here: https://doc.rust-lang.org/unstable-book/library-features/compiler-builtins-lib.html

The documentation I was working from included this section of the Unstable Book: "Writing an executable without stdlib", which doesn't mention this feature at all.

  1. Should users writing no_std binaries always use this feature/crate?
  2. Should we add a comment about the compiler_builtins_lib feature to the above docs on writing a no_std executable?
@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 19, 2017

Member

Ok cool, glad that worked out! This is an interesting case though in terms of documentation and embedding and whatnot. In the limit it's true that all binaries should use this crate unconditionally, but for specific really tiny embedded projects it may want to be avoided for one reason or another.

My recommendation though would be that we should definitely update the docs to mention this!

Member

alexcrichton commented Jul 19, 2017

Ok cool, glad that worked out! This is an interesting case though in terms of documentation and embedding and whatnot. In the limit it's true that all binaries should use this crate unconditionally, but for specific really tiny embedded projects it may want to be avoided for one reason or another.

My recommendation though would be that we should definitely update the docs to mention this!

@ranweiler

This comment has been minimized.

Show comment
Hide comment
@ranweiler

ranweiler Jul 19, 2017

Contributor

@alexcrichton, great, and thanks so much for the help! I'm happy to open a PR for the docs, too.

Contributor

ranweiler commented Jul 19, 2017

@alexcrichton, great, and thanks so much for the help! I'm happy to open a PR for the docs, too.

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 19, 2017

Member

That'd be awesome, thanks! Feel free to r? me on the PR and I can take a look

Member

alexcrichton commented Jul 19, 2017

That'd be awesome, thanks! Feel free to r? me on the PR and I can take a look

Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Jul 24, 2017

Rollup merge of rust-lang#43342 - ranweiler:no-std-exe-docs, r=alexcr…
…ichton

Document use of `compiler_builtins` with `no_std` binaries

See discussion in rust-lang#43264.

The docs for the `compiler_builtins_lib` feature were removed in
PR rust-lang#42899. But, though the `compiler_builtins` library has been
migrated out-of-tree, the language feature remains, and is needed to
use the stand-alone crate. So, we reintroduce the docs for the
feature, and add a reference to them when describing how to create a
`no_std` executable.
@FiloSottile

This comment has been minimized.

Show comment
Hide comment
@FiloSottile

FiloSottile Aug 7, 2017

FWIW, this (along with #38281) is very hard to discover when trying to just make a simple no_std staticlib, partially because it's unclear what the entry point docs are for no_std (I ended up starting from an old version of the book).

FiloSottile commented Aug 7, 2017

FWIW, this (along with #38281) is very hard to discover when trying to just make a simple no_std staticlib, partially because it's unclear what the entry point docs are for no_std (I ended up starting from an old version of the book).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment