Skip to content

c-api: JIT debugging of wasm guest code not enabled #9909

@puremourning

Description

@puremourning

According to the documentation it should be possible to use a source/line debugger with guest code running inside the wasmtime VM.

This works well for rust embeddings, but when using the c-api (or anything based on it, like wasmtime-cpp), the DWARF data is not exposed to the debugger.

After a little investigation and debugging, this is because the debug-builtins cargo feature is not enabled in builds of the C api crate.

Test Case

https://docs.wasmtime.dev/examples-c-debugging.html

Steps to Reproduce

  • build the C api:
cmake -S crates/c-api -B target/c-api --install-prefix "$(pwd)/artifacts" \
    -DCMAKE_BUILD_TYPE=Debug \
    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build target/c-api --parallel 16
cmake --install target/c-api
  • Build the example fib wasm
rustup target add wasm32-unknown-unknown
cargo build -p example-fib-debug-wasm --target wasm32-unknown-unknown
  • Build the example main.c above:
cd examples/fib-debug
gcc main.c -I../../artifacts/include -L../../artifacts/lib -Xlinker -rpath $(pwd)/../../artifacts/lib -Xlinker -lwasmtime
  • Run the example in debugger (e.g. lldb)
ben@BenMBP2021 wasmtime % lldb examples/fib-debug/a.out
(lldb) target create "examples/fib-debug/a.out"
Current executable set to '/Users/ben/Development/wasm/wasmtime/examples/fib-debug/a.out' (arm64).
(lldb) settings set plugin.jit-loader.gdb.enable on

(lldb) break set -f examples/fib-debug/wasm/fib.rs -l 3
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.

(lldb) run
Process 55426 launched: '/Users/ben/Development/wasm/wasmtime/examples/fib-debug/a.out' (arm64)
Initializing...
Loading binary...
Compiling module...
Instantiating module...
Calling fib...
> fib(6) = 21
Shutting down...
Done.
Process 55426 exited with status = 0 (0x00000000)

Expected Results

  • Breakpoint is hit in the fib.rs file

Actual Results

  • No breakpoint is hit

Versions and Environment

Wasmtime version or commit: 01a43ed

Operating system: macOS

Architecture: arm64

Extra Info

I made a quick patch to enable the feature, repeated the test above and it works.

