Reputation: 35
Let me explain a little bit about what I'm doing. I have an application that I'm embedding a wasm engine (specifically wasmtime) and writing the wasm in Rust. The target is not a browser so I'm not using wasm-bindgen. I'm trying to import two functions from the host environment. I've gotten it to work but with a bit of a hack and I'd like to remove the hack. Here's the problem I'm having. I've been able to figure out how to get Rust to generate the import statements in the wasm output. The problem is that if those functions aren't used the import statements in the wasm aren't included. Wasmtime seem to require that the number of imports passed to the wasm instance match the number of import statements. Makes sense that if the wasm module is expecting imports it's a problem if you don't provide them. The problem is, it's also an error if you provide imports and they're not used.
So I see two ways to fix that, either I need to figure out how to get Rust to include the import statements even if they're not used (right now the hack is to call the functions but ignore the results and it's basically a no-op) or to find a way to introspect the wasm an figure out what kind of imports it's expecting and only pass what it's asking for.
My question is is that the correct approach and if so how do you do that?
Upvotes: 1
Views: 3332
Reputation: 950
I have used a 2 step approach with the wasm-tools
.
wasm-tools objdump
❯ wasm-tools objdump mywasm.wasm
custom "\0ozzzzz_metadata" | 0x1b - 0x1e | 3 bytes | 1 count
types | 0x21 - 0x286 | 613 bytes | 78 count
imports | 0x289 - 0x8da | 1617 bytes | 42 count
functions | 0x8dd - 0x2a16 | 8505 bytes | 8503 count
tables | 0x2a18 - 0x2a1f | 7 bytes | 1 count
memories | 0x2a21 - 0x2a25 | 4 bytes | 1 count
globals | 0x2a27 - 0x2a35 | 14 bytes | 2 count
exports | 0x2a37 - 0x2a4a | 19 bytes | 2 count
elements | 0x2a4d - 0x4fd5 | 9608 bytes | 1 count
code | 0x4fda - 0x374e69 | 3604111 bytes | 8503 count
data | 0x374e6e - 0xc9fea7 | 9613369 bytes | 2 count
custom ".debug_loc" | 0xc9feb7 - 0xf22865 | 2632110 bytes | 1 count
custom ".debug_abbrev" | 0xf22877 - 0xf5230e | 195223 bytes | 1 count
custom ".debug_info" | 0xf5231f - 0x1600847 | 7005480 bytes | 1 count
custom ".debug_ranges" | 0x1600859 - 0x1649691 | 298552 bytes | 1 count
custom ".debug_str" | 0x16496a0 - 0x16dbb98 | 599288 bytes | 1 count
custom ".debug_line" | 0x16dbba9 - 0x1953495 | 2586860 bytes | 1 count
custom "name" | 0x195349e - 0x197db8e | 173808 bytes | 1 count
custom "producers" | 0x197db9b - 0x197dc16 | 123 bytes | 1 count
custom "target_features" | 0x197dc28 - 0x197dc51 | 41 bytes | 1 count
❯ wasm-tools dump mywasm.wasm | grep import
0x286 | 02 d1 0c | import section
0x28a | 16 77 61 73 | import [func 0] Import { module: "wasi_snapshot_preview1", name: "args_get", ty: Func(2) }
0x2ac | 16 77 61 73 | import [func 1] Import { module: "wasi_snapshot_preview1", name: "args_sizes_get", ty: Func(2) }
0x2d4 | 16 77 61 73 | import [func 2] Import { module: "wasi_snapshot_preview1", name: "environ_get", ty: Func(2) }
0x2f9 | 16 77 61 73 | import [func 3] Import { module: "wasi_snapshot_preview1", name: "environ_sizes_get", ty: Func(2) }
[...]
But regarding your question, I would verify if your functions that your rust project should have been provided are missing.
E.g. all extern "C" fn
that are annotated with #[no_mangle]
should appear in the listing below:
❯ wasm-tools dump mywasm.wasm | grep export | grep 'kind: Func'
0x2a41 | 06 5f 73 74 | export Export { name: "_start", kind: Func, index: 43 }
In order that wasmtime can execute your wasm it needs this _start
entry point.
Upvotes: 1
Reputation: 1579
You can convert between .wasm
(binary format) and .wat
(textual format) with the The WebAssembly Binary Toolkit. It is open source. Maybe it can help you to extract the needed imports programmatically.
The proper way, should be that your host environment gives you the import requirements before you initialize the instance. The Module gives you the imports. See the "Instance variables". You get that in between the module loading and the creation of the instance that itself needs these imports.
Upvotes: 3
Reputation: 3032
To find the imports of a wasm module you can you use a command line tool that converts the .wasm
to .wat
and inspect the wat file (using grep or similar). For example wasm-dis
which is part of binaryen
or wasm2wat
which is part of wabt
could be used (or wasm-objdump
which is also part of wabt
).
Upvotes: 0