Stream: git-wasmtime

Topic: wasmtime / issue #12677 DWARF debug info: local variables...


view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 00:06):

radu-matei opened issue #12677:

I'm working on debugging support for WASI HTTP/Spin Rust components.
Breakpoints are correctly triggered; however, inspecting variables through LLDB/VS Code results in "no location, value may have been optimized out".

I have reproduced with a simple Rust program compiled to either wasm32-wasip1 or wasm32-wasip2:

fn main() {
    let x = 42;
    let y = "foo";
    println!("Hello, world!");
}

With this debug profile in Cargo.toml:

[profile.dev]
opt-level = 0
debug = true

Running with Wasmtime 42.0.0 (or 41.0.4) and LLDB, then listing variables results in the message no location, value may have been optimized out for all variables:

lldb -- wasmtime run -D debug-info -O opt-level=0 target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm
(lldb) target create "wasmtime"
Current executable set to '/Users/radu/.wasmtime/bin/wasmtime' (arm64).
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 94942 launched: '/Users/radu/.wasmtime/bin/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 94942 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000107e1c3b0 JIT(0x8a6028000)`dwarf_debugging_repro::main::h15ad2e2a588792ef at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x00000008a7258ca0
(int) x = <no location, value may have been optimized out>

(long) y = <no location, value may have been optimized out>

(&str) msg = <no location, value may have been optimized out>

(lldb)

Disclaimer: I have a patch to Wasmtime generated with Claude (plus description) that allows me to retrieve the variables when debugging with lldb:
(I do not claim to fully understand how it works, which is why this is not a PR; feel free to use or ignore the patch I linked):

lldb -- wasmtime-with-the-patch run -D debug-info -O opt-level=0 target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 96860 launched: '/Users/radu/projects/github.com/spinframework/wasmtime/target/release/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 96860 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001089d86bc JIT(0xaba000000)`dwarf_debugging_repro::main::hb42100e0c21c7fa3 at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x0000000abb0c40a0
(int) x = 42
(long) y = 100
(&str) msg = {
  data_ptr = (__ptr = 1048576)
  length = 5
}

Being able to support breakpoint debugging for WASI HTTP components and variable inspection support would be incredibly valuable for the Spin project. Let me know if there is anything I can help with further.

Environment:

$ lldb --version
lldb-1703.0.234.3
Apple Swift version 6.2.1 (swiftlang-6.2.1.4.8 clang-1700.4.4.1)

$ cargo --version
cargo 1.93.1 (083ac5135 2025-12-15)

Thanks!

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 00:06):

radu-matei added the bug label to Issue #12677.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 00:15):

cfallin commented on issue #12677:

Thanks for filing the issue! I am actually working on "guest debugging", which is a fully integrated host-level debugger inside Wasmtime that solves this issue in a complete/perfect-fidelity way. It is intended to replace the "native" debugging workflow where you attach LLDB to the host Wasmtime process, which we've known is flaky for some time.

You have good timing here, because I am actually giving a talk about this tomorrow at the second day of the BA Plumber's Summit; feel free to watch for more info. All of the core Wasmtime bits for my work are already in-tree, but the debugger component is not. Free free to read the RFCs (1, 2, 3) for more info.

Because this is the path forward, I don't think we are going to add a lot of new ad-hoc DWARF fixups. Interestingly, your Claude-produced patch more or less re-invented (borrowed?) the instrumentation approach that guest-debugging also takes, putting Wasm locals in explicit stack slots (but worse: e.g. no support for operand stack, no awareness of inlining, ...). Interesting experiment nonetheless.

I'll go ahead and close this issue but please feel free to ask any questions about the upcoming approach if you'd like.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 00:15):

cfallin closed issue #12677:

I'm working on debugging support for WASI HTTP/Spin Rust components.
Breakpoints are correctly triggered; however, inspecting variables through LLDB/VS Code results in "no location, value may have been optimized out".

I have reproduced with a simple Rust program compiled to either wasm32-wasip1 or wasm32-wasip2:

