Skip to content
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

/checkout/src/libcore/num/mod.rs:920: undefined reference to `__muloti4' when using core::num methods in a no-std staticlib #48339

Closed
glandium opened this issue Feb 18, 2018 · 14 comments
Labels
C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@glandium
Copy link
Contributor

glandium commented Feb 18, 2018

STR:

$ cargo new foo
$ cd foo
$ cat <<EOF >> Cargo.toml
[lib]
crate-type = ["staticlib"]
[profile.release]
panic = "abort"
EOF
$ cat <<EOF > src/lib.rs
#![feature(lang_items)]
#![no_std]
#[lang="panic_fmt"]
#[no_mangle]
extern fn panic_fmt(_: ::core::fmt::Arguments, _: &'static str, _: u32, _: u32) -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn foo(a: u32, b: u32) -> u32 {
    a.checked_add(b).unwrap()
}
EOF
$ cat <<EOF > test.c
extern unsigned foo(unsigned, unsigned);

int main() {
    foo(1, 2);
    return 0;
}
EOF
$ cargo +nightly build --release
$ gcc -o test test.c target/release/libfoo.a
target/release/libfoo.a(core-963c548171e08e13.core0.rcgu.o): In function `core::num::<impl i128>::overflowing_mul':
/checkout/src/libcore/num/mod.rs:920: undefined reference to `__muloti4'
/checkout/src/libcore/num/mod.rs:920: undefined reference to `__muloti4'

Note this happens whether you actually use overflowing_mul or not: anything that uses a function from core::num triggers this because of how the linker works.

The following also appears:

target/release/libfoo.a(core-963c548171e08e13.core0.rcgu.o): In function `core::panicking::panic_fmt':
/checkout/src/libcore/panicking.rs:71: undefined reference to `rust_begin_unwind'

which is surprising when building with panic=abort.

Somehow, building without --release (but adding panic=abort to profile.dev) adds another error:

target/debug/libfoo.a(foo-4ef191f9b3780723.4ypvbwho0bu5tnww.rcgu.o):(.data.DW.ref.rust_eh_personality[DW.ref.rust_eh_personality]+0x0): undefined reference to `rust_eh_personality'
@glandium
Copy link
Contributor Author

The funny thing is that this is all triggered by .unwrap(). Without unwrap, the core::num function is inlined, and nothing from num.rs is linked in. So somehow, the code path for unwrap ends up calling into some non-inlined core::num function (or some function pulled in from the same object as core::panicking::panic does, etc.).

@glandium
Copy link
Contributor Author

Indeed, this all still happens when replacing the body of the foo function with panic!("").

@glandium
Copy link
Contributor Author

The

/checkout/src/libcore/panicking.rs:71: undefined reference to `rust_begin_unwind'

error is because panic_fmt was not properly exported. It's missing pub and #[no_mangle]. I'll file a separate bug for that.

@glandium
Copy link
Contributor Author

The core problem here seems to be that libcompiler-builtins is not linked in, while it is when building without no-std.

@pietroalbini pietroalbini added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Feb 20, 2018
@glandium
Copy link
Contributor Author

Cc @japaric I think it is one of the issues you mentioned on http://blog.japaric.io/embedded-rust-in-2018/ (or close to one of them)

@japaric
Copy link
Member

japaric commented Feb 21, 2018

The core problem here seems to be that libcompiler-builtins is not linked in, while it is when building without no-std.

That's because std depends on compiler-builtins while core does not (core can't depend on anything). You'll have to add (a) link to compiler-builtins as in add extern crate compiler_builtins to your lib.rs, or (b) link to libgcc.a when linking the final binary. Both compiler-builtins and libgcc.a should provide the symbol you are missing

@glandium
Copy link
Contributor Author

There are actually two problems in one here.

One is that somehow the implementation for overflowing_mul gets pulled in.

The second is that when it's pulled in, legitimately or not, you end up with a dependency on a __muloti4 symbol, and that's an implementation detail of how LLVM compiles libcore. Crates merely using libcore shouldn't have to care what implementations details of LLVM require, and shouldn't have to link to compiler-builtins or whatever on their own (btw, __muloti4 is not in libgcc.a).

@nikomatsakis
Copy link
Contributor

@glandium

One is that somehow the implementation for overflowing_mul gets pulled in.

Clarification: By this I guess you mean more "not stripped out", right? i.e., the implementation for overflowing_mul is in libcore, as I understand, but since it is not used, you expect it to be stripped? Or am I confused.

The second is that when it's pulled in, legitimately or not, you end up with a dependency on a __muloti4 symbol

This seems to interact with @aturon's proposal to deprecate the facade and move towards something more like cargo features. If we did so, it'd be no problem for us to bring in supplemental libraries in addition to core.

cc @jethrogb -- I'm not really clear on what the "state of the art" is here. I had a look around the portability WG repo but I wasn't sure just what I was looking for. =)

@jethrogb
Copy link
Contributor

Added issue for compiler_builtins

@glandium
Copy link
Contributor Author

Clarification: By this I guess you mean more "not stripped out", right? i.e., the implementation for overflowing_mul is in libcore, as I understand, but since it is not used, you expect it to be stripped? Or am I confused.

In the case of the code I pasted when filing this issue, it's "just" a problem of it not being stripped out. In fact, passing -Wl,--gc-sections to gcc makes the problem go away. But if you look closely at the generated libfoo.a, you'll see that the __muloti4 calls are inlined in from_str_radix, which is called from various from_str functions, so it's really not hard to have it become a legitimately necessary symbol that won't be stripped.

Also note that the problem does happen without involving a non-rust compiler, on Windows: it seems cargo doesn't pass the equivalent to -Wl,--gc-sections to link.exe, or the libcore code is not generated in a way that allows link.exe to do it (because I think it's actually enabled by default in link.exe).

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Mar 22, 2018

so it's really not hard to have it become a legitimately necessary symbol that won't be stripped

ok so the bigger priority is to find a way to supply it.

@glandium
Copy link
Contributor Author

This issue would be fixed by #49380.

@zokier
Copy link

zokier commented Apr 8, 2018

Has this been resolved by #49503?

#49380 is now closed

@glandium
Copy link
Contributor Author

glandium commented Apr 8, 2018

Yes, this is now fixed.

@glandium glandium closed this as completed Apr 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants