Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd a used attribute #1459
Conversation
mahkoh
added some commits
Jan 11, 2016
This comment has been minimized.
This comment has been minimized.
arcnmx
commented
Jan 12, 2016
|
Note that rust-lang/rust#30830 fixes this, and I consider the current behaviour to be a bug. However, there's a bit of an unresolved question around whether the type should need to be marked |
This comment has been minimized.
This comment has been minimized.
|
That issue is somewhat related but doesn't fix this.
|
This comment has been minimized.
This comment has been minimized.
|
I also don't agree with the patch that was merged. Items should be aggressively removed if they are not used. I'm not sure what your patch does exactly, but if it allows completely unused items to be present in the executable, then it should be reverted. |
This comment has been minimized.
This comment has been minimized.
arcnmx
commented
Jan 12, 2016
|
Erm I was a bit confused, sorry, let's make a graph! #![feature(linkage)]
#![allow(dead_code)]
#[link_section = ".init_array"] #[linkage = "external"]
static F_STATIC_EXT: extern fn() = f_static_external;
#[link_section = ".init_array"] #[linkage = "external"]
pub static F_PUB_STATIC_EXT: extern fn() = f_pub_static_external;
#[link_section = ".init_array"]
static F_STATIC: extern fn() = f_static;
#[link_section = ".init_array"]
pub static F_PUB_STATIC: extern fn() = f_pub_static;
extern fn f_static() {
println!("static");
}
extern fn f_static_external() {
println!("static external");
}
extern fn f_pub_static_external() {
println!("pub static external");
}
extern fn f_pub_static() {
println!("pub static");
}
fn main() { }
|
This comment has been minimized.
This comment has been minimized.
I don't think it is. Otherwise LLVM wouldn't have a separate mechanism for |
This comment has been minimized.
This comment has been minimized.
|
Linkage has really nothing to do with this RFC. |
This comment has been minimized.
This comment has been minimized.
arcnmx
commented
Jan 12, 2016
|
Ah, fair, I wasn't aware llvm had a construct for that! |
nrc
added
T-lang
T-dev-tools
labels
Jan 12, 2016
nikomatsakis
assigned
alexcrichton
Jan 14, 2016
This comment has been minimized.
This comment has been minimized.
|
This seems like a reasonable thing to me, modulo bikeshedding the name. I feel like the name should be less generic, perhaps include something about "link" in it :) |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis This is the name used by gcc/clang and llvm for this feature. I don't know what else you'd call it. |
This comment has been minimized.
This comment has been minimized.
|
Yes rust-lang/rust#30830 is different than this RFC as that largely just has to do with LTO. As @mahkoh indicated it is indeed the case that LLVM's For example, a #![feature(linkage)]
#[export_name = "llvm.used"]
#[linkage = "appending"]
static mut _FOO: [*const u8; 1] = [
&FOO_ADDR as *const _ as *const _
];
static FOO_ADDR: fn() = foo;
fn foo() {}
fn main() { }If you take a look at the generated object file: $ rustc foo.rs --emit obj
$ nm -g foo.o
0000000000000000 T main
U _ZN2rt10lang_start20h81372bffc43d2081zkyE
$ nm -a foo.o
0000000000000000 a foo.0.rs
0000000000000000 T main
0000000000000000 t .text.main
0000000000000000 t .text._ZN3foo20hea4f1d23bdee9020vaaE
0000000000000000 t .text._ZN4main20h7bc0c385e27c0783yaaE
U _ZN2rt10lang_start20h81372bffc43d2081zkyE
0000000000000000 t _ZN3foo20hea4f1d23bdee9020vaaE
0000000000000000 t _ZN4main20h7bc0c385e27c0783yaaE
0000000000000000 d _ZN8FOO_ADDR20hc3c6a3fb783d8c08saaEHere we can see that Another difference, I believe, is that LLVM has different optimization heuristics (such as inlining) for internal functions rather than external ones. In my testing, however, I was surprised that this may not be as useful as originally appearing. One might expect that if the above program is compiled into a binary that it would indeed have the relevant symbols in the binary (but as private), it in fact does not. The reason for this is that we still pass (note dynamic linkage is used here to reduce the number of stripped symbols $ rustc -C prefer-dynamic -O foo.rs -C link-args=-Wl,--print-gc-sections
INFO:rustc_trans::back::link: LinkMeta { crate_name: "foo", crate_hash: Svh { hash: "d9f16434537bb629" } }
INFO:rustc_trans::back::link: preparing dylib? (false) from ["foo.0.o"] to "foo"
INFO:rustc_trans::back::linker: linking with ld.gold
INFO:rustc_trans::back::link: "cc" "-Wl,--as-needed" "-m64" "-L" "/home/alex/.multirust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib" "foo.0.o" "-o" "foo" "-Wl,--gc-sections" "-pie" "-Wl,-O1" "-nodefaultlibs" "-L" "/home/alex/.multirust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "-L" "/home/alex/.multirust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-l" "std-17a8ccbd" "-l" "dl" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-fuse-ld=gold" "-Wl,--print-gc-sections" "-l" "compiler-rt"
INFO:rustc_trans::back::link: linker stderr:
/usr/bin/ld.gold: removing unused section from '.rodata.cst4' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/Scrt1.o'
/usr/bin/ld.gold: removing unused section from '.data' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/Scrt1.o'
/usr/bin/ld.gold: removing unused section from '.bss' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/Scrt1.o'
/usr/bin/ld.gold: removing unused section from '.text' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o'
/usr/bin/ld.gold: removing unused section from '.data' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o'
/usr/bin/ld.gold: removing unused section from '.bss' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o'
/usr/bin/ld.gold: removing unused section from '.data' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbeginS.o'
/usr/bin/ld.gold: removing unused section from '.text' in file 'foo.0.o'
/usr/bin/ld.gold: removing unused section from '.data' in file 'foo.0.o'
/usr/bin/ld.gold: removing unused section from '.bss' in file 'foo.0.o'
/usr/bin/ld.gold: removing unused section from '.text._ZN3foo20hea4f1d23bdee9020vaaE' in file 'foo.0.o'
/usr/bin/ld.gold: removing unused section from '.data.rel.ro.local._ZN8FOO_ADDR20hc3c6a3fb783d8c08saaE' in file 'foo.0.o'
/usr/bin/ld.gold: removing unused section from '.data' in file '/usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)'
/usr/bin/ld.gold: removing unused section from '.bss' in file '/usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)'
/usr/bin/ld.gold: removing unused section from '.text' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/crtendS.o'
/usr/bin/ld.gold: removing unused section from '.data' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/crtendS.o'
/usr/bin/ld.gold: removing unused section from '.bss' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/crtendS.o'
/usr/bin/ld.gold: removing unused section from '.text' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o'
/usr/bin/ld.gold: removing unused section from '.data' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o'
/usr/bin/ld.gold: removing unused section from '.bss' in file '/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o'Here we see that our "used symbol" This seems like it's at least a downside of this RFC, although it's one that I think it would also be interesting to explore if we could fix as well. The current state of affairs is that we've also stabilized very little with respect to this sort of fine-grained control over linkage and symbol names, which is relatively intentional. That's not to say the set could expand, though! This largely just means that there's not many other pieces of the system we need to consider the interaction with, but that set may grow over time. I'd personally probably be mostly interested in pursuing this as a nightly feature for now. I'm sure if there are that many use cases for an attribute like this (it looks like |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton My mistake was that I misunderstood this part of the LLVM docs:
I thought this referred to LLVM itself emitting such a directive on certain targets but maybe it is the code that generates the IR that has to do this. I'll investigate what clang does here. |
This comment has been minimized.
This comment has been minimized.
|
Oh interesting, so according to the docs as well:
I wonder if we're perhaps invoking the linker in a weird way? Or maybe it's just not designed to work in tandem with It looks like LLVM also has a |
This comment has been minimized.
This comment has been minimized.
|
Both GCC and clang throw If you're using a linker script you can tell the linker to keep a specific section. I haven't found a way to keep a section via a command line option. |
This comment has been minimized.
This comment has been minimized.
|
I don't think there are many uses for symbols are are not referenced anywhere at the linking stage. As long as this this behavior is documented, there shouldn't be an issue. |
This comment has been minimized.
This comment has been minimized.
arcnmx
commented
Jan 14, 2016
|
Agreed. The main purpose of the attribute would be to ensure that an internal symbol makes it all the way to the linker. At that point it's free to throw it out if it's truly unused; the linker script is what determines that. |
This comment has been minimized.
This comment has been minimized.
|
It's possible to keep them by putting them all in a section that is used: #![feature(linkage)]
#[export_name = "llvm.used"]
#[linkage = "appending"]
static mut _FOO: [*const u8; 1] = [
&foo as *const _ as *const _
];
#[link_section = ".text"]
fn foo() {}
#[link_section = ".text"]
fn main() { }This is probably good enough for those rare cases that want this behavior. |
This comment has been minimized.
This comment has been minimized.
|
I'd personally still be a bit wary to give this such a small name like |
This comment has been minimized.
This comment has been minimized.
What is "it"?
The same can be done with a #[used] attribute. What one might do is make #[used] more general (here called #[preserved]):
|
This comment has been minimized.
This comment has been minimized.
arcnmx
commented
Jan 15, 2016
|
I like |
This comment has been minimized.
This comment has been minimized.
|
I'd be a little wary to overdesign a feature like this as it may be difficult to actually guarantee that all the various combinations and such actually work. I'd also want to have a strong motivation for each one before we added it. I do agree, however, that |
This comment has been minimized.
This comment has been minimized.
|
Updated. |
This comment has been minimized.
This comment has been minimized.
|
I too prefer On Sat, Jan 16, 2016 at 6:37 PM, mahkoh notifications@github.com wrote:
|
This comment has been minimized.
This comment has been minimized.
|
The RFC uses the imperative form because it is also used for inline. |
This comment has been minimized.
This comment has been minimized.
|
Updated. |
This comment has been minimized.
This comment has been minimized.
ArtemGr
commented
Jan 18, 2016
|
Sorry if it's not entirely on topic, but could the |
This comment has been minimized.
This comment has been minimized.
|
That's an orthogonal issue that can already be solved with fences. |
alexcrichton
reviewed
Jan 19, 2016
| # Drawbacks | ||
| [drawbacks]: #drawbacks | ||
|
|
||
| None. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jan 19, 2016
Member
I think that this drawbacks section should probably at least mention that "may be discarded by the linker" can in some cases be confusing. In annotating a symbol as #[preserve] one might expect it to be preserved but it may not make it all the way through.
This comment has been minimized.
This comment has been minimized.
mahkoh
Jan 19, 2016
Author
Contributor
One might expect that #[inline] inlines the function but that's not true either.
alexcrichton
reviewed
Jan 19, 2016
| # Alternatives | ||
| [alternatives]: #alternatives | ||
|
|
||
| None. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jan 19, 2016
Member
I think that "no alternatives" may be a bit disingenuous here, you may want to at least mention that there's always at least a minor bikeshed around the naming, but there's also a few possible syntactical forms that this could take.
This comment has been minimized.
This comment has been minimized.
|
Updated. |
japaric
referenced this pull request
Feb 10, 2016
Closed
Symbols are removed from object file when optimizations are enabled #31531
arcnmx
referenced this pull request
Feb 21, 2016
Closed
rustc doesn't propagate custom link sections #31758
This comment has been minimized.
This comment has been minimized.
|
The tools team discussed this RFC yesterday and the current feeling is that we're likely to not merge this for now. While a number of possibilities have all been discussed here they all suffer from one complication or another unfortunately, and the general story around what symbols end up as what in Rust is relatively vague today as well (so it's tough to provide attributes to control them at an even finer grain). |
alexcrichton
added
the
final-comment-period
label
Jun 29, 2016
This comment has been minimized.
This comment has been minimized.
|
I don't have much opinion on this. It looks reasonable to me. |
This comment has been minimized.
This comment has been minimized.
|
I don't feel strongly whether we should merge or not, however, istm that most of the sentiment on the thread has been positive and that there is clearly some need for something in this space. So, if we don't merge, I think we should make some effort to spec the details that need to be spec'ed so that our symbol story is not "relatively vague" and we can then progress either merging this RFC or a new one. |
This comment has been minimized.
This comment has been minimized.
|
Ok, the tools team got a chance to talk about this RFC the other day, and the conclusion was that we're going to close this for now. Overall our symbol story is pretty vague today and is largely "best effort", so it's difficult to extend it as there's not already a set of documented guarantees. Additionally, once LTO is thrown into the mix, it adds quite a few complications to our symbol visibility story as well. This RFC is also lacking some details with the relationship to LTO and such, so it's not quite fully fleshed out as-is. Today we approximate symbol visibility on a "best-effort" kind of basis with In other words, though, we should have existing mechanisms to guarantee a symbols makes it to the linker such as:
Given all that, to merge an RFC like this we felt that there would want to be a more comprehensive design for our symbols story before adding pieces here and there, so closing. |
alexcrichton
closed this
Jul 14, 2016
frehberg
referenced this pull request
Aug 12, 2016
Closed
Pre-RFC: Rust version of `__attribute(used)__` (GCC) or `llvm.used` (LLVM). #1002
This was referenced Feb 20, 2017
This comment has been minimized.
This comment has been minimized.
|
I've send a PR implementing this in rust-lang/rust#39987. I'd like to hear about what use cases people have in mind for this (apart from the one mentioned in the PR description). Please leave a comment on that PR. |
mahkoh commentedJan 11, 2016
Add a
usedattribute to prevent symbols from being discarded.