@@ -3,7 +3,7 @@ mod raw_dylib;
3
3
use std:: collections:: BTreeSet ;
4
4
use std:: ffi:: OsString ;
5
5
use std:: fs:: { File , OpenOptions , read} ;
6
- use std:: io:: { BufWriter , Write } ;
6
+ use std:: io:: { BufReader , BufWriter , Write } ;
7
7
use std:: ops:: { ControlFlow , Deref } ;
8
8
use std:: path:: { Path , PathBuf } ;
9
9
use std:: process:: { Output , Stdio } ;
@@ -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 {
@@ -3375,3 +3381,54 @@ fn add_lld_args(
3375
3381
}
3376
3382
}
3377
3383
}
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