@@ -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