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-wasip1orwasm32-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 = trueRunning 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 outfor 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!
radu-matei added the bug label to Issue #12677.
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.
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-wasip1orwasm32-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 = trueRunning 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 outfor 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!
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-wasip1orwasm32-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 = trueRunning 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 outfor 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!
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.
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.
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.
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.
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.
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?
alexcrichton added the wasmtime:debugging label to Issue #12677.
alexcrichton commented on issue #12677:
Happy to talk about this in the next Wasmtime meeting as well to see what everyone thinks...
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.
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-wasip1orwasm32-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 = trueRunning 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 outfor 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!
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!
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.
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 #49439The ones relevant to
xare: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
xas long asx2andw24are 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::vcodetrace 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
p24iis 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 ofx.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.
philipc commented on issue #12677:
It appears that what happens is:
- during translation we add an instruction to extend the memory index
- and add a value label alias for the extended memory index
- but during lowering that uextend instruction is not emitted (it appears to be folded into the store with
uxtw)- so we end up with a value label for a vreg that was not needed and thus not emitted
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 }
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
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_baseThis fixes all except 2 of them.
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-wasip1orwasm32-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 = trueRunning 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 outfor 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