11//! Reading of the rustc metadata for rlibs and dylibs
22
3+ use std:: borrow:: Cow ;
34use std:: fs:: File ;
45use std:: io:: Write ;
56use std:: path:: Path ;
@@ -15,7 +16,6 @@ use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
1516use rustc_metadata:: creader:: MetadataLoader ;
1617use rustc_metadata:: fs:: METADATA_FILENAME ;
1718use rustc_metadata:: EncodedMetadata ;
18- use rustc_serialize:: leb128;
1919use rustc_session:: Session ;
2020use rustc_span:: sym;
2121use rustc_target:: abi:: Endian ;
@@ -434,12 +434,15 @@ pub enum MetadataPosition {
434434/// automatically removed from the final output.
435435pub fn create_wrapper_file (
436436 sess : & Session ,
437- section_name : Vec < u8 > ,
437+ section_name : String ,
438438 data : & [ u8 ] ,
439439) -> ( Vec < u8 > , MetadataPosition ) {
440440 let Some ( mut file) = create_object_file ( sess) else {
441441 if sess. target . is_like_wasm {
442- return ( create_metadata_file_for_wasm ( data, & section_name) , MetadataPosition :: First ) ;
442+ return (
443+ create_metadata_file_for_wasm ( sess, data, & section_name) ,
444+ MetadataPosition :: First ,
445+ ) ;
443446 }
444447
445448 // Targets using this branch don't have support implemented here yet or
@@ -452,7 +455,7 @@ pub fn create_wrapper_file(
452455 } else {
453456 file. add_section (
454457 file. segment_name ( StandardSegment :: Debug ) . to_vec ( ) ,
455- section_name,
458+ section_name. into_bytes ( ) ,
456459 SectionKind :: Debug ,
457460 )
458461 } ;
@@ -524,7 +527,7 @@ pub fn create_compressed_metadata_file(
524527
525528 let Some ( mut file) = create_object_file ( sess) else {
526529 if sess. target . is_like_wasm {
527- return create_metadata_file_for_wasm ( & packed_metadata, b ".rustc") ;
530+ return create_metadata_file_for_wasm ( sess , & packed_metadata, ".rustc" ) ;
528531 }
529532 return packed_metadata. to_vec ( ) ;
530533 } ;
@@ -624,51 +627,41 @@ pub fn create_compressed_metadata_file_for_xcoff(
624627/// `data`.
625628///
626629/// NB: the `object` crate does not yet have support for writing the wasm
627- /// object file format. The format is simple enough that for now an extra crate
628- /// from crates.io (such as ` wasm-encoder`). The file format is:
630+ /// object file format. In lieu of that the `wasm-encoder` crate is used to
631+ /// build a wasm file by hand.
629632///
630- /// * 4-byte header "\0asm"
631- /// * 4-byte version number - 1u32 in little-endian format
632- /// * concatenated sections, which for this object is always "custom sections"
633- ///
634- /// Custom sections are then defined by:
635- /// * 1-byte section identifier - 0 for a custom section
636- /// * leb-encoded section length (size of the contents beneath this bullet)
637- /// * leb-encoded custom section name length
638- /// * custom section name
639- /// * section contents
640- ///
641- /// One custom section, `linking`, is added here in accordance with
633+ /// The wasm object file format is defined at
642634/// <https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md>
643- /// which is required to inform LLD that this is an object file but it should
644- /// otherwise basically ignore it if it otherwise looks at it. The linking
645- /// section currently is defined by a single version byte (2) and then further
646- /// sections, but we have no more sections, so it's just the byte "2".
635+ /// and mainly consists of a `linking` custom section. In this case the custom
636+ /// section there is empty except for a version marker indicating what format
637+ /// it's in.
647638///
648- /// The next custom section is the one we're interested in.
649- pub fn create_metadata_file_for_wasm ( data : & [ u8 ] , section_name : & [ u8 ] ) -> Vec < u8 > {
650- let mut bytes = b"\0 asm\x01 \0 \0 \0 " . to_vec ( ) ;
651-
652- let mut append_custom_section = |section_name : & [ u8 ] , data : & [ u8 ] | {
653- let mut section_name_len = [ 0 ; leb128:: max_leb128_len :: < usize > ( ) ] ;
654- let off = leb128:: write_usize_leb128 ( & mut section_name_len, section_name. len ( ) ) ;
655- let section_name_len = & section_name_len[ ..off] ;
656-
657- let mut section_len = [ 0 ; leb128:: max_leb128_len :: < usize > ( ) ] ;
658- let off = leb128:: write_usize_leb128 (
659- & mut section_len,
660- data. len ( ) + section_name_len. len ( ) + section_name. len ( ) ,
639+ /// The main purpose of this is to contain a custom section with `section_name`,
640+ /// which is then appended after `linking`.
641+ ///
642+ /// As a further detail the object needs to have a 64-bit memory if `wasm64` is
643+ /// the target or otherwise it's interpreted as a 32-bit object which is
644+ /// incompatible with 64-bit ones.
645+ pub fn create_metadata_file_for_wasm ( sess : & Session , data : & [ u8 ] , section_name : & str ) -> Vec < u8 > {
646+ assert ! ( sess. target. is_like_wasm) ;
647+ let mut module = wasm_encoder:: Module :: new ( ) ;
648+ let mut imports = wasm_encoder:: ImportSection :: new ( ) ;
649+
650+ if sess. target . pointer_width == 64 {
651+ imports. import (
652+ "env" ,
653+ "__linear_memory" ,
654+ wasm_encoder:: MemoryType { minimum : 0 , maximum : None , memory64 : true , shared : false } ,
661655 ) ;
662- let section_len = & section_len[ ..off] ;
663-
664- bytes. push ( 0u8 ) ;
665- bytes. extend_from_slice ( section_len) ;
666- bytes. extend_from_slice ( section_name_len) ;
667- bytes. extend_from_slice ( section_name) ;
668- bytes. extend_from_slice ( data) ;
669- } ;
656+ }
670657
671- append_custom_section ( b"linking" , & [ 2 ] ) ;
672- append_custom_section ( section_name, data) ;
673- bytes
658+ if imports. len ( ) > 0 {
659+ module. section ( & imports) ;
660+ }
661+ module. section ( & wasm_encoder:: CustomSection {
662+ name : "linking" . into ( ) ,
663+ data : Cow :: Borrowed ( & [ 2 ] ) ,
664+ } ) ;
665+ module. section ( & wasm_encoder:: CustomSection { name : section_name. into ( ) , data : data. into ( ) } ) ;
666+ module. finish ( )
674667}
0 commit comments