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

Static linking without LTO on Linux does not remove unused code #39270

Closed
sdroege opened this issue Jan 24, 2017 · 10 comments
Closed

Static linking without LTO on Linux does not remove unused code #39270

sdroege opened this issue Jan 24, 2017 · 10 comments

Comments

@sdroege
Copy link
Contributor

sdroege commented Jan 24, 2017

When linking a minimal cdylib on Linux with Rust 1.14.0, lots of code from libstd is included that should not be. According to @sfackler, on MacOS all that code is not included.
Enabling LTO will get it removed on Linux, while it's not required on MacOS.

When compiling a mini-cdylib (see below), you can e.g. find functions for receiving packets from UDP sockets:

$ objdump -T ./target/release/libtest.so | grep net | grep recv
0000000000074710 g    DF .text	000000000000003f  Base        _ZN3std3sys3imp3ext3net12UnixDatagram4recv17hd6877157b1dad8adE
0000000000074210 g    DF .text	00000000000004fe  Base        _ZN3std3sys3imp3ext3net12UnixDatagram9recv_from17h5fb97d5dc256448cE
0000000000061bf0 g    DF .text	0000000000000177  Base        _ZN3std3net3udp9UdpSocket9recv_from17h69eac8c4da79232dE
0000000000062770 g    DF .text	000000000000003f  Base        _ZN3std3net3udp9UdpSocket4recv17hf94a0fd19de68323E

See following mini-cdylib for reproducing

src/lib.rs

#[no_mangle]                                                                                               
pub extern "C" fn foo(meh: &i32) {
    println!("foo {}", meh);
}

Cargo.toml

[package]
name = "test"
version = "0.1.0"
authors = ["Some One <[email protected]>"]

[profile.release]
#lto = true

[lib]
name = "test"
crate-type = ["cdylib"]
path = "src/lib.rs"
@sfackler
Copy link
Member

I can repro this on CentOS 6. We're passing this to cc:

cc -Wl,--as-needed -Wl,-z,noexecstack -m64 -L /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib /tmp/foo/target/release/deps/foo.0.o -o /tmp/foo/target/release/deps/libfoo.so -Wl,--retain-symbols-file=/tmp/rustc.S66vFMiyj67d/list -Wl,--gc-sections -Wl,-O1 -nodefaultlibs -L /tmp/foo/target/release/deps -L /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib -Wl,-Bstatic -Wl,-Bdynamic /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_unicode-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_system-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-f5a209a9.rlib /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-f5a209a9.rlib -l dl -l pthread -l gcc_s -l pthread -l c -l m -l rt -l util -shared

Could it be that CentOS 6's ld doesn't actually support --gc-sections? The man page seems to say it's a no-op on "unsupported targets".

@sdroege
Copy link
Contributor Author

sdroege commented Jan 24, 2017

I'm running on Debian/unstable with GNU ld 2.27.90.20170118 on x86-64, which definitely supports --gc-sections

@alexcrichton
Copy link
Member

If we linked these as usual then we'd have all these exported symbols, but we tell the linker to use a version script which should hide all the symbols in the standard library. I think it does that at least, but all the others are still exported... somehow. I'm not super familiar with all the various levels of visibility.

@alexcrichton
Copy link
Member

cc @michaelwoerister maybe related to #38117?

@sdroege
Copy link
Contributor Author

sdroege commented Jan 24, 2017

It's not only about having the symbols exported, but also about having the code corresponding to those symbols in the binaries at all although none of them are used

@alexcrichton
Copy link
Member

Yes my assumption is that the linker sees that we're not exporting a symbol and it's in its own section, so it eliminates it. Apparently that's not happening though.

@michaelwoerister
Copy link
Member

Does this also happen with the nightly compiler?

@alexcrichton
Copy link
Member

@michaelwoerister aha, looks like no! I think I misinterpreted results from earlier... In that case I think this is dealt with already!

@michaelwoerister
Copy link
Member

At least the problem description sounds a lot like what #38117 was meant to solve :)

@sdroege
Copy link
Contributor Author

sdroege commented Jan 24, 2017

Yes, with nightly this problem does not exist anymore. Thanks for fixing this before I even reported it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants