Stream: wasmtime

Topic: access memory offset in Rust-based guest


view this post on Zulip Jean Mertz (Apr 29 2020 at 22:08):

I'm trying to understand how I can direct the host to some piece of memory the guest has written some data to (both are implemented in Rust). I understand that a guest can't have direct access to the host memory, and all it knows is the offset of the memory it is assigned, but how can I go from doing something like Vec::with_capacity(10), to having an offset integer that I can pass to the host for it to use in a memory.data_unchecked()[offset + len] call? Basically, I know how to pass len (10), but I don't know how to get the offset u32 after allocating the memory in the guest.

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:12):

(assuming both sides are written in rust) was Vec::with_capacity(10) run on the wasm/guest side? if yes, then wasm's v.as_ptr() shall give you offset for host

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:22):

wasm pointer is an int32 and direct offset in host's allocated memory

view this post on Zulip Jean Mertz (Apr 29 2020 at 22:31):

Ah interesting. Thanks @Yury Delendik. So something like this should work (some psuedo code): https://gist.github.com/rust-play/e790f19505cc19d2b1330f68f2e7321c?

Code shared from the Rust Playground. GitHub Gist: instantly share code, notes, and snippets.

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:33):

not so fast :) I bet the CString::new("foo") will be destroyed after run call

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:34):

but yeah, you'll get the offset

view this post on Zulip Jean Mertz (Apr 29 2020 at 22:39):

Hmm, yeah, even with mem::forget I still get a NulError because I didn't pass the length. And since I can only return a single value from the guest function, I guess that means the right approach is for the guest to call a host function that takes the offset and length as an argument, right?

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:39):

there is also mem.data_ptr() which might be more intuitive in your case

view this post on Zulip Jean Mertz (Apr 29 2020 at 22:50):

Thanks @Yury Delendik. One more question: how can I add the offset to the ptr from mem.data_ptr() to get the memory location of the string written by the guest? It seems data_ptr().add(offset as usize) won't work, as I get an empty string when I print the cstr from that pointer.

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:54):

.add() is right, so is .offset(). I'm skeptical about guest's code. Try: { static HELLO: &[u8] = b"Hello, world!\x00"; HELLO.as_ptr() as i32 }

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:58):

but normally, you would write something like fn run() -> *const u8 {in the function signature -- you don't have to cast that to i32

view this post on Zulip Jean Mertz (Apr 29 2020 at 22:58):

Yep, that worked! I wonder why mem::forget doesn't work in this case though.

view this post on Zulip Yury Delendik (Apr 29 2020 at 22:59):

yep, be careful, rust can trick you by moving and dropping your stuff

view this post on Zulip Jean Mertz (Apr 29 2020 at 23:00):

Returning *const u8 won't work in this case, will it? Since WasmTy isn't implemented for that type?

view this post on Zulip Yury Delendik (Apr 29 2020 at 23:01):

on host side... for guest side it is fine

view this post on Zulip Jean Mertz (Apr 29 2020 at 23:03):

Aha, I see. Thanks again @Yury Delendik, I'm off to playing some more with this. It's definitely a lot of fun to work with.

view this post on Zulip Jean Mertz (Apr 30 2020 at 07:34):

Quick update for anyone who reads this in the future, mem::forget does work (and so does ManuallyDrop), I was erroneously dropping the ptr instead of the value itself.


Last updated: Nov 22 2024 at 16:03 UTC