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, §ion_name), MetadataPosition::First);
`
``
442
`+
return (
`
``
443
`+
create_metadata_file_for_wasm(sess, data, §ion_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 = §ion_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 = §ion_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
`}
`