Stream: wasi

Topic: Failed to link module


view this post on Zulip daubaris (Mar 09 2020 at 13:17):

Hey! I am trying to experiment with strings, but whenever I use the code I get a Failed to link module error.

The code that I am using is:

#[no_mangle]
pub extern "C" fn __modlib_return_string(ptr: *const u8, len: usize) -> *mut c_char {
    let string: String = String::from("Returning a string");
    let cstr = CString::new(string).unwrap();
    cstr.into_raw()
}

Could anyone explain what am I doing wrong?

view this post on Zulip Dan Gohman (Mar 09 2020 at 22:08):

Is this extern "C" function host code that's called from wasm code?

view this post on Zulip daubaris (Mar 10 2020 at 07:33):

@Dan Gohman this function is compiled to wasm code and called externally from the host using wasmtime.

view this post on Zulip daubaris (Mar 10 2020 at 20:27):

It's probably also worth mentioning that the error is Link error: wasi_snapshot_preview1/fd_write

view this post on Zulip Dan Gohman (Mar 11 2020 at 00:16):

I was going to guess that the error was because you're passing a pointer argument. This will need to be translated from a wasm pointer, which is 32-bit and relative to the wasm linear memory, to a host pointer, which I assume is 64-bit for you.

view this post on Zulip Dan Gohman (Mar 11 2020 at 00:17):

But I don't know what would cause an fd_write link error. Can you show the code that calls fd_write?

view this post on Zulip daubaris (Mar 11 2020 at 08:38):

@Dan Gohman I kind of changed the example now. Nevertheless I am still getting the same error.
The module code (it basically tries to call a function from a host which loads another module). It also had to be wrapped in unsafe as without it the compiler spits out errors.

#[link(wasm_import_module = "env")]
extern "C" {
    pub fn load(name: i32) -> i32;
}

#[no_mangle]
pub extern "C" fn __modlib_memory() {
    unsafe {
        load(0);
    }
}

And the load function in the host is:

pub fn load(name: i32) -> i32 {
    let store = Store::default();
    let mod_name = format!("{}.{}", name, "wasm");
    let module = Module::from_file(&store, mod_name).expect("Cannot load a module");
    let instance = Instance::new(&module, &[]).expect("Cannot instantiate a module");

    instances.with(|mut i| {
        let new_instance = ModuleInstance::new(name, instance);
        (*i.borrow_mut()).lock().unwrap().push(new_instance);
    });

    // Success.
    return 0;
}

It's a bit of a hacky code, but I suppose the error is in the modules themselves rather than in main, but of course I might be wrong.

This code calls another module, but that module is super simple without any returns and with one line of println!("OK")

I also saw this issue. Not sure if it's relevant in this case.

Summary I seem to not be able to run RustPython with wasmer. I already looked into the issue RustPython/RustPython#1637 but now it seems like wasmer cannot identify it uses wasi_snapshot_preview1. ...

view this post on Zulip daubaris (Mar 11 2020 at 08:49):

Oh and instances is just a:
thread_local!(static instances: Mutex<Vec<ModuleInstance>> = Mutex::new(Vec::new()));

view this post on Zulip Alex Crichton (Mar 11 2020 at 13:11):

@daubaris it looks like you're compiling for the wasm32-wasi target which requires wasi imports to be satisfied. For that you'll need to pull in the wasmtime-wasi crate and iterate over the module exports to hook them up to wasi functions. If you want to generate a wasm module that doesn't have wasi imports you'll want to use the wasm32-unknown-unknown target. The fd_write intrinsic here is most likely showing up because of panics, which trigger writes to stderr

view this post on Zulip daubaris (Mar 11 2020 at 17:27):

@Alex Crichton Oooh, okay. By the way, about hooking up the exports, I assume you are talking about this repository. I am a bit puzzled on how this "hooking up" is done, any hints?

Standalone JIT-style runtime for WebAssembly, using Cranelift - bytecodealliance/wasmtime

view this post on Zulip Alex Crichton (Mar 11 2020 at 17:28):

@daubaris oh it sort of depends, are you using the wasmtime crate or the C API?

view this post on Zulip daubaris (Mar 11 2020 at 17:28):

I am using wasmtime crate.

view this post on Zulip Alex Crichton (Mar 11 2020 at 17:29):

Ah the hooking up happens in Instance::new w

view this post on Zulip Alex Crichton (Mar 11 2020 at 17:29):

which has docs about what the imports argument there is

view this post on Zulip Alex Crichton (Mar 11 2020 at 17:30):

and for wasi you'd be using the wasmtime_wasi crate

view this post on Zulip Alex Crichton (Mar 11 2020 at 17:30):

and namely the get_export method

view this post on Zulip daubaris (Mar 11 2020 at 17:33):

Hmmm, in the previously mentioned example, I already had the Instance::new, but the problem is that load is being called in the module itself

view this post on Zulip daubaris (Mar 11 2020 at 17:35):

I think I get the idea. I'll try it out and report how it goes :+1: thanks for the help!


Last updated: Dec 23 2024 at 12:05 UTC