Only compile #[used] as llvm.compiler.used for ELF targets

This commit is contained in:
Thom Chiovoloni 2022-02-06 13:51:11 -08:00
parent ecd44958e0
commit 54133cfcf4
No known key found for this signature in database
GPG Key ID: E2EFD4309E11C8A8
2 changed files with 36 additions and 4 deletions

View File

@ -535,11 +535,41 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
// The semantics of #[used] in Rust only require the symbol to make it into the
// object file. It is explicitly allowed for the linker to strip the symbol if it
// is dead. As such, use llvm.compiler.used instead of llvm.used.
// is dead, which means we are allowed use `llvm.compiler.used` instead of
// `llvm.used` here.
//
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
// in some versions of the gold linker.
// in the handling of `.init_array` (the static constructor list) in versions of
// the gold linker (prior to the one released with binutils 2.36).
//
// However, unconditional use of `llvm.compiler.used` caused a nontrivial amount of
// ecosystem breakage, especially on Mach-O targets. To resolve this, we compile it
// as llvm.used on ELF targets and llvm.compiler.used elsewhere, which and should be
// equivalent to how we compiled `#[used]` before LLVM 13, as `llvm.used` and
// `llvm.compiler.used` were treated the same on ELF targets prior in earlier LLVM
// versions (additionally, it seems to be how Clang handles `__attribute__((used))`,
// perhaps for similar compatibility-motivated reasons).
//
// See https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146 and
// following comments for some discussion of this.
//
// The final wrinkle is it's not really clear how to tell if we're going to output
// ELF, so it's been approximated as "not like wasm, osx, or windows", which is
// not exactly correct, but is pretty close and hopefully handles all the platforms
// platforms where old versions of `ld.gold` are likely to show up.
//
// All this is subject to change in the future. Which is a good thing, because this
// probably should be firmed up somehow!
let seems_like_elf = !(self.tcx.sess.target.is_like_osx
|| self.tcx.sess.target.is_like_windows
|| self.tcx.sess.target.is_like_wasm);
if seems_like_elf {
self.add_compiler_used_global(g);
} else {
self.add_used_global(g);
}
}
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
// `USED` and `USED_LINKER` can't be used together.

View File

@ -13,7 +13,9 @@ pub trait StaticMethods: BackendTypes {
/// Same as add_used_global(), but only prevent the compiler from potentially removing an
/// otherwise unused symbol. The linker is still permitted to drop it.
///
/// This corresponds to the semantics of the `#[used]` attribute.
/// This corresponds to the documented semantics of the `#[used]` attribute, although
/// on some targets (non-ELF), we may use `add_used_global` for `#[used]` statics
/// instead.
fn add_compiler_used_global(&self, global: Self::Value);
}