fn main() {
    let x = 42;
    let y = "foo";
    println!("Hello, world!");
}

With this debug profile in Cargo.toml:

[profile.dev]
opt-level = 0
debug = true

Running with Wasmtime 42.0.0 (or 41.0.4) and LLDB, then listing variables results in the message no location, value may have been optimized out for all variables:

lldb -- wasmtime run -D debug-info -O opt-level=0 target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm
(lldb) target create "wasmtime"
Current executable set to '/Users/radu/.wasmtime/bin/wasmtime' (arm64).
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 94942 launched: '/Users/radu/.wasmtime/bin/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 94942 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000107e1c3b0 JIT(0x8a6028000)`dwarf_debugging_repro::main::h15ad2e2a588792ef at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x00000008a7258ca0
(int) x = <no location, value may have been optimized out>

(long) y = <no location, value may have been optimized out>

(&str) msg = <no location, value may have been optimized out>

(lldb)

Disclaimer: I have a patch to Wasmtime generated with Claude (plus description) that allows me to retrieve the variables when debugging with lldb:
(I do not claim to fully understand how it works, which is why this is not a PR; feel free to use or ignore the patch I linked):

lldb -- wasmtime-with-the-patch run -D debug-info -O opt-level=0 target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 96860 launched: '/Users/radu/projects/github.com/spinframework/wasmtime/target/release/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 96860 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001089d86bc JIT(0xaba000000)`dwarf_debugging_repro::main::hb42100e0c21c7fa3 at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x0000000abb0c40a0
(int) x = 42
(long) y = 100
(&str) msg = {
  data_ptr = (__ptr = 1048576)
  length = 5
}

Being able to support breakpoint debugging for WASI HTTP components and variable inspection support would be incredibly valuable for the Spin project. Let me know if there is anything I can help with further.

Environment:

$ lldb --version
lldb-1703.0.234.3
Apple Swift version 6.2.1 (swiftlang-6.2.1.4.8 clang-1700.4.4.1)

$ cargo --version
cargo 1.93.1 (083ac5135 2025-12-15)

Thanks!

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 00:15):

cfallin closed issue #12677:

I'm working on debugging support for WASI HTTP/Spin Rust components.
Breakpoints are correctly triggered; however, inspecting variables through LLDB/VS Code results in "no location, value may have been optimized out".

I have reproduced with a simple Rust program compiled to either wasm32-wasip1 or wasm32-wasip2:

fn main() {
    let x = 42;
    let y = "foo";
    println!("Hello, world!");
}

With this debug profile in Cargo.toml:

[profile.dev]
opt-level = 0
debug = true

Running with Wasmtime 42.0.0 (or 41.0.4) and LLDB, then listing variables results in the message no location, value may have been optimized out for all variables:

lldb -- wasmtime run -D debug-info -O opt-level=0 target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm
(lldb) target create "wasmtime"
Current executable set to '/Users/radu/.wasmtime/bin/wasmtime' (arm64).
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 94942 launched: '/Users/radu/.wasmtime/bin/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 94942 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000107e1c3b0 JIT(0x8a6028000)`dwarf_debugging_repro::main::h15ad2e2a588792ef at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x00000008a7258ca0
(int) x = <no location, value may have been optimized out>

(long) y = <no location, value may have been optimized out>

(&str) msg = <no location, value may have been optimized out>

(lldb)

Disclaimer: I have a patch to Wasmtime generated with Claude (plus description) that allows me to retrieve the variables when debugging with lldb:
(I do not claim to fully understand how it works, which is why this is not a PR; feel free to use or ignore the patch I linked):

lldb -- wasmtime-with-the-patch run -D debug-info -O opt-level=0 target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 96860 launched: '/Users/radu/projects/github.com/spinframework/wasmtime/target/release/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 96860 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001089d86bc JIT(0xaba000000)`dwarf_debugging_repro::main::hb42100e0c21c7fa3 at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x0000000abb0c40a0
(int) x = 42
(long) y = 100
(&str) msg = {
  data_ptr = (__ptr = 1048576)
  length = 5
}

