Skip to content

Commit 389e842

Browse files
Auto merge of #141750 - Noratrieb:gold-rush, r=<try>
Warn when gold was used as the linker gold has been deprecated recently and is known to behave incorrectly around Rust programs, including miscompiling `#[used(linker)]`. Tell people to switch to a different linker instead. closes #141748 opening mostly for perf for now, but feel free to review r? bjorn3
2 parents e6152cd + 70950cc commit 389e842

File tree

1 file changed

+58
-0
lines changed
  • compiler/rustc_codegen_ssa/src/back

1 file changed

+58
-0
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ pub fn link_binary(
184184
);
185185
}
186186

187+
if sess.target.binary_format == BinaryFormat::Elf {
188+
if let Err(err) = warn_if_linked_with_gold(sess, &out_filename) {
189+
info!(?err, "Error while checking if gold was the linker");
190+
}
191+
}
192+
187193
if output.is_stdout() {
188194
if output.is_tty() {
189195
sess.dcx().emit_err(errors::BinaryOutputToTty {
@@ -3425,3 +3431,55 @@ fn add_lld_args(
34253431
}
34263432
}
34273433
}
3434+
3435+
// gold has been deprecated with binutils 2.44
3436+
// and is known to behave incorrectly around Rust programs.
3437+
// There have been reports of being unable to bootstrap with gold:
3438+
// https://github.com/rust-lang/rust/issues/139425
3439+
// Additionally, gold miscompiles SHF_GNU_RETAIN sections, which are
3440+
// emitted with `#[used(linker)]`.
3441+
fn warn_if_linked_with_gold(sess: &Session, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
3442+
fn elf_has_gold_version_note<'a>(
3443+
elf: &impl object::read::elf::FileHeader,
3444+
data: impl object::read::ReadRef<'a>,
3445+
) -> Result<bool, Box<dyn std::error::Error>> {
3446+
use object::read::elf::SectionHeader;
3447+
3448+
let endian = elf.endian()?;
3449+
3450+
let section =
3451+
elf.sections(endian, data)?.section_by_name(endian, b".note.gnu.gold-version");
3452+
if let Some((_, section)) = section {
3453+
if let Some(mut notes) = section.notes(endian, data)? {
3454+
return Ok(notes.any(|note| {
3455+
note.is_ok_and(|note| note.n_type(endian) == object::elf::NT_GNU_GOLD_VERSION)
3456+
}));
3457+
}
3458+
}
3459+
3460+
Ok(false)
3461+
}
3462+
3463+
use object::elf;
3464+
use object::read::elf::FileHeader;
3465+
3466+
let data = object::read::ReadCache::new(std::io::BufReader::new(std::fs::File::open(path)?));
3467+
3468+
let was_linked_with_gold = if sess.target.pointer_width == 64 {
3469+
let elf = elf::FileHeader64::<object::Endianness>::parse(&data)?;
3470+
elf_has_gold_version_note(elf, &data)?
3471+
} else if sess.target.pointer_width == 32 {
3472+
let elf = elf::FileHeader32::<object::Endianness>::parse(&data)?;
3473+
elf_has_gold_version_note(elf, &data)?
3474+
} else {
3475+
return Ok(());
3476+
};
3477+
3478+
if was_linked_with_gold {
3479+
let mut warn =
3480+
sess.dcx().struct_warn("the gold linker is deprecated and has known bugs with Rust");
3481+
warn.help("consider using LLD or ld from GNU binutils instead");
3482+
warn.emit();
3483+
}
3484+
Ok(())
3485+
}

0 commit comments

Comments
 (0)