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

Duplicate symbols when compiling a library with x86_64-unknown-linux-musl #78919

Closed
jasagredo opened this issue Nov 10, 2020 · 1 comment
Closed
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

@jasagredo
Copy link

jasagredo commented Nov 10, 2020

I created a toy project that was supposed to link against musl-libc. For that, I installed the target as described here:

❯ rustup target add x86_64-unknown-linux-musl
info: downloading component 'rust-std' for 'x86_64-unknown-linux-musl'
info: installing component 'rust-std' for 'x86_64-unknown-linux-musl'
info: Defaulting to 500.0 MiB unpack ram
 20.3 MiB /  20.3 MiB (100 %)  18.5 MiB/s in  1s ETA:  0s

Proceeded then to create a rust library that only exported one function through ffi:

❯ tree
.
├── Cargo.toml
└── src
    └── lib.rs

1 directory, 2 files
❯ tail Cargo.toml src/lib.rs
==> Cargo.toml <==
version = "0.1.0"
authors = ["Javier <xxxxx>"]
edition = "2018"

[lib]
crate-type = ["staticlib"]

[dependencies]

==> src/lib.rs <==
#[no_mangle]
pub extern "C" fn hi() {
    println!("Hi from Rust");
}

Tried then a simple compilation specifying the target, which succeeds:

❯ cargo build --target x86_64-unknown-linux-musl
   Compiling simple_rs_lib v0.1.0 (/home/javier/simpleRSlib)
    Finished dev [unoptimized + debuginfo] target(s) in 0.06s

Which indeed seems to work as I can link this other C program with it:

❯ tail rust.h program.c
==> rust.h <==
void hi();

==> program.c <==
#include <rust.h>
int main() {
	hi();
}
❯ musl-gcc -o program program.c -I/home/javier/simpleRSlib/ -L/home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug -lsimple_rs_lib
❯ ./program
Hi from Rust

However this is not fully static as we can see here:

❯ musl-ldd program
	/lib/ld-musl-x86_64.so.1 (0x7f3a3e809000)
	libc.so => /lib/ld-musl-x86_64.so.1 (0x7f3a3e809000)

So then trying to specify to the linked that we want to get a fully static binary:

❯ musl-gcc -static -o program program.c -I/home/javier/simpleRSlib/ -L/home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug -lsimple_rs_lib
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(__init_tls.lo): in function `__init_tp':
(.text.__init_tp+0x0): multiple definition of `__init_tp'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(__init_tls.lo):__init_tls.c:(.text.__init_tp+0x0): first defined here
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(__init_tls.lo): in function `__copy_tls':
(.text.__copy_tls+0x0): multiple definition of `__copy_tls'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(__init_tls.lo):__init_tls.c:(.text.__copy_tls+0x0): first defined here
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(abort.lo): in function `abort':
(.text.abort+0x0): multiple definition of `abort'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(abort.lo):abort.c:(.text.abort+0x0): first defined here
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(libc.lo):(.bss.__progname_full+0x0): multiple definition of `__progname_full'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(libc.lo):(.bss.__progname_full+0x0): first defined here
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(libc.lo):(.bss.__progname+0x0): multiple definition of `__progname'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(libc.lo):(.bss.__progname+0x0): first defined here
/usr/bin/ld: warning: size of symbol `__libc' changed from 112 in /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(libc.lo) to 104 in /usr/lib/x86_64-linux-musl/libc.a(libc.lo)
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(sigaction.lo): in function `__get_handler_set':
(.text.__get_handler_set+0x0): multiple definition of `__get_handler_set'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(sigaction.lo):sigaction.c:(.text.__get_handler_set+0x0): first defined here
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(sigaction.lo): in function `__libc_sigaction':
(.text.__libc_sigaction+0x0): multiple definition of `__libc_sigaction'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(sigaction.lo):sigaction.c:(.text.__libc_sigaction+0x0): first defined here
/usr/bin/ld: /usr/lib/x86_64-linux-musl/libc.a(sigaction.lo): in function `__sigaction':
(.text.__sigaction+0x0): multiple definition of `__sigaction'; /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(sigaction.lo):sigaction.c:(.text.__sigaction+0x0): first defined here
collect2: error: ld returned 1 exit status

This seems to indicate that we have duplicated libc symbols coming from the rust library and from the system's musl-libc. Which then could be solved by indicating -z muldefs as specified in the documentation for gold. This will keep the first symbol in case of a duplicate, and it warns if the size changes:

❯ musl-gcc -Wl,-z,muldefs -static -o program program.c -I/home/javier/simpleRSlib/ -L/home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug -lsimple_rs_lib
/usr/bin/ld: warning: size of symbol `__libc' changed from 112 in /home/javier/simpleRSlib/target/x86_64-unknown-linux-musl/debug/libsimple_rs_lib.a(libc.lo) to 104 in /usr/lib/x86_64-linux-musl/libc.a(libc.lo)
❯ musl-ldd program
musl-ldd: program: Not a valid dynamic program
❯ ./program
Hi from Rust

