Stream: wasmtime

Topic: adding a handler to wasmtime


view this post on Zulip julia (Aug 25 2022 at 20:32):

I want to add a handler function to Wasmtime to be called when the wasm module calls an imprted function such as Wasi libc functions. So, wasmtime transfers the control to my handler and then my handler calls the imported function. Can you please help me how I can implement this handler for wasmtime?

view this post on Zulip Alphyr (Aug 26 2022 at 08:34):

Does Store::call_hook do the trick for you ?

view this post on Zulip julia (Aug 27 2022 at 03:24):

Thanks for your reply.
I need the mechanism like ptrace, is it the similar to it? I couldn't find an example for it

view this post on Zulip bjorn3 (Aug 27 2022 at 07:29):

Wasmtime doesn't support singlestepping through a wasm function. You will likely need a wasm interpreter (as opposed to compiler) for that.

view this post on Zulip julia (Aug 27 2022 at 23:40):

I think my comment wasn't clear, and made you confuse, sorry for that.
Let me clarify it:
This is what I need to do:
1. a wasm module calls a wasi function or another imported function
2. Regardless of which function was called, my custom function should be called (like a proxy) and this function should access to all parameter’s values
3. Then my custom function can change parameters values and then calls the requested wasi function with the changed values
Is it possible to add this functionality to Wasmtime?

view this post on Zulip Alex Crichton (Aug 30 2022 at 15:03):

This should be possibly by defining your own version of a function within a Linker. Calling the original function is a bit wonky but you can use Linker::get to get the previous version of the function to call after you've applied your ahead-of-time filtering logic. Additionally many items inserted into a Linker are also provided as free functions (e.g. in the case of WASI I think that should be the case, or we can at least make that be the case)

view this post on Zulip julia (Aug 31 2022 at 04:56):

@Alex Crichton great! thanks for your reply. I should study more about the linker to get familiar with it to understand how I can implement it. thanks!

view this post on Zulip julia (Sep 05 2022 at 07:13):

@Alex Crichton I found out how I can add my function to a linker. But it is still confusing to me how I can access to imported function parameters when a call happens. Can you please help me with accessing argument's values of calling import functions? You mentioned that it is possible to use Linker::get to get the previous version of the function. Is this function (get in linker) called when an import function called in the wasm module? How can this function access to imported function parameters? Can you clarify your answer a little bit more?
Sorry if my question is silly because I just started to learn wasmtime structure.

view this post on Zulip Alex Crichton (Sep 06 2022 at 15:54):

Hm I'm not sure I understand, when a function is added to a Linker it's added as a closure, and the parameters to the wasm function are the parameters to the closure, so I'm not sure how else you'd like access to the parameters?

For acquiring the previous version you'd probably get the current version of the function, then close over that in the definition of the new function. Something like:

let mut linker = ...;
let prev_func = linker.get(&mut store, "foo", "bar").unwrap().into_func().unwrap();
linker.define("foo", "bar", |arg: u32| {
    println!("got: {}", arg);
    prev_func.call(&mut store, arg)?;
    Ok(())
})?;

view this post on Zulip Alex Crichton (Sep 06 2022 at 15:55):

or something like that

view this post on Zulip julia (Sep 06 2022 at 17:24):

Thanks for your reply.
I wanted my function to act like a transparent proxy for a wasm module and call when a wasi function has been called. But right now, based on your sample code, I think what you mean is that I have to import my custom function into the wasm module and call it instead of wasi function and then my custom function calls the wasi (previous) function. Is it right?

I have another question, is there any function in wasmtime that calls when a wasi function is called by a wasm module? I mean a function which transfer the control to the wasi functions in wasi_snapshot_preview1.

view this post on Zulip Alex Crichton (Sep 06 2022 at 18:10):

No what I'm describing is shadowing a function in a linker where you redefine a previous item (e.g. a previously defined wasi function) with your own custom function, so when a wasm module calls that wasi function it calls your function instead.

There are some simliar features to your second question but I don't think we have one precisely for that.

I'd probably recommend studying the API documentation of the Linker type and additionally looking more into how WASI is implemented in Wasmtime today using Linker. Putting those two together will probably give you a better picture about how to implement what you're thinking and what the limitations are.

view this post on Zulip julia (Sep 12 2022 at 05:02):

Thanks for your solution. It worked and I could shadow a wasi function. However I had to use linker.func_wap instead of define (define didn’t work). I added my implementation to RunCommand implementation in src/commands/run.rs file.
But I still have trouble with calling the previous function. For example, I got these errors when I wanted to shadow args_sizes_get function which is a function without any argument. Do you know what is wrong with my implementation?

linker.func_wrap("wasi_snapshot_preview1", "args_sizes_get",  || -> (i32,i32) {
    |                                                        ^^^^^^^^^^^^^^^ this closure implements FnOnce , not  Fn    the requirement to implement  Fn  derives from here
prev_func.call(store,&[],&mut []);
closure is  FnOnce  because it moves the variable  store  out of its environment

error[E0277]:  RefCell<wasmtime_wasi_nn::ctx::Ctx>  cannot be shared between threads safely
   --> src/commands/run.rs:209:20
 ```

Last updated: Dec 23 2024 at 13:07 UTC