Being able to support breakpoint debugging for WASI HTTP components and variable inspection support would be incredibly valuable for the Spin project. Let me know if there is anything I can help with further.

Environment:

$ lldb --version
lldb-1703.0.234.3
Apple Swift version 6.2.1 (swiftlang-6.2.1.4.8 clang-1700.4.4.1)

$ cargo --version
cargo 1.93.1 (083ac5135 2025-12-15)

Thanks!

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 00:16):

cfallin edited a comment on issue #12677:

Thanks for filing the issue! I am actually working on "guest debugging", which is a fully integrated host-level debugger inside Wasmtime that solves this issue in a complete/perfect-fidelity way. It is intended to replace the "native" debugging workflow where you attach LLDB to the host Wasmtime process, which we've known is flaky for some time.

You have good timing here, because I am actually giving a talk about this tomorrow at the second day of the BA Plumber's Summit; feel free to watch for more info. All of the core Wasmtime bits for my work are already in-tree, but the debugger component is not. Free free to read the RFCs (1, 2, 3) for more info.

Because this is the path forward, I don't think we are going to add a lot of new ad-hoc DWARF fixups. Interestingly, your Claude-produced patch more or less re-invented (borrowed?) the instrumentation approach that guest-debugging also takes, putting Wasm locals in explicit stack slots (but worse: e.g. no support for operand stack, no awareness of inlining, ...). Interesting experiment nonetheless.

I'll go ahead and close this issue but please feel free to ask any questions about the upcoming approach if you'd like.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 00:17):

cfallin edited a comment on issue #12677:

Thanks for filing the issue! I am actually working on "guest debugging", which is a fully integrated host-level debugger inside Wasmtime that solves this issue in a complete/perfect-fidelity way. It is intended to replace the "native" debugging workflow where you attach LLDB to the host Wasmtime process, which we've known is flaky for some time.

You have good timing here, because I am actually giving a talk about this tomorrow at the second day of the BA Plumber's Summit; feel free to watch for more info. All of the core Wasmtime bits for my work are already in-tree, but the debugger component is not. Free free to read the RFCs (1, 2, 3) for more info. I will demo a working LLDB attached to Wasmtime via a native gdbstub server tomorrow.

Because this is the path forward, I don't think we are going to add a lot of new ad-hoc DWARF fixups. Interestingly, your Claude-produced patch more or less re-invented (borrowed?) the instrumentation approach that guest-debugging also takes, putting Wasm locals in explicit stack slots (but worse: e.g. no support for operand stack, no awareness of inlining, ...). Interesting experiment nonetheless.

I'll go ahead and close this issue but please feel free to ask any questions about the upcoming approach if you'd like.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 15:42):

alexcrichton commented on issue #12677:

@cfallin my impression is that we don't want to jettison the DWARF support we have, so while the priority for fixing this might be lower than other debugging-related issues, this seems useful for me to keep open. We have a tranch of issues with the DWARF support we have but also a trickle of fixes coming in over time.

Would you be opposed to me reopening this to track this? If we decide to remove DWARF support I think it's reasonable to close, but otherwise I think it's good to track.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 16:02):

cfallin commented on issue #12677:

