rustc: Fix wasm64 metadata object files · rust-lang/rust@646e8e7 (original) (raw)

1

1

`//! Reading of the rustc metadata for rlibs and dylibs

`

2

2

``

``

3

`+

use std::borrow::Cow;

`

3

4

`use std::fs::File;

`

4

5

`use std::io::Write;

`

5

6

`use std::path::Path;

`

`@@ -15,7 +16,6 @@ use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};

`

15

16

`use rustc_metadata::creader::MetadataLoader;

`

16

17

`use rustc_metadata::fs::METADATA_FILENAME;

`

17

18

`use rustc_metadata::EncodedMetadata;

`

18

``

`-

use rustc_serialize::leb128;

`

19

19

`use rustc_session::Session;

`

20

20

`use rustc_span::sym;

`

21

21

`use rustc_target::abi::Endian;

`

`@@ -434,12 +434,15 @@ pub enum MetadataPosition {

`

434

434

`/// automatically removed from the final output.

`

435

435

`pub fn create_wrapper_file(

`

436

436

`sess: &Session,

`

437

``

`-

section_name: Vec,

`

``

437

`+

section_name: String,

`

438

438

`data: &[u8],

`

439

439

`) -> (Vec, MetadataPosition) {

`

440

440

`let Some(mut file) = create_object_file(sess) else {

`

441

441

`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

`+

);

`

443

446

`}

`

444

447

``

445

448

`// Targets using this branch don't have support implemented here yet or

`

`@@ -452,7 +455,7 @@ pub fn create_wrapper_file(

`

452

455

`} else {

`

453

456

` file.add_section(

`

454

457

` file.segment_name(StandardSegment::Debug).to_vec(),

`

455

``

`-

section_name,

`

``

458

`+

section_name.into_bytes(),

`

456

459

`SectionKind::Debug,

`

457

460

`)

`

458

461

`};

`

`@@ -524,7 +527,7 @@ pub fn create_compressed_metadata_file(

`

524

527

``

525

528

`let Some(mut file) = create_object_file(sess) else {

`

526

529

`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");

`

528

531

`}

`

529

532

`return packed_metadata.to_vec();

`

530

533

`};

`

`@@ -624,51 +627,41 @@ pub fn create_compressed_metadata_file_for_xcoff(

`

624

627

`` /// data.

``

625

628

`///

`

626

629

`` /// 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.

`

629

632

`///

`

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

`

642

634

`/// 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.

`

647

638

`///

`

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 {

`

650

``

`-

let mut bytes = b"\0asm\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::()];

`

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::()];

`

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 {

`

``

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 },

`

661

655

`);

`

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

`+

}

`

670

657

``

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()

`

674

667

`}

`