@@ -184,6 +184,12 @@ pub fn link_binary(
184
184
) ;
185
185
}
186
186
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
+
187
193
if output. is_stdout ( ) {
188
194
if output. is_tty ( ) {
189
195
sess. dcx ( ) . emit_err ( errors:: BinaryOutputToTty {
@@ -3425,3 +3431,59 @@ fn add_lld_args(
3425
3431
}
3426
3432
}
3427
3433
}
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
+ use object:: elf;
3443
+ use object:: read:: elf:: FileHeader ;
3444
+
3445
+ let data = std:: fs:: read ( path) ?;
3446
+
3447
+ let was_linked_with_gold = if sess. target . pointer_width == 64 {
3448
+ let elf = elf:: FileHeader64 :: < object:: Endianness > :: parse ( & * data) ?;
3449
+ elf_has_gold_version_note ( elf, & data)
3450
+ } else if sess. target . pointer_width == 32 {
3451
+ let elf = elf:: FileHeader32 :: < object:: Endianness > :: parse ( & * data) ?;
3452
+ elf_has_gold_version_note ( elf, & data)
3453
+ } else {
3454
+ return Ok ( ( ) ) ;
3455
+ } ;
3456
+
3457
+ match was_linked_with_gold {
3458
+ Ok ( true ) => {
3459
+ let mut warn = sess
3460
+ . dcx ( )
3461
+ . struct_warn ( "the gold linker is deprecated and has known bugs with Rust" ) ;
3462
+ warn. help ( "consider using LLD or ld from GNU binutils instead" ) ;
3463
+ warn. emit ( ) ;
3464
+ }
3465
+ Ok ( false ) => { }
3466
+ Err ( err) => info ! ( ?err, "Error while trying to detect whether binary was linked with gold" ) ,
3467
+ }
3468
+ Ok ( ( ) )
3469
+ }
3470
+
3471
+ fn elf_has_gold_version_note (
3472
+ elf : & impl object:: read:: elf:: FileHeader ,
3473
+ data : & [ u8 ] ,
3474
+ ) -> Result < bool , Box < dyn std:: error:: Error > > {
3475
+ use object:: read:: elf:: SectionHeader ;
3476
+
3477
+ let endian = elf. endian ( ) ?;
3478
+
3479
+ let section = elf. sections ( endian, data) ?. section_by_name ( endian, b".note.gnu.gold-version" ) ;
3480
+ if let Some ( ( _, section) ) = section {
3481
+ if let Some ( mut notes) = section. notes ( endian, data) ? {
3482
+ return Ok ( notes. any ( |note| {
3483
+ note. is_ok_and ( |note| note. n_type ( endian) == object:: elf:: NT_GNU_GOLD_VERSION )
3484
+ } ) ) ;
3485
+ }
3486
+ }
3487
+
3488
+ Ok ( false )
3489
+ }
0 commit comments