From 78cb5cab00c04f1d698b6776ef9d878ea0cdffae Mon Sep 17 00:00:00 2001 From: Arshia Ghafoori Date: Fri, 15 Aug 2025 18:02:57 +0400 Subject: [PATCH] Add support for the WASM_DYLINK_RUNTIME_PATH subsection of the dylink.0 custom section --- crates/wasmparser/src/readers/core/dylink0.rs | 7 +++++++ crates/wasmprinter/src/lib.rs | 9 +++++++++ crates/wast/src/core/binary.rs | 1 + crates/wast/src/core/custom.rs | 9 +++++++++ crates/wast/src/lib.rs | 1 + crates/wit-component/src/linking/metadata.rs | 7 +++++++ tests/cli/dump-dylink0.wat | 1 + tests/cli/dump-dylink0.wat.stdout | 6 ++++-- tests/cli/dylink0.wast | 1 + tests/snapshots/cli/dylink0.wast.json | 4 ++-- tests/snapshots/cli/dylink0.wast/6.print | 1 + 11 files changed, 43 insertions(+), 4 deletions(-) diff --git a/crates/wasmparser/src/readers/core/dylink0.rs b/crates/wasmparser/src/readers/core/dylink0.rs index 7e92fac882..97917d6fbf 100644 --- a/crates/wasmparser/src/readers/core/dylink0.rs +++ b/crates/wasmparser/src/readers/core/dylink0.rs @@ -12,6 +12,7 @@ const WASM_DYLINK_MEM_INFO: u8 = 1; const WASM_DYLINK_NEEDED: u8 = 2; const WASM_DYLINK_EXPORT_INFO: u8 = 3; const WASM_DYLINK_IMPORT_INFO: u8 = 4; +const WASM_DYLINK_RUNTIME_PATH: u8 = 5; /// Represents a `WASM_DYLINK_MEM_INFO` field #[derive(Debug, Copy, Clone)] @@ -56,6 +57,7 @@ pub enum Dylink0Subsection<'a> { Needed(Vec<&'a str>), ExportInfo(Vec>), ImportInfo(Vec>), + RuntimePath(Vec<&'a str>), Unknown { ty: u8, data: &'a [u8], @@ -100,6 +102,11 @@ impl<'a> Subsection<'a> for Dylink0Subsection<'a> { }) .collect::>()?, ), + WASM_DYLINK_RUNTIME_PATH => Self::RuntimePath( + (0..reader.read_var_u32()?) + .map(|_| reader.read_string()) + .collect::>()?, + ), ty => Self::Unknown { ty, data, diff --git a/crates/wasmprinter/src/lib.rs b/crates/wasmprinter/src/lib.rs index d65d6fc3fb..889c7797ac 100644 --- a/crates/wasmprinter/src/lib.rs +++ b/crates/wasmprinter/src/lib.rs @@ -2006,6 +2006,15 @@ impl Printer<'_, '_> { self.end_group()?; } } + Dylink0Subsection::RuntimePath(runtime_path) => { + self.newline(start)?; + self.start_group("runtime-path")?; + for s in runtime_path { + self.result.write_str(" ")?; + self.print_str(s)?; + } + self.end_group()?; + } Dylink0Subsection::Unknown { ty, .. } => { bail!("don't know how to print dylink.0 subsection id {ty}"); } diff --git a/crates/wast/src/core/binary.rs b/crates/wast/src/core/binary.rs index 98dd2c3ef9..cc27b92c99 100644 --- a/crates/wast/src/core/binary.rs +++ b/crates/wast/src/core/binary.rs @@ -1392,6 +1392,7 @@ impl Encode for Dylink0Subsection<'_> { Dylink0Subsection::Needed(libs) => libs.encode(e), Dylink0Subsection::ExportInfo(list) => list.encode(e), Dylink0Subsection::ImportInfo(list) => list.encode(e), + Dylink0Subsection::RuntimePath(list) => list.encode(e), } } } diff --git a/crates/wast/src/core/custom.rs b/crates/wast/src/core/custom.rs index 2205bf514c..938f749e1e 100644 --- a/crates/wast/src/core/custom.rs +++ b/crates/wast/src/core/custom.rs @@ -261,6 +261,7 @@ pub enum Dylink0Subsection<'a> { Needed(Vec<&'a str>), ExportInfo(Vec<(&'a str, u32)>), ImportInfo(Vec<(&'a str, &'a str, u32)>), + RuntimePath(Vec<&'a str>), } impl<'a> Parse<'a> for Dylink0<'a> { @@ -335,6 +336,13 @@ impl<'a> Dylink0<'a> { .subsections .push(Dylink0Subsection::ImportInfo(vec![(module, name, flags)])), } + } else if l.peek::()? { + parser.parse::()?; + let mut names = Vec::new(); + while !parser.is_empty() { + names.push(parser.parse()?); + } + self.subsections.push(Dylink0Subsection::RuntimePath(names)); } else { return Err(l.error()); } @@ -388,6 +396,7 @@ impl Dylink0Subsection<'_> { Needed(..) => 2, ExportInfo(..) => 3, ImportInfo(..) => 4, + RuntimePath(..) => 5, } } } diff --git a/crates/wast/src/lib.rs b/crates/wast/src/lib.rs index ee2e662267..d1fdbe6380 100644 --- a/crates/wast/src/lib.rs +++ b/crates/wast/src/lib.rs @@ -555,6 +555,7 @@ pub mod kw { custom_keyword!(needed); custom_keyword!(export_info = "export-info"); custom_keyword!(import_info = "import-info"); + custom_keyword!(runtime_path = "runtime-path"); custom_keyword!(thread); custom_keyword!(thread_spawn_ref = "thread.spawn_ref"); custom_keyword!(thread_spawn_indirect = "thread.spawn_indirect"); diff --git a/crates/wit-component/src/linking/metadata.rs b/crates/wit-component/src/linking/metadata.rs index eab6e33f3f..4ae5dda1c7 100644 --- a/crates/wit-component/src/linking/metadata.rs +++ b/crates/wit-component/src/linking/metadata.rs @@ -169,6 +169,9 @@ pub struct Metadata<'a> { /// The `WASM_DYLINK_NEEDED` values, if any pub needed_libs: Vec<&'a str>, + /// The `WASM_DYLINK_RUNTIME_PATH` values, if any + pub runtime_path: Vec<&'a str>, + /// Whether this module exports `__wasm_apply_data_relocs` pub has_data_relocs: bool, @@ -228,6 +231,7 @@ impl<'a> Metadata<'a> { table_alignment: 1, }, needed_libs: Vec::new(), + runtime_path: Vec::new(), has_data_relocs: false, has_ctors: false, has_initialize: false, @@ -267,6 +271,9 @@ impl<'a> Metadata<'a> { .map(|info| ((info.module, info.field), info.flags)), ); } + Dylink0Subsection::RuntimePath(runtime_path) => { + result.runtime_path.extend(runtime_path.iter()); + } Dylink0Subsection::Unknown { ty, .. } => { bail!("unrecognized `dylink.0` subsection: {ty}") } diff --git a/tests/cli/dump-dylink0.wat b/tests/cli/dump-dylink0.wat index 04c9c780d5..81e5ffff73 100644 --- a/tests/cli/dump-dylink0.wat +++ b/tests/cli/dump-dylink0.wat @@ -7,5 +7,6 @@ (export-info "a" 0) (import-info "a" "a" 0) (export-info "a" 2 binding-local binding-weak 0 undefined) + (runtime-path "a" "b") ) ) diff --git a/tests/cli/dump-dylink0.wat.stdout b/tests/cli/dump-dylink0.wat.stdout index 221ab824a2..ade3d7b7fb 100644 --- a/tests/cli/dump-dylink0.wat.stdout +++ b/tests/cli/dump-dylink0.wat.stdout @@ -1,6 +1,6 @@ 0x0 | 00 61 73 6d | version 1 (Module) | 01 00 00 00 - 0x8 | 00 2a | custom section + 0x8 | 00 31 | custom section 0xa | 08 64 79 6c | name: "dylink.0" | 69 6e 6b 2e | 30 @@ -13,4 +13,6 @@ 0x26 | 04 06 01 01 | ImportInfo([ImportInfo { module: "a", field: "a", flags: SymbolFlags(0x0) }]) | 61 01 61 00 0x2e | 03 04 01 01 | ExportInfo([ExportInfo { name: "a", flags: SymbolFlags(BINDING_WEAK | BINDING_LOCAL | UNDEFINED) }]) - | 61 13 + | 61 13 + 0x34 | 05 05 02 01 | RuntimePath(["a", "b"]) + | 61 01 62 diff --git a/tests/cli/dylink0.wast b/tests/cli/dylink0.wast index c783cfb6a0..3f4e782136 100644 --- a/tests/cli/dylink0.wast +++ b/tests/cli/dylink0.wast @@ -47,6 +47,7 @@ (export-info "a" 0) (import-info "a" "a" 0) (import-info "b" "b" 1) + (runtime-path "a" "b") ) ) diff --git a/tests/snapshots/cli/dylink0.wast.json b/tests/snapshots/cli/dylink0.wast.json index 8beb51860f..a2ec3073a0 100644 --- a/tests/snapshots/cli/dylink0.wast.json +++ b/tests/snapshots/cli/dylink0.wast.json @@ -45,13 +45,13 @@ }, { "type": "module", - "line": 53, + "line": 54, "filename": "dylink0.7.wasm", "module_type": "binary" }, { "type": "module", - "line": 66, + "line": 67, "filename": "dylink0.8.wasm", "module_type": "binary" } diff --git a/tests/snapshots/cli/dylink0.wast/6.print b/tests/snapshots/cli/dylink0.wast/6.print index 16eb6ab801..23f8a1f7ef 100644 --- a/tests/snapshots/cli/dylink0.wast/6.print +++ b/tests/snapshots/cli/dylink0.wast/6.print @@ -5,5 +5,6 @@ (export-info "a") (import-info "a" "a") (import-info "b" "b" binding-weak) + (runtime-path "a" "b") ) )