Skip to content

Commit 99426c5

Browse files
committed
Auto merge of #141750 - Noratrieb:gold-rush, r=bjorn3
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 r? bjorn3
2 parents 5d707b0 + ba5a744 commit 99426c5

File tree

1 file changed

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

1 file changed

+58
-1
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod raw_dylib;
33
use std::collections::BTreeSet;
44
use std::ffi::OsString;
55
use std::fs::{File, OpenOptions, read};
6-
use std::io::{BufWriter, Write};
6+
use std::io::{BufReader, BufWriter, Write};
77
use std::ops::{ControlFlow, Deref};
88
use std::path::{Path, PathBuf};
99
use std::process::{Output, Stdio};
@@ -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 {
@@ -3375,3 +3381,54 @@ fn add_lld_args(
33753381
}
33763382
}
33773383
}
3384+
3385+
// gold has been deprecated with binutils 2.44
3386+
// and is known to behave incorrectly around Rust programs.
3387+
// There have been reports of being unable to bootstrap with gold:
3388+
// https://github.com/rust-lang/rust/issues/139425
3389+
// Additionally, gold miscompiles SHF_GNU_RETAIN sections, which are
3390+
// emitted with `#[used(linker)]`.
3391+
fn warn_if_linked_with_gold(sess: &Session, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
3392+
use object::read::elf::{FileHeader, SectionHeader};
3393+
use object::read::{ReadCache, ReadRef, Result};
3394+
use object::{Endianness, elf};
3395+
3396+
fn elf_has_gold_version_note<'a>(
3397+
elf: &impl FileHeader,
3398+
data: impl ReadRef<'a>,
3399+
) -> Result<bool> {
3400+
let endian = elf.endian()?;
3401+
3402+
let section =
3403+
elf.sections(endian, data)?.section_by_name(endian, b".note.gnu.gold-version");
3404+
if let Some((_, section)) = section {
3405+
if let Some(mut notes) = section.notes(endian, data)? {
3406+
return Ok(notes.any(|note| {
3407+
note.is_ok_and(|note| note.n_type(endian) == elf::NT_GNU_GOLD_VERSION)
3408+
}));
3409+
}
3410+
}
3411+
3412+
Ok(false)
3413+
}
3414+
3415+
let data = ReadCache::new(BufReader::new(File::open(path)?));
3416+
3417+
let was_linked_with_gold = if sess.target.pointer_width == 64 {
3418+
let elf = elf::FileHeader64::<Endianness>::parse(&data)?;
3419+
elf_has_gold_version_note(elf, &data)?
3420+
} else if sess.target.pointer_width == 32 {
3421+
let elf = elf::FileHeader32::<Endianness>::parse(&data)?;
3422+
elf_has_gold_version_note(elf, &data)?
3423+
} else {
3424+
return Ok(());
3425+
};
3426+
3427+
if was_linked_with_gold {
3428+
let mut warn =
3429+
sess.dcx().struct_warn("the gold linker is deprecated and has known bugs with Rust");
3430+
warn.help("consider using LLD or ld from GNU binutils instead");
3431+
warn.emit();
3432+
}
3433+
Ok(())
3434+
}

0 commit comments

Comments
 (0)