@alexcrichton we have a bunch of issues like this indeed; if we want to track ongoing issues with DWARF I think we should standardize on one of them (e.g. #3439 to pick a random one) rather than keeping all of them open as they're all essentially the same issue.

I was interpreting the issue more broadly: trying to debug an HTTP component, following the "attach LLDB to Wasmtime process" procedure, and my contention is that for this use-case one really wants to use guest-debugging.

I'm also slightly concerned that the proposed patch here adds essentially another debugging instrumentation pass, in parallel to the existing one. If we want to put more effort into DWARF for host-attached debugging in the future we should probably generate DWARF using our existing instrumentation IMHO.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 16:29):

alexcrichton commented on issue #12677:

I was under the impression that each DWARF issue more-or-less is a different cause. For example https://github.com/bytecodealliance/wasmtime/issues/9716 is a very similar issue, which is fixed, yet this and #3439 remains. I would personally expect us to keep these issues open and perhaps tag them as DWARF issues to catalogue them.

How certain are you though this is the exact same issue as #3439? I agree there's no need to have duplicate issues, but if the underlying cause is different I think it's useful to have different examples as necessary.

Also I'm not specifically advocating for the attached patch here. The presence of that doesn't invalidate this issue itself, and while that may be somewhat helpful for understanding the underlying issue here I don't think that should guide whether this issue is closed/not.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 20:25):

cfallin commented on issue #12677:

You're right, I don't know whether it's the same issue or not. I suppose I lump all of these into "incomplete DWARF fidelity" as one bucket.

There's a deeper question of what we do about incomplete DWARF -- a true fix would be something like the patch linked here, but that creates a whole parallel instrumentation mechanism alongside guest-debugging. In essence we need to either choose "some values will always be missing because we have an optimizing compiler" or "we emit instrumentation so we always have all values", and the latter... already exists.

In that sense I guess I am advocating not continuing to make spot-fixes to the host DWARF infrastructure, because it's a losing battle and goes against the fundamental tradeoff we've already made: by default, we optimize code (and don't insert instrumentation). We have an answer for perfect fidelity, and we've decided not to take on more complexity in the host/native debuginfo handling and associated compiler infra.

Happy to talk about this in the next Wasmtime meeting as well to see what everyone thinks...

@radu-matei can you clarify whether your use-case required attaching LLDB to the native process, versus only debugging the guest code? If the latter, does the guest-debugging as demoed (upstreamed soon hopefully!) meet your needs?

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 21:44):

alexcrichton added the wasmtime:debugging label to Issue #12677.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 21:45):

alexcrichton commented on issue #12677:

Happy to talk about this in the next Wasmtime meeting as well to see what everyone thinks...

Good idea!


I'm going to reopen this in the meantime since it's, at least to me, not necessarily a duplicate of #3439, but this is also pending the outcome of discussion at the next meeting to see how much we want to preserve/push/keep the existing DWARF support.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 26 2026 at 21:45):

alexcrichton reopened issue #12677:

I'm working on debugging support for WASI HTTP/Spin Rust components.
Breakpoints are correctly triggered; however, inspecting variables through LLDB/VS Code results in "no location, value may have been optimized out".

I have reproduced with a simple Rust program compiled to either wasm32-wasip1 or wasm32-wasip2:

fn main() {
    let x = 42;
    let y = "foo";
    println!("Hello, world!");
}

With this debug profile in Cargo.toml:

[profile.dev]
opt-level = 0
debug = true

Running with Wasmtime 42.0.0 (or 41.0.4) and LLDB, then listing variables results in the message no location, value may have been optimized out for all variables:

lldb -- wasmtime run -D debug-info -O opt-level=0 target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm
(lldb) target create "wasmtime"
Current executable set to '/Users/radu/.wasmtime/bin/wasmtime' (arm64).
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 94942 launched: '/Users/radu/.wasmtime/bin/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 94942 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000107e1c3b0 JIT(0x8a6028000)`dwarf_debugging_repro::main::h15ad2e2a588792ef at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x00000008a7258ca0
(int) x = <no location, value may have been optimized out>

(long) y = <no location, value may have been optimized out>

(&str) msg = <no location, value may have been optimized out>

(lldb)

Disclaimer: I have a patch to Wasmtime generated with Claude (plus description) that allows me to retrieve the variables when debugging with lldb:
(I do not claim to fully understand how it works, which is why this is not a PR; feel free to use or ignore the patch I linked):

lldb -- wasmtime-with-the-patch run -D debug-info -O opt-level=0 target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 96860 launched: '/Users/radu/projects/github.com/spinframework/wasmtime/target/release/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 96860 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001089d86bc JIT(0xaba000000)`dwarf_debugging_repro::main::hb42100e0c21c7fa3 at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x0000000abb0c40a0
(int) x = 42
(long) y = 100
(&str) msg = {
  data_ptr = (__ptr = 1048576)
  length = 5
}

Being able to support breakpoint debugging for WASI HTTP components and variable inspection support would be incredibly valuable for the Spin project. Let me know if there is anything I can help with further.

Environment:

$ lldb --version
lldb-1703.0.234.3
Apple Swift version 6.2.1 (swiftlang-6.2.1.4.8 clang-1700.4.4.1)

$ cargo --version
cargo 1.93.1 (083ac5135 2025-12-15)

Thanks!

view this post on Zulip Wasmtime GitHub notifications bot (Mar 02 2026 at 10:19):

radu-matei commented on issue #12677:

Thanks for the conversation, appreciate it!

My goal is to allow users to debug the programs they are writing, not the Wasmtime embedding itself, and I was following the guide from https://github.com/bytecodealliance/wasmtime/blob/main/docs/examples-debugging-native-debugger.md on how to achieve that today.

Since in this case we don't need to debug hosts, the guest debugging proposal (and awesome demo!) is what we need.

What I don't understand is the level of effort (and time) required to switch to this vs. the existing implementation that already supports setting and stopping on breakpoints during debugging sessions.

Thanks!

view this post on Zulip Wasmtime GitHub notifications bot (Mar 02 2026 at 14:55):

cfallin commented on issue #12677:

Thanks @radu-matei -- it sounds like guest-debugging is actually better for your use-case then since it avoids confusing the user by stepping through native runtime code.

What I don't understand is the level of effort (and time) required to switch to this vs. the existing implementation that already supports setting and stopping on breakpoints during debugging sessions.

It should be more or less as easy as the current workflow once the last bits (debug-component host, and the gdbstub adapter) are landed. It's not quite "lldb -- wasmtime run ...", it'll be more like "wasmtime run -D ... port=1234" then "lldb" + "connect :1234" in another terminal (as you saw in my demo), but perhaps we could ship a wrapper CLI binary that does all this to give a single-command experience again.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 04 2026 at 05:39):

