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

musl staticlib builds include all of the musl symbols #65760

Open
Twey opened this issue Oct 24, 2019 · 3 comments
Open

musl staticlib builds include all of the musl symbols #65760

Twey opened this issue Oct 24, 2019 · 3 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-musl Target: The musl libc T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Twey
Copy link

Twey commented Oct 24, 2019

Observed Behaviour

If I produce a simple staticlib crate for the x86_64-unknown-linux-musl target, I get a .a file that includes all the symbols from musl, including standard libc symbols like (for example) readlink. This makes it impossible to link this library into a C program that links against libc itself (or another Rust staticlib) as the linker will fail with duplicate symbol errors.

Reproduction

A test repository is at https://github.com/Twey/musl-staticlib-test, along with a Nix description of the relevant build environment for those so inclined. You can execute rustc -omusl-staticlib-test.a --target=x86_64-unknown-linux-musl --crate-type=staticlib lib.rs to get a library, and use a tool such as nm to view the symbols in the resulting binary. For example:

[twey@uruz:/tmp/musl-staticlib-test]$ nm musl_staticlib_test.a | grep readlink
                 U readlink
0000000000000000 T _ZN3std3sys4unix2fs8readlink17h4d68afd72996b214E
                 U readlink
readlink.lo:
0000000000000000 T readlink
readlinkat.lo:
0000000000000000 T readlinkat
                 U readlink

Expected Behaviour

Normally, static libraries for consumption by C, like rlibs, contain only symbols from the project itself, not symbols from dependencies. Certainly symbols from libc should never make it into the binary, as these will always conflict.

For example, here's libev, also built statically against musl:

[twey@uruz:/tmp/musl-staticlib-test]$ nm /nix/store/6r9z7a007vrla17paac35c968fmbzilq-libev-4.27-x86_64-unknown-linux-musl/lib/libev.a | grep readlink
[twey@uruz:/tmp/musl-staticlib-test]$
@jonas-schievink jonas-schievink added A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-musl Target: The musl libc T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 24, 2019
@aidanhs
Copy link
Member

aidanhs commented Oct 24, 2019

The culprit is likely https://github.com/gnzlbg/libc/blob/e07cd949b0f5f30c009066b8c074ae32afd7feed/src/unix/mod.rs#L299-L305, where musl libc is unconditionally statically linked in when including the rust stdlib with "crt-static".

When working with @Twey on this, our general observation was that:

  • it's not a good idea to put libc in a staticlib
  • it's not a good idea to put libc in a cdylib
  • it is a good idea for musl static linking to put musl libc in a binary

Unfortunately, the first is not handled correctly by Rust. The right way to solve this for staticlibs is likely to just not link to libc at all - the symbols will remain undefined (as they should) and can be filled out in the actual link later.

Unfortunately there's no way (that I'm aware of) to switch a cfg based on the final "kind of thing" being linked/produced by Rust, i.e. "if this is a staticlib then please don't link libc statically". And I do think it has to be a special case for libc - it is entirely reasonable to want to be able to bundle staticlibs inside each other in general.

In an interesting twist of fate, setting -crt-static 'fixes' it...even though this attempts to link against libc dynamically. I believe the reason this works (and, as far as I can tell, the only reason building glibc staticlibs works at all) is because dylibs are ignored when creating a staticlib (without a warning afaict, contrary to the comment in the code) - https://github.com/rust-lang/rust/blob/3f2ae44/src/librustc_codegen_ssa/back/link.rs#L402-L403.

@mati865
Copy link
Contributor

mati865 commented Oct 24, 2019

@aidanhs there was an attempt to do it, detailed discussion is available at rust-lang/libc#1327

@petrochenkov
Copy link
Contributor

Posted a plan for the fix in #72274.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-musl Target: The musl libc 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

5 participants