ben@BenMBP2021 wasmtime % lldb examples/fib-debug/a.out
(lldb) target create "examples/fib-debug/a.out"
Current executable set to '/Users/ben/Development/wasm/wasmtime/examples/fib-debug/a.out' (arm64).
(lldb) break set -f /Users/ben/Devel^Cment/wasm/wasmtime/examples/fib-debug/wasm/fib.rs -l 3                                                bck?options                                                                                                                                 b
(lldb) settings set plugin.jit-loader.gdb.enable on
(lldb) break set -f examples/fib-debug/wasm/fib.rs -l 3
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) run
Process 55596 launched: '/Users/ben/Development/wasm/wasmtime/examples/fib-debug/a.out' (arm64)
Initializing...
Loading binary...
Compiling module...
1 location added to breakpoint 1
Instantiating module...
Calling fib...
Process 55596 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100090040 JIT(0x1402a8000)`fib(n=6) at fib.rs:3:17
   1   	#[no_mangle]
   2   	pub extern "C" fn fib(n: u32) -> u32 {
-> 3   	    let mut a = 1;
   4   	    let mut b = 1;
   5   	    for _ in 0..n {
   6   	        let t = a;
   7   	        a = b;
JIT(0x1402a8000)`fib:
->  0x100090040 <+64>: mov    w0, #0x1 ; =1
    0x100090044 <+68>: ldr    x1, [x2, #0x60]
    0x100090048 <+72>: add    x1, x1, #0x10
    0x10009004c <+76>: str    w0, [x1, w22, uxtw]
Target 0: (a.out) stopped.
warning: This version of LLDB has no plugin for the language "rust". Inspection of frame variables will be limited.
(lldb)

Here's the trivial patch:

commit 8f69c41d998ddb33b1d099b913f104cb93ba1b3d (HEAD -> main)
Author: Ben Jackson <puremourning@gmail.com>
Date:   Sat Dec 28 15:31:54 2024 +0000

    Enable JIT DWARF info in c-api

diff --git a/crates/c-api/Cargo.toml b/crates/c-api/Cargo.toml
index 84b7d45ed..d77312f42 100644
--- a/crates/c-api/Cargo.toml
+++ b/crates/c-api/Cargo.toml
@@ -56,5 +56,6 @@ gc-drc = ["wasmtime/gc-drc"]
 gc-null = ["wasmtime/gc-null"]
 cranelift = ['wasmtime/cranelift']
 winch = ['wasmtime/winch']
+debug-builtins = ['wasmtime/debug-builtins']
 # ... if you add a line above this be sure to change the other locations
 # marked WASMTIME_FEATURE_LIST
diff --git a/crates/c-api/artifact/Cargo.toml b/crates/c-api/artifact/Cargo.toml
index 1eb6659ec..8aa846d23 100644
--- a/crates/c-api/artifact/Cargo.toml
+++ b/crates/c-api/artifact/Cargo.toml
@@ -38,6 +38,7 @@ default = [
   'gc-null',
   'cranelift',
   'winch',
+  'debug-builtins',
   # ... if you add a line above this be sure to change the other locations
   # marked WASMTIME_FEATURE_LIST
 ]
@@ -58,5 +59,6 @@ gc-drc = ["wasmtime-c-api/gc-drc"]
 gc-null = ["wasmtime-c-api/gc-null"]
 cranelift = ["wasmtime-c-api/cranelift"]
 winch = ["wasmtime-c-api/winch"]
+debug-builtins = ["wasmtime-c-api/debug-builtins"]
 # ... if you add a line above this be sure to read the comment at the end of
 # `default`
diff --git a/crates/c-api/build.rs b/crates/c-api/build.rs
index b500fd1bf..12bc0b501 100644
--- a/crates/c-api/build.rs
+++ b/crates/c-api/build.rs
@@ -19,6 +19,7 @@ const FEATURES: &[&str] = &[
     "GC_NULL",
     "CRANELIFT",
     "WINCH",
+    "DEBUG_BUILTINS",
 ];
 // ... if you add a line above this be sure to change the other locations
 // marked WASMTIME_FEATURE_LIST
diff --git a/crates/c-api/cmake/features.cmake b/crates/c-api/cmake/features.cmake
index 385c13965..727412a04 100644
--- a/crates/c-api/cmake/features.cmake
+++ b/crates/c-api/cmake/features.cmake
@@ -43,5 +43,6 @@ feature(gc-null ON)
 feature(async ON)
 feature(cranelift ON)
 feature(winch ON)
+feature(debug-builtins ON)
 # ... if you add a line above this be sure to change the other locations
 # marked WASMTIME_FEATURE_LIST
diff --git a/crates/c-api/include/wasmtime/conf.h.in b/crates/c-api/include/wasmtime/conf.h.in
index 3dff987ac..03f4debf9 100644
--- a/crates/c-api/include/wasmtime/conf.h.in
+++ b/crates/c-api/include/wasmtime/conf.h.in
@@ -25,6 +25,7 @@
 #cmakedefine WASMTIME_FEATURE_ASYNC
 #cmakedefine WASMTIME_FEATURE_CRANELIFT
 #cmakedefine WASMTIME_FEATURE_WINCH
+#cmakedefine WASMTIME_FEATURE_DEBUG_BUILTINS
 // ... if you add a line above this be sure to change the other locations
 // marked WASMTIME_FEATURE_LIST

I'm not clear if the issue here is the feature should be enabled, and the docs are right, or a decision was made to not enable it, and the docs are wrong, or if there is some other way to enable this feature in the C-api or other C embeddings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIncorrect behavior in the current implementation that needs fixing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions