Stream: general

Topic: How does wasmtime print Rust backtrace on panics?


view this post on Zulip osa1 (Dec 10 2020 at 12:58):

I'm surprised that if I run a wasm32-wasi Rust program with wasmtime it prints the Rust backtrace (of the Wasm program, not the host) on panic. How does wasmtime implement this? I'd expect it to understand Rust stack implementation on Wasm target for this.. is this the case? Or is it Rust's runtime/core/std that prints the backtrace? If so, why is it printed even when I don't pass RUST_BACKTRACE=1? Example:

$ cat src/main.rs
fn main() {
    panic!()
}

$ cargo build --target=wasm32-wasi
   Compiling wasm_backtrace v0.1.0 (/home/omer/rust/wasm_backtrace)
    Finished dev [unoptimized + debuginfo] target(s) in 0.34s

$ wasmtime target/wasm32-wasi/debug/wasm_backtrace.wasm
thread 'main' panicked at 'explicit panic', src/main.rs:2:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Error: failed to run main module `target/wasm32-wasi/debug/wasm_backtrace.wasm`

Caused by:
    0: failed to invoke command default
    1: wasm trap: unreachable
       wasm backtrace:
         0: 0x6c34 - <unknown>!__rust_start_panic
         1: 0x68df - <unknown>!rust_panic
         2: 0x65b9 - <unknown>!std::panicking::rust_panic_with_hook::h2345fb0909b53e12
         3: 0x10c7 - <unknown>!std::panicking::begin_panic::{{closure}}::h86678b4e45fbd7fa
         4: 0x1ccc - <unknown>!std::sys_common::backtrace::__rust_end_short_backtrace::h8c7fe73fc6112e0e
         5:  0xfb5 - <unknown>!std::panicking::begin_panic::h5a83b3bb18195122
         6: 0x1fed - <unknown>!wasm_backtrace::g::hc5f9230a6e65a92c
         7: 0x1fbf - <unknown>!wasm_backtrace::f::h80747d9c660ceee4
         8: 0x1fb5 - <unknown>!wasm_backtrace::main::h9fc5985544d26b7b
         9: 0x1bee - <unknown>!core::ops::function::FnOnce::call_once::hfd088d5879747b81
         10: 0x1d03 - <unknown>!std::sys_common::backtrace::__rust_begin_short_backtrace::h2d7439e32125816a
         11:  0x4a5 - <unknown>!std::rt::lang_start::{{closure}}::hc9be9987846fa67a
         12: 0x69f0 - <unknown>!std::rt::lang_start_internal::h260050c92cd470af
         13:  0x457 - <unknown>!std::rt::lang_start::hd15e4b73e676a12b
         14: 0x200b - <unknown>!__original_main
         15:  0x397 - <unknown>!_start

view this post on Zulip Yury Delendik (Dec 10 2020 at 13:18):

It is generated and printed by wasmtime. During the trap, cranelift gets entire backtrace (see backtrace crate) and filters out only wasm addresses, wasmtime just prints out wasm portion, but capable of getting entire stack including host.

view this post on Zulip osa1 (Dec 10 2020 at 14:02):

cranelift gets entire backtrace (see backtrace crate)

How is this done exactly? Does wasmtime/cranelift know about Rust's stack implementation in Wasm linear memory?

view this post on Zulip osa1 (Dec 10 2020 at 14:03):

So backtrace (the crate) can walk Rust stack.. but for example in my example wasmtime needs to be aware that the Wasm program is Rust and call that crate to obtain the stack trace, no?

view this post on Zulip Yury Delendik (Dec 10 2020 at 14:05):

nope, the wasm program can be in C, and your will see similar trace but with C names

view this post on Zulip osa1 (Dec 10 2020 at 14:06):

So wasmtime understands C ABI on Wasm?

view this post on Zulip Yury Delendik (Dec 10 2020 at 14:07):

backtrace walk native stack not just rust

view this post on Zulip Yury Delendik (Dec 10 2020 at 14:08):

it is more related with libunwind works than C API

view this post on Zulip osa1 (Dec 10 2020 at 14:09):

OK thanks. I'll look at uses of the backtrace crate in wasmtime for details.

view this post on Zulip osa1 (Dec 10 2020 at 14:10):

One more question: the backtrace in my example is obtained on Wasm trap instruction, right?

view this post on Zulip Yury Delendik (Dec 10 2020 at 14:11):

more exactly from unreachable (multiple instructions can trap for different reasons)

view this post on Zulip osa1 (Dec 10 2020 at 14:37):

@Yury Delendik thanks, really helpful. Does wasmtime provide an API for getting the Wasm program's backtrace (using the backtrace crate or otherwise) when implementing a host function? As far as I understand host functions have access to Caller but it's not possible to get a backtrace from that type, right?

view this post on Zulip Yury Delendik (Dec 10 2020 at 14:39):

https://docs.wasmtime.dev/api/wasmtime/struct.Trap.html ?

view this post on Zulip Peter Huene (Dec 10 2020 at 19:21):

On a related note, I think we should probably default the module name to the filename sans .wasm so that backtraces aren't filled with <unknown>.

view this post on Zulip Peter Huene (Dec 10 2020 at 19:26):

Filed https://github.com/bytecodealliance/wasmtime/issues/2495

Repro Create a Rust wasm file that simply panics in main. Run the wasm with wasmtime foo.wasm Expected behavior As the module doesn't declare a module name, Wasmtime should provide a meaningful...

Last updated: Dec 23 2024 at 12:05 UTC