@@ -14,24 +14,21 @@ use rustc_session::utils::NativeLibKind;
1414/// need out of the shared crate context before we get rid of it.
1515use rustc_session:: { filesearch, Session } ;
1616use rustc_span:: symbol:: Symbol ;
17- use rustc_target:: abi:: Endian ;
1817use rustc_target:: spec:: crt_objects:: { CrtObjects , CrtObjectsFallback } ;
1918use rustc_target:: spec:: { LinkOutputKind , LinkerFlavor , LldFlavor , SplitDebuginfo } ;
2019use rustc_target:: spec:: { PanicStrategy , RelocModel , RelroLevel , SanitizerSet , Target } ;
2120
2221use super :: archive:: { find_library, ArchiveBuilder } ;
2322use super :: command:: Command ;
2423use super :: linker:: { self , Linker } ;
24+ use super :: metadata:: create_rmeta_file;
2525use super :: rpath:: { self , RPathConfig } ;
2626use crate :: {
2727 looks_like_rust_object_file, CodegenResults , CompiledModule , CrateInfo , NativeLib ,
2828 METADATA_FILENAME ,
2929} ;
3030
3131use cc:: windows_registry;
32- use object:: elf;
33- use object:: write:: Object ;
34- use object:: { Architecture , BinaryFormat , Endianness , FileFlags , SectionFlags , SectionKind } ;
3532use regex:: Regex ;
3633use tempfile:: Builder as TempFileBuilder ;
3734
@@ -339,7 +336,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
339336 // metadata in rlib files is wrapped in a "dummy" object file for
340337 // the target platform so the rlib can be processed entirely by
341338 // normal linkers for the platform.
342- let metadata = create_metadata_file ( sess, codegen_results. metadata . raw_data ( ) ) ;
339+ let metadata = create_rmeta_file ( sess, codegen_results. metadata . raw_data ( ) ) ;
343340 ab. add_file ( & emit_metadata ( sess, & metadata, tmpdir) ) ;
344341
345342 // After adding all files to the archive, we need to update the
@@ -358,136 +355,6 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
358355 }
359356 }
360357 return Ok ( ab) ;
361-
362- // For rlibs we "pack" rustc metadata into a dummy object file. When rustc
363- // creates a dylib crate type it will pass `--whole-archive` (or the
364- // platform equivalent) to include all object files from an rlib into the
365- // final dylib itself. This causes linkers to iterate and try to include all
366- // files located in an archive, so if metadata is stored in an archive then
367- // it needs to be of a form that the linker will be able to process.
368- //
369- // Note, though, that we don't actually want this metadata to show up in any
370- // final output of the compiler. Instead this is purely for rustc's own
371- // metadata tracking purposes.
372- //
373- // With the above in mind, each "flavor" of object format gets special
374- // handling here depending on the target:
375- //
376- // * MachO - macos-like targets will insert the metadata into a section that
377- // is sort of fake dwarf debug info. Inspecting the source of the macos
378- // linker this causes these sections to be skipped automatically because
379- // it's not in an allowlist of otherwise well known dwarf section names to
380- // go into the final artifact.
381- //
382- // * WebAssembly - we actually don't have any container format for this
383- // target. WebAssembly doesn't support the `dylib` crate type anyway so
384- // there's no need for us to support this at this time. Consequently the
385- // metadata bytes are simply stored as-is into an rlib.
386- //
387- // * COFF - Windows-like targets create an object with a section that has
388- // the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker
389- // ever sees the section it doesn't process it and it's removed.
390- //
391- // * ELF - All other targets are similar to Windows in that there's a
392- // `SHF_EXCLUDE` flag we can set on sections in an object file to get
393- // automatically removed from the final output.
394- //
395- // Note that this metdata format is kept in sync with
396- // `rustc_codegen_ssa/src/back/metadata.rs`.
397- fn create_metadata_file ( sess : & Session , metadata : & [ u8 ] ) -> Vec < u8 > {
398- let endianness = match sess. target . options . endian {
399- Endian :: Little => Endianness :: Little ,
400- Endian :: Big => Endianness :: Big ,
401- } ;
402- let architecture = match & sess. target . arch [ ..] {
403- "arm" => Architecture :: Arm ,
404- "aarch64" => Architecture :: Aarch64 ,
405- "x86" => Architecture :: I386 ,
406- "s390x" => Architecture :: S390x ,
407- "mips" => Architecture :: Mips ,
408- "mips64" => Architecture :: Mips64 ,
409- "x86_64" => {
410- if sess. target . pointer_width == 32 {
411- Architecture :: X86_64_X32
412- } else {
413- Architecture :: X86_64
414- }
415- }
416- "powerpc" => Architecture :: PowerPc ,
417- "powerpc64" => Architecture :: PowerPc64 ,
418- "riscv32" => Architecture :: Riscv32 ,
419- "riscv64" => Architecture :: Riscv64 ,
420- "sparc64" => Architecture :: Sparc64 ,
421-
422- // This is used to handle all "other" targets. This includes targets
423- // in two categories:
424- //
425- // * Some targets don't have support in the `object` crate just yet
426- // to write an object file. These targets are likely to get filled
427- // out over time.
428- //
429- // * Targets like WebAssembly don't support dylibs, so the purpose
430- // of putting metadata in object files, to support linking rlibs
431- // into dylibs, is moot.
432- //
433- // In both of these cases it means that linking into dylibs will
434- // not be supported by rustc. This doesn't matter for targets like
435- // WebAssembly and for targets not supported by the `object` crate
436- // yet it means that work will need to be done in the `object` crate
437- // to add a case above.
438- _ => return metadata. to_vec ( ) ,
439- } ;
440-
441- if sess. target . is_like_osx {
442- let mut file = Object :: new ( BinaryFormat :: MachO , architecture, endianness) ;
443-
444- let section =
445- file. add_section ( b"__DWARF" . to_vec ( ) , b".rmeta" . to_vec ( ) , SectionKind :: Debug ) ;
446- file. append_section_data ( section, metadata, 1 ) ;
447- file. write ( ) . unwrap ( )
448- } else if sess. target . is_like_windows {
449- const IMAGE_SCN_LNK_REMOVE : u32 = 0 ;
450- let mut file = Object :: new ( BinaryFormat :: Coff , architecture, endianness) ;
451-
452- let section = file. add_section ( Vec :: new ( ) , b".rmeta" . to_vec ( ) , SectionKind :: Debug ) ;
453- file. section_mut ( section) . flags =
454- SectionFlags :: Coff { characteristics : IMAGE_SCN_LNK_REMOVE } ;
455- file. append_section_data ( section, metadata, 1 ) ;
456- file. write ( ) . unwrap ( )
457- } else {
458- const SHF_EXCLUDE : u64 = 0x80000000 ;
459- let mut file = Object :: new ( BinaryFormat :: Elf , architecture, endianness) ;
460-
461- match & sess. target . arch [ ..] {
462- // copied from `mipsel-linux-gnu-gcc foo.c -c` and
463- // inspecting the resulting `e_flags` field.
464- "mips" => {
465- let e_flags = elf:: EF_MIPS_ARCH_32R2 | elf:: EF_MIPS_CPIC | elf:: EF_MIPS_PIC ;
466- file. flags = FileFlags :: Elf { e_flags } ;
467- }
468- // copied from `mips64el-linux-gnuabi64-gcc foo.c -c`
469- "mips64" => {
470- let e_flags = elf:: EF_MIPS_ARCH_64R2 | elf:: EF_MIPS_CPIC | elf:: EF_MIPS_PIC ;
471- file. flags = FileFlags :: Elf { e_flags } ;
472- }
473-
474- // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though
475- // that the `+d` target feature represents whether the double
476- // float abi is enabled.
477- "riscv64" if sess. target . options . features . contains ( "+d" ) => {
478- let e_flags = elf:: EF_RISCV_RVC | elf:: EF_RISCV_FLOAT_ABI_DOUBLE ;
479- file. flags = FileFlags :: Elf { e_flags } ;
480- }
481-
482- _ => { }
483- }
484-
485- let section = file. add_section ( Vec :: new ( ) , b".rmeta" . to_vec ( ) , SectionKind :: Debug ) ;
486- file. section_mut ( section) . flags = SectionFlags :: Elf { sh_flags : SHF_EXCLUDE } ;
487- file. append_section_data ( section, metadata, 1 ) ;
488- file. write ( ) . unwrap ( )
489- }
490- }
491358}
492359
493360/// Extract all symbols defined in raw-dylib libraries, collated by library name.
0 commit comments