Skip to content

Make #[used(linker)] the default on ELF too #140872

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bjorn3
Copy link
Member

@bjorn3 bjorn3 commented May 9, 2025

#[used] currently is an alias for #[used(linker)] on all platforms except ELF based ones where it is an alias for #[used(compiler)]. The latter has surprising behavior and the LLVM LangRef explicitly states that it "should only be used in rare circumstances, and should not be exposed to source languages." 1

The reason #[used] still was an alias to #[used(compiler)] on ELF is because the gold linker has issues with it. Luckily gold has been deprecated with GCC 15 2 and seems to be unable to bootstrap rustc anyway 3. As such we shouldn't really care about supporting gold.

This would also allow re-enabling start-stop-gc with lld.

cc #93798
Likely fixes #85045

Footnotes

  1. https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable

  2. https://lists.gnu.org/archive/html/info-gnu/2025-02/msg00001.html

  3. https://github.com/rust-lang/rust/issues/139425

@rustbot
Copy link
Collaborator

rustbot commented May 9, 2025

r? @nnethercote

rustbot has assigned @nnethercote.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 9, 2025
@rustbot
Copy link
Collaborator

rustbot commented May 9, 2025

Some changes occurred in compiler/rustc_codegen_ssa

cc @WaffleLapkin

Some changes occurred in compiler/rustc_codegen_ssa/src/codegen_attrs.rs

cc @jdonszelmann

@bjorn3 bjorn3 added A-linkage Area: linking into static, shared libraries and binaries F-used_with_arg `#![feature(used_with_arg)]` labels May 9, 2025
@bjorn3
Copy link
Member Author

bjorn3 commented May 9, 2025

cg_clif currently treats #[used(linker)] as #[used(compiler)] (bytecodealliance/wasmtime#10758), but I don't think that should be a blocker for this PR.

@nnethercote
Copy link
Contributor

Looks ok to me, but as this is the first I've heard of these attributes, I will run it past the person who first suggested them:

r? @nikic

@rustbot rustbot assigned nikic and unassigned nnethercote May 21, 2025
@nikic
Copy link
Contributor

nikic commented May 21, 2025

This generally sounds reasonable to me in the interest of having consistent behavior across platforms. Some questions:

  • What is the interaction of this with symbols.o? I have a vague understanding that symbols.o already gets us this behavior in most cases, but maybe I'm wrong about that. (Was that only about making sure the symbols get pulled in at all from archives?)
  • IIRC one of the issues was that SHF_RETAIN is a new flag. While only gold was actively miscompiling it at the time, there was still the issue that non-bleeding-edge linkers wouldn't actually support it, giving you different behavior depending on how new your linker is. I guess the situation here is somewhat better now.
  • I assume the intention here is that this is still just an implementation detail, and the guarantee continues to only be the #[used(compiler)] behavior?
  • There seems to be some doubt on Linking to a static library does not always include exported symbols #99721 whether this PR would actually fix it. Can we have a test (run-make presumably?) for it? Or at least we should make sure the "likely" fixes don't auto-close.

@bjorn3
Copy link
Member Author

bjorn3 commented May 21, 2025

What is the interaction of this with symbols.o? I have a vague understanding that symbols.o already gets us this behavior in most cases, but maybe I'm wrong about that. (Was that only about making sure the symbols get pulled in at all from archives?)

symbols.o only ensures that the object file containing the symbol is pulled in from an archive. It does nothing to stop --gc-sections from removing a static if the linker believes it to be unused. #[used(linker)] however ensures that the linker will keep it even if it isn't referenced.

I assume the intention here is that this is still just an implementation detail, and the guarantee continues to only be the #[used(compiler)] behavior?

I want to guarantee the #[used(linker)] behavior as soon as we are confident that the this PR doesn't regress anything.

@lqd
Copy link
Member

lqd commented May 21, 2025

This would also allow re-enabling start-stop-gc with lld.

It would at least remove the main reason why we introduced -znostart-stop-gc, as this PR would of course fix linkme with lld.

@bjorn3
Copy link
Member Author

bjorn3 commented May 21, 2025

IIRC one of the issues was that SHF_RETAIN is a new flag. While only gold was actively miscompiling it at the time, there was still the issue that non-bleeding-edge linkers wouldn't actually support it, giving you different behavior depending on how new your linker is. I guess the situation here is somewhat better now.

SHF_GNU_RETAIN is a lot newer than I thought. It was only introduced in 2021 with binutils 2.36. I guess that means we can't make it a hard guarantee for now. We can stop passing -znostart-stop-gc for rust-lld however as we know the LLD version we ship is new enough to support it.

@bors
Copy link
Collaborator

bors commented May 25, 2025

☔ The latest upstream changes (presumably #141518) made this pull request unmergeable. Please resolve the merge conflicts.

#[used] currently is an alias for #[used(linker)] on all platforms
except ELF based ones where it is an alias for #[used(compiler)]. The
latter has surprising behavior and the LLVM LangRef explicitly states
that it "should only be used in rare circumstances, and should not be
exposed to source languages."

The reason #[used] still was an alias to #[used(compiler)] on ELF is
because the gold linker has issues with it. Luckily gold has been
deprecated with GCC 15 and seems to be unable to bootstrap rustc anyway.
As such we shouldn't really care about supporting gold.
@Noratrieb
Copy link
Member

Noratrieb commented May 29, 2025

I did some investigation on the history of SHF_GNU_RETAIN and its interactions with GCC.
It was proposed in 2020 on the linked mails in https://sourceware.org/pipermail/binutils/2020-November/113993.html.

Originally, the previously existing C-equivalent of #[used], __attribute__((used)) was changed to imply SHF_GNU_RETAIN (https://gcc.gnu.org/pipermail/gcc-patches/2020-October/555594.html, https://gcc.gnu.org/pipermail/gcc-patches/2020-November/557906.html). Additionally, __attribute__((retain)) was proposed to only apply SHF_GNU_RETAIN. Since SHF_GNU_RETAIN was a section flag (and linker GC happens on the section level), __attribute__((used)) was changed such that the symbol was put in a -fdata-sections-like new section with the flag applied.

It was then discovered that this behavior broke projects, like the Linux kernel (https://gcc.gnu.org/pipermail/gcc-patches/2021-February/565337.html). The reason for that was that they already used __attribute__((used)) but their linker scripts did not support the symbols ending up in these new sections. The general consensus on the mailing list appeared to have been that it would have been nice to make __attribute__((used)) apply SHF_GNU_RETAIN as well.

So what does that mean for Rust? Since we always use the equivalent of -fdata-sections (funnily enough there's -Zfunction-sections to disable -ffunction-sections but no equivalent of -fdata-sections) this breakage is not a concern for us. So this does indeed seem safe to go ahead.

I've opened #141750 to see whether it's possible to warn about the potential miscompiles with gold.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-linkage Area: linking into static, shared libraries and binaries F-used_with_arg `#![feature(used_with_arg)]` S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

#[link_section] does not work in libraries on release
7 participants