Stream: wasmtime

Topic: import memory


view this post on Zulip Ubaid Shaikh (Feb 03 2023 at 12:01):

I have a compiled .wasm file which does not use memory. I am trying to run it using wasmtime. It seems wasmtime needs the .wasm file to export memory.

The .wasm file is a simple file which just exits with a specific non-zero exit code. On executing it with wasmtime, I currently face the following:

$ wasmtime tmp
Error: failed to run main module `tmp`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
           0:   0xa7 - <unknown>!<wasm function 1>
           1:   0xce - <unknown>!<wasm function 3>
           2:   0xb4 - <unknown>!<wasm function 2>
           3:   0xda - <unknown>!<wasm function 4>
    2: missing required memory export

Please, could someone possibly share if there is any flag in wasmtime that allows executing without memory export? Also, does wasmtime allow/support memory import in .wasm file?

view this post on Zulip Ubaid Shaikh (Feb 03 2023 at 12:08):

Some doubts:

  1. Where can I find/learn about the structure of .wasm files that wasmtime expects?
  2. On compiling a C/C++ code with emscripten, I found the following functions exported in the generated .wasm file
  (export "__wasm_call_ctors" (func 0))
  (export "main" (func 3))
  (export "__indirect_function_table" (table 0))
  (export "__errno_location" (func 21))
  (export "fflush" (func 20))
  (export "emscripten_stack_init" (func 10))
  (export "emscripten_stack_get_free" (func 11))
  (export "emscripten_stack_get_base" (func 12))
  (export "emscripten_stack_get_end" (func 13))
  (export "stackSave" (func 6))
  (export "stackRestore" (func 7))
  (export "stackAlloc" (func 8))
  (export "emscripten_stack_get_current" (func 9)))

Please, could someone possibly share what these functions do and/or where I could find information about the working of these functions?

view this post on Zulip Ubaid Shaikh (Feb 03 2023 at 12:09):

I would be really grateful for any help on the above. Thank you.

view this post on Zulip fitzgen (he/him) (Feb 03 2023 at 18:59):

emscripten targets the Web and relies on its generated JS to fulfil all its imports and manage its exports. it isn't really going to work in non-Web environments.

if you are trying to target wasmtime, you'd be better served by wasi-sdk: https://github.com/WebAssembly/wasi-sdk

WASI-enabled WebAssembly C/C++ toolchain. Contribute to WebAssembly/wasi-sdk development by creating an account on GitHub.

view this post on Zulip bjorn3 (Feb 03 2023 at 19:05):

For 1. The wasmtime cli expects a wasi module. The wasi specification requires a memory to be exported. If you want to use a non-wasi wasm module you will have to use wasmtime as library and manually expose whichever interface you want to the wasm module.

view this post on Zulip Ubaid Shaikh (Feb 03 2023 at 21:09):

Thank you so much for the clarification! This is very helpful!

view this post on Zulip Ubaid Shaikh (Feb 03 2023 at 22:35):

Using wasi, how can one print an integer or float to screen? There is fd_write in the wasi api documentation, but it seems it is only for printing strings. I attempted to store an integer in memory and then print it using fd_writeas follows:

(func $main (export "_start")
    (i32.store (i32.const 12) (i32.const 26)) ;; store the number


    ;; iov vector
    (i32.store (i32.const 4) (i32.const 12))
    (i32.store (i32.const 8) (i32.const 4))


    (call $fd_write
      (i32.const 1) ;; 1 for stdout
      (i32.const 4) ;; *iovs
      (i32.const 1) ;; iovs_len
      (i32.const 0) ;; nwritten
    )
    drop
  )

It does not print any output. Printing an integer by storing it directly in memory using (data (i32.const 12) "26") works (because we are just printing it as string), but by storing it as (i32.store (i32.const 12) (i32.const 26)) does not work. Please, could someone possibly share what I might be missing and/or how to print integers/float to stdout using wasi?

view this post on Zulip Dan Gohman (Feb 03 2023 at 22:39):

There is no WASI-level support for formatted output of numbers. Typically programs would link with a source language's standard library, which would implement this in wasm, such as format!(...) in Rust or printf in C or other things in other languages.

view this post on Zulip Jakob Lilliemarck (Feb 04 2023 at 05:43):

I'm attempting to write some basic memory-logic to be able to pass strings to a wasm module, following this article.

It appears however that the wasmtime api have changed a bit since, and functions that return values no seem to require get_typed_func::<Params, Returns>() (which is great btw). What I don't understand is how to type guest functions that return a raw pointer to memory, and what difference it does if I use a i32 or u32 etc. for that.

Given this function defined in rust and compiled to wasm:

#[no_mangle]
pub extern "C" fn alloc(len: usize) -> *mut u8 {
    let mut buf = Vec::with_capacity(len);
    let ptr = buf.as_mut_ptr();
    std::mem::forget(buf);
    return ptr;
}

how do I type that on the hose side?

let alloc = instance.get_typed_func::<??, ??>(&mut store, "alloc")?;
Memory in WebAssembly is one of the topics that creates confusion for newcomers, particularly for those with experience in languages with memory management features like garbage collection, such as JavaScript, Go, or Java. In this article we explore using memory in WebAssembly in various scenarios - passing JavaScript arrays to Rust and AssemblyScript modules, checking for some basic memory leaks using Valgrind, or exchanging strings between runtimes and modules using Wasmtime.

view this post on Zulip bjorn3 (Feb 04 2023 at 09:49):

For wasm32 you did use a 32bit int and for wasm64 a 64bit int. Using an unsigned integer makes most sense.

view this post on Zulip bjorn3 (Feb 04 2023 at 09:50):

By the way have you seen wit-bindgen? It takes care of a lot of work to pass higher level types like structs and arrays between the host and wasm.


Last updated: Dec 23 2024 at 14:03 UTC