Stream: wasmtime

Topic: Printing wasm stack while debugging in LLDB


view this post on Zulip _Vi (Aug 08 2026 at 22:17):

I have tried debugging according to https://docs.wasmtime.dev/examples-debugging-guest.html . It seems to work - I can attach the LLDB, step though instructions, inspect memory using x/8. But how do I inspect the operand stack?

For example, if I'm at "call" in

    0x40000000000000b9: i32.const 1
    0x40000000000000bb: i32.const 0
    0x40000000000000bd: call   0

how do I see that "1" and "0" that are currently in the stack and then see what call put to stack after returning?

view this post on Zulip Chris Fallin (Aug 08 2026 at 22:24):

That support is missing in LLDB. The underlying protocol that we implement can provide the information (and LLDB uses it to get the data needed to print locals, etc) but LLDB's UI has no command for it

view this post on Zulip Chris Fallin (Aug 08 2026 at 22:25):

We could in theory also support an alternative environment (rendered through DAP) that gives a raw machine-level view; I haven't had time to do that but contributions welcome (the debug-component APIs should provide everything needed)

view this post on Zulip _Vi (Aug 08 2026 at 22:36):

Is there a hack like using xon some magical address that will reveal the stack, like {the 0x40000000000000a7 that consistently contains the code for _start}, but for the stack?

Is there other, non-LLDB or non-Wasmtime debugging experience for WASI with everything implemented?

view this post on Zulip Chris Fallin (Aug 08 2026 at 22:38):

no and no, as far as I know; the right way to do this would be to either implement the extensions in LLDB's Wasm machine model to understand the stack and expose it as printable state (not too hard) or build our own Wasm-native debugging stack (very hard)

view this post on Zulip Vasily Levchenko (Aug 19 2026 at 19:00):

Update for this thread: we've built this. Hexana 0.18 (JetBrains IDEs, free) shows the live operand stack during Wasm debugging: stop at an instruction, see the actual stack-machine values, step and watch them change. Works in LLDB sessions against Wasmtime/WAMR and in Node.js over CDP. Details: https://bsky.app/profile/minamoto79.bsky.social/post/3mthexkw6ns2b

Chris's read was exactly right: the protocol has the data, the missing piece was the UI layer. Thanks to this thread for the nudge, _Vi's question moved it up our list. If it misbehaves on your modules, that's the feedback we want.

view this post on Zulip Chris Fallin (Aug 19 2026 at 19:02):

@Vasily Levchenko pretty cool; are you contributing the enhancements upstream to LLDB?

view this post on Zulip Chris Fallin (Aug 19 2026 at 19:02):

(Or does your UI get at the low-level connection directly and bypass LLDB somehow?)

view this post on Zulip Vasily Levchenko (Aug 19 2026 at 19:16):

@Chris Fallin we didn't change lldb, we're using WebAssembly extension of gdb protocol. It looks like packet family: qWasmCallStack, qWasmLocal, qWasmGlobal, qWasmStackValue is enough to get all required information.

view this post on Zulip Chris Fallin (Aug 19 2026 at 19:28):

Yes, LLDB supports the Wasm extensions and it's what we recommend using with Wasmtime. You mention "works in LLDB sessions against Wasmtime" which is why I'm assuming you've made some changes to LLDB to support printing the value stack

view this post on Zulip Chris Fallin (Aug 19 2026 at 19:29):

LLDB knows about those commands and uses them, including to evaluate source-level locals, but doesn't have UI-layer support to invoke them directly and (e.g.) print the value stack

view this post on Zulip Vasily Levchenko (Aug 19 2026 at 20:09):

We send commands like:

(lldb) process plugin packet send qWasmStackValue:0;0
packet: qWasmStackValue:0;0
response: f0ff0f00

and decode the value basing on type information we've parsed from debug information from dwarf sections.

view this post on Zulip Chris Fallin (Aug 19 2026 at 20:11):

Ah, gotcha, so there's backdoor access via LLDB itself. Interesting, thanks! Would be great if someone wired this up to something akin to info registers (e.g., info wasm-stack and info wasm-locals) for native CLI debugger users

view this post on Zulip Vasily Levchenko (Aug 19 2026 at 20:16):

yeah that would be great :slight_smile:

view this post on Zulip _Vi (Aug 19 2026 at 22:45):

So the answer to "Is there a hack like using x on some magical address that will reveal the stack...?" question back there was actually "yes" rather than "no" -
I have checked that process plugin packet send qWasmStackValue:0;0 indeed allows you to inspect the data stack - it shows UNIMPLEMENTED if the stack is empty and the little-endian representation of the value if not.
You can change the final 0 to other number to dig deeper into the stack.
I also see process plugin packet send qWasmGlobal:0;5 and qWasmLocal working and giving me the thing I was interested in.

Shall those tricks be documented somewhere (e.g. on examples-debugging-guest.html) until proper support rolls in?

view this post on Zulip Chris Fallin (Aug 19 2026 at 22:52):

Shall those tricks be documented somewhere (e.g. on examples-debugging-guest.html) until proper support rolls in?

Probably not; I'm happy it worked for the above use-case and maybe it makes sense for a UI to use this backdoor but I would not advise users to manually send raw gdbstub packets -- it would be far too easy to desync the connection / get it into a bad state

view this post on Zulip Chris Fallin (Aug 19 2026 at 22:52):

Anyone who wants this in LLDB should file a feature request upstream (on the LLVM repo)


Last updated: Aug 30 2026 at 09:07 UTC