philipc commented on issue #12677:

I agree that guest-debugging is a better solution for this use-case. However, I've done some digging to figure out what's going on here.

Here's the compiled instructions:

00000000000003e0 <wasm[0]::function[11]::_ZN11issue_126774main17h720650835ab3a273E>:
     3e0:       a9bf7bfd        stp     x29, x30, [sp, #-16]!
     3e4:       910003fd        mov     x29, sp
     3e8:       f8408050        ldur    x16, [x2, #8]
     3ec:       f8418210        ldur    x16, [x16, #24]
     3f0:       91008210        add     x16, x16, #0x20
     3f4:       eb3063ff        cmp     sp, x16
     3f8:       540004e3        b.cc    494 <wasm[0]::function[11]::_ZN11issue_126774main17h720650835ab3a273E+0xb4>  // b.lo, b.ul, b.last
     3fc:       a9bf63f3        stp     x19, x24, [sp, #-16]!
     400:       b940c040        ldr     w0, [x2, #192]
     404:       51008018        sub     w24, w0, #0x20
     408:       b900c058        str     w24, [x2, #192]
     40c:       52800540        mov     w0, #0x2a                       // #42
     410:       f9401c41        ldr     x1, [x2, #56]
     414:       91005021        add     x1, x1, #0x14
     418:       b8384820        str     w0, [x1, w24, uxtw]
     41c:       52800300        mov     w0, #0x18                       // #24
     420:       72a00200        movk    w0, #0x10, lsl #16
     424:       f9401c41        ldr     x1, [x2, #56]
     428:       91006021        add     x1, x1, #0x18
     42c:       b8384820        str     w0, [x1, w24, uxtw]
     430:       52800060        mov     w0, #0x3                        // #3
     434:       f9401c41        ldr     x1, [x2, #56]
     438:       aa0203f3        mov     x19, x2
     43c:       91007021        add     x1, x1, #0x1c
     440:       b8384820        str     w0, [x1, w24, uxtw]
     444:       52800365        mov     w5, #0x1b                       // #27
     448:       72a00205        movk    w5, #0x10, lsl #16
     44c:       528001c6        mov     w6, #0xe                        // #14
     450:       11002304        add     w4, w24, #0x8
     454:       aa1303e3        mov     x3, x19
     458:       9400004a        bl      580 <wasm[0]::function[15]::_ZN4core3fmt9Arguments8from_str17h473e4d5a234a1078E>
     45c:       f9401e60        ldr     x0, [x19, #56]
     460:       91003000        add     x0, x0, #0xc
     464:       b8784805        ldr     w5, [x0, w24, uxtw]
     468:       f9401e60        ldr     x0, [x19, #56]
     46c:       91002000        add     x0, x0, #0x8
     470:       b8784804        ldr     w4, [x0, w24, uxtw]
     474:       aa1303e2        mov     x2, x19
     478:       aa1303e3        mov     x3, x19
     47c:       94000991        bl      2ac0 <wasm[0]::function[54]::_ZN3std2io5stdio6_print17h18a8a3ba3986bed2E>
     480:       11008300        add     w0, w24, #0x20
     484:       b900c260        str     w0, [x19, #192]
     488:       a8c163f3        ldp     x19, x24, [sp], #16
     48c:       a8c17bfd        ldp     x29, x30, [sp], #16
     490:       d65f03c0        ret
     494:       0000c11f        udf     #49439

The ones relevant to x are:

     40c:       52800540        mov     w0, #0x2a                       // #42
     410:       f9401c41        ldr     x1, [x2, #56]
     414:       91005021        add     x1, x1, #0x14
     418:       b8384820        str     w0, [x1, w24, uxtw]

Based on that, you would expect that we should be able to give a location for x as long as x2 and w24 are valid, which should be for the majority of the function.

The DWARF expression from the transform is:

    DW_AT_location    (0x00000436:
       (0x000000000000040c, 0x0000000000000410): DW_OP_breg24 W24+0, DW_OP_plus_uconst 0x14, DW_OP_breg2 W2+56, DW_OP_deref, DW_OP_swap, DW_OP_const4u 0xffffffff, DW_OP_and, DW_OP_plus)

which looks to be doing mostly the right thing (*(x2 + 56) + w24 + 0x14), but its address range is far shorter than it should be.

Looking at the cranelift_codegen::machinst::vcode trace I get this table:

|BB|Inst    |IP  |VL0      |VL1     |VL2     |VL3     |VL4294967294|
|--|--------|----|---------|--------|--------|--------|------------|
|B0|Inst 0  |32  |    |    |    |   |    |   |    |   |    |       |
|  |Inst 1  |32  |v194|    |v194|   |v194|   |v194|   |v192|p2i    |
|  |Inst 2  |36  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 3  |40  |v255|p24i|*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 4  |44  |*   |p24i|*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 5  |48  |v199|    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 6  |52  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 7  |56  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 8  |60  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 9  |64  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 10 |68  |v205|    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 11 |72  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 12 |76  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 13 |80  |*   |    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 14 |84  |v211|    |*   |   |*   |   |*   |   |*   |p2i    |
|  |Inst 15 |92  |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 16 |96  |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 17 |100 |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 18 |104 |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 19 |108 |*   |    |v244|p5i|*   |   |*   |   |*   |p19i   |
|  |Inst 20 |112 |*   |    |*   |p5i|v242|p6i|*   |   |*   |p19i   |
|  |Inst 21 |120 |*   |    |*   |p5i|*   |p6i|*   |   |*   |p19i   |
|  |Inst 22 |124 |v220|    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 23 |128 |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 24 |132 |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 25 |136 |v226|    |*   |   |*   |   |v239|p5i|*   |p19i   |
|  |Inst 26 |140 |*   |    |*   |   |*   |   |*   |p5i|*   |p19i   |
|  |Inst 27 |144 |*   |    |*   |   |*   |   |*   |p5i|*   |p19i   |
|  |Inst 28 |156 |*   |    |*   |   |*   |   |*   |p5i|*   |p19i   |
|  |Inst 29 |160 |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 30 |164 |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 31 |168 |*   |    |*   |   |*   |   |*   |   |*   |p19i   |
|  |Inst 32 |168 |*   |    |*   |   |*   |   |*   |   |*   |       |
Recording debug range for VL0 in Reg(p24i): [Inst 3..Inst 5) [40..48)
Recording debug range for VL1 in Reg(p5i): [Inst 19..Inst 22) [108..124)
Recording debug range for VL2 in Reg(p6i): [Inst 20..Inst 22) [112..124)
Recording debug range for VL3 in Reg(p5i): [Inst 25..Inst 29) [136..160)
Recording debug range for VL4294967294 in Reg(p2i): [Inst 1..Inst 15) [32..92)
Recording debug range for VL4294967294 in Reg(p19i): [Inst 15..Inst 21) [92..120)
Extending debug range for VL4294967294 in Reg(p19i) to Inst 32 (168)

So the information being fed into the DWARF transform is that p24i is only valid for 2 instructions. I'm not at all familiar with what happens in cranelift prior to this point, so I would need to investigate further, but maybe others have a better idea. It's worth noting that this appears to be specific to AArch64; x86_64 manages to give a longer address range for the location of x.

Regarding discussions about the long term support of the DWARF transform, I'm happy to support the DWARF part of this, but as you can see above, I'm not yet in a position to be able to support the parts of cranelift that it depends on.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 07 2026 at 11:53):

philipc commented on issue #12677:

It appears that what happens is:

This patch fixes the reproduction given in this issue, but I really don't have the knowledge to know if this is a correct fix:

--- a/cranelift/codegen/src/machinst/lower.rs
+++ b/cranelift/codegen/src/machinst/lower.rs
@@ -800,13 +800,13 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
                 continue;
             }

-            // Value defined by "inst" becomes live after it in normal
-            // order, and therefore **before** in reversed order.
-            self.emit_value_label_live_range_start_for_inst(inst);
-
             // Normal instruction: codegen if the instruction is side-effecting
             // or any of its outputs is used.
             if has_side_effect || value_needed {
+                // Value defined by "inst" becomes live after it in normal
+                // order, and therefore **before** in reversed order.
+                self.emit_value_label_live_range_start_for_inst(inst);
+
                 trace!("lowering: inst {}: {}", inst, self.f.dfg.display_inst(inst));
                 let temp_regs = match backend.lower(self, inst) {
                     Some(regs) => regs,

lldb output with this patch:

SY666:wasmtime-issue12677 user937765$ lldb -- ../wasmtime/target/debug/wasmtime run -D debug-info -O opt-level=0 target/wasm32-wasip1/debug/wasmtime-issue12677.wasm
(lldb) target create "../wasmtime/target/debug/wasmtime"
Current executable set to '/Users/user937765/wasmtime/target/debug/wasmtime' (arm64).
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip1/debug/wasmtime-issue12677.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:4
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 59915 launched: '/Users/user937765/wasmtime/target/debug/wasmtime' (arm64)
1 location added to breakpoint 1
Process 59915 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000111904568 JIT(0x1181b8000)`wasmtime_issue12677::main::hbee1db8dd8875889 at main.rs:4:5
   1    fn main() {
   2        let x = 42;
   3        let y = "foo";
-> 4        println!("Hello, world!");
   5    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x000000010d00fea0
(int) x = 42
(&str) y = {
  data_ptr = (__ptr = 1048600)
  length = 3
}

view this post on Zulip Wasmtime GitHub notifications bot (Mar 13 2026 at 14:19):

alexcrichton commented on issue #12677:

@philipc would you be up for sending a PR with that + maybe a small test/repro? That's probably reasonable enough to go ahead and land even if we're not entirely certain if it's 100% correct

view this post on Zulip Wasmtime GitHub notifications bot (Mar 14 2026 at 06:25):

philipc commented on issue #12677:

Sure. The existing tests should be sufficient, because they currently fail on macOS arm64. I guess no one runs them currently.

failures:
    native_debug::lldb::dwarf_cold_block
    native_debug::lldb::dwarf_fib_wasm
    native_debug::lldb::dwarf_fib_wasm_dwarf5
    native_debug::lldb::dwarf_fib_wasm_split4
    native_debug::lldb::dwarf_fission
    native_debug::lldb::dwarf_fraction_norm
    native_debug::lldb::dwarf_generic
    native_debug::lldb::dwarf_imported_memory
    native_debug::lldb::dwarf_multiple_codegen_units
    native_debug::lldb::dwarf_shared_memory
    native_debug::lldb::dwarf_simple
    native_debug::lldb::dwarf_spilled_frame_base

This fixes all except 2 of them.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 16 2026 at 15:13):

alexcrichton closed issue #12677:

I'm working on debugging support for WASI HTTP/Spin Rust components.
Breakpoints are correctly triggered; however, inspecting variables through LLDB/VS Code results in "no location, value may have been optimized out".

I have reproduced with a simple Rust program compiled to either wasm32-wasip1 or wasm32-wasip2:

fn main() {
    let x = 42;
    let y = "foo";
    println!("Hello, world!");
}

With this debug profile in Cargo.toml:

[profile.dev]
opt-level = 0
debug = true

Running with Wasmtime 42.0.0 (or 41.0.4) and LLDB, then listing variables results in the message no location, value may have been optimized out for all variables:

lldb -- wasmtime run -D debug-info -O opt-level=0 target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm
(lldb) target create "wasmtime"
Current executable set to '/Users/radu/.wasmtime/bin/wasmtime' (arm64).
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip1/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 94942 launched: '/Users/radu/.wasmtime/bin/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 94942 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000107e1c3b0 JIT(0x8a6028000)`dwarf_debugging_repro::main::h15ad2e2a588792ef at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x00000008a7258ca0
(int) x = <no location, value may have been optimized out>

(long) y = <no location, value may have been optimized out>

(&str) msg = <no location, value may have been optimized out>

(lldb)

Disclaimer: I have a patch to Wasmtime generated with Claude (plus description) that allows me to retrieve the variables when debugging with lldb:
(I do not claim to fully understand how it works, which is why this is not a PR; feel free to use or ignore the patch I linked):

lldb -- wasmtime-with-the-patch run -D debug-info -O opt-level=0 target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm
(lldb) settings set -- target.run-args  "run" "-D" "debug-info" "-O" "opt-level=0" "target/wasm32-wasip2/debug/dwarf-debugging-repro.wasm"
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) b src/main.rs:5
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) r
Process 96860 launched: '/Users/radu/projects/github.com/spinframework/wasmtime/target/release/wasmtime' (arm64)
3 locations added to breakpoint 1
Process 96860 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001089d86bc JIT(0xaba000000)`dwarf_debugging_repro::main::hb42100e0c21c7fa3 at main.rs:5:5
   2        let x: i32 = 42;
   3        let y: i64 = 100;
   4        let msg: &str = "hello";
-> 5        println!("x={} y={} msg={}", x, y, msg);
   6    }
Target 0: (wasmtime) stopped.
(lldb) frame variable
(WasmtimeVMContext *) __vmctx = 0x0000000abb0c40a0
(int) x = 42
(long) y = 100
(&str) msg = {
  data_ptr = (__ptr = 1048576)
  length = 5
}

Being able to support breakpoint debugging for WASI HTTP components and variable inspection support would be incredibly valuable for the Spin project. Let me know if there is anything I can help with further.

Environment:

$ lldb --version
lldb-1703.0.234.3
Apple Swift version 6.2.1 (swiftlang-6.2.1.4.8 clang-1700.4.4.1)

$ cargo --version
cargo 1.93.1 (083ac5135 2025-12-15)

Thanks!


Last updated: Mar 23 2026 at 16:19 UTC