So the size of the __libc symbol changed between musl's libc and the object included in the rust library we compiled. Inspecting libc.lo it seems to contain the programe routine. Is it safe to overwrite this symbol if using the rust library in other compiler?:

❯ nm libc.lo
0000000000000008 C __hwcap
0000000000000070 C __libc
0000000000000000 B __progname
0000000000000000 B __progname_full
0000000000000000 V program_invocation_name
0000000000000000 V program_invocation_short_name

So here comes the question:

How can I avoid these duplicate symbols produced by Rust "duplicating" symbols that are present in the standard musl distribution?
Should a library even have those symbols defined?
Why is there a size change in a routine for setting the program name if everything should be linked against the same musl libc?

Also, I tried to use strace to print all the consulted libraries from the system and it seems to only use linux-gnu libraries, though I'm not an expert on strace and these could be just the libraries that are loaded to execute gcc/rustc and not the ones opened by the linker to link the symbols. If someone could clarify this it would be awesome:

Output

``` ❯ strace -f cargo build --target x86_64-unknown-linux-musl 2>&1 | grep /lib/x86_64 | grep -v ENOENT openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, " /usr/lib/x86_64-linux-gnu/li"..., 1024) = 1024 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libz.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41785] read(3, " /usr/lib/x86_64-linux-gnu/l"..., 1024) = 1024 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libz.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41786] read(3, " /usr/lib/x86_64-linux-gnu/l"..., 1024) = 1024 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libz.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 [pid 41788] read(3, " /usr/lib/x86_64-linux-gnu/l"..., 1024) = 1024 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] read(7, " /usr/lib/x86_64-l"..., 1024) = 979 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libz.so.1", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 7 [pid 41792] read(7, " /usr/lib/x86_64-linux-gnu/l"..., 1024) = 1024 ```

Meta

System information

❯ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.10
Release:	20.10
Codename:	groovy
❯ uname -r
5.8.0-26-generic
❯ find /usr/lib/ -maxdepth 1 -type d -name "x86_64*"
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-musl
❯ find /usr/lib/ -type f -name "libc.*"
/usr/lib/x86_64-linux-gnu/libc.so
/usr/lib/x86_64-linux-gnu/libc.a
/usr/lib/x86_64-linux-musl/libc.so
/usr/lib/x86_64-linux-musl/libc.a

rustc --version --verbose:

❯ rustc --version --verbose
rustc 1.47.0 (18bf6b4f0 2020-10-07)
binary: rustc
commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
commit-date: 2020-10-07
host: x86_64-unknown-linux-gnu
release: 1.47.0
LLVM version: 11.0
@jasagredo jasagredo added the C-bug Category: This is a bug. label Nov 10, 2020
@camelid camelid added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Nov 10, 2020
@jyn514 jyn514 added A-linkage Area: linking into static, shared libraries and binaries O-musl Target: The musl libc labels Nov 11, 2020
@jasagredo
Copy link
Author

Seems that for my intended use, target-feature=-crt-static is needed. For reference https://rust-lang.github.io/rfcs/1721-crt-static.html

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

3 participants