Skip to content

Commit 49732df

Browse files
committed
Enable native debugging for wasm modules/components
Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent c08ed30 commit 49732df

File tree

15 files changed

+357
-51
lines changed

15 files changed

+357
-51
lines changed

.vscode/launch.json

Lines changed: 89 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,101 @@
11
{
2-
// Use IntelliSense to learn about possible attributes.
3-
// Hover to view descriptions of existing attributes.
4-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5-
// this can be used to debug tests
6-
"version": "0.2.0",
2+
"inputs": [
3+
{
4+
"id": "program",
5+
"type": "promptString",
6+
"default": "x64/debug/wasm_runtime",
7+
"description": "Path to the program to debug",
8+
}
9+
],
710
"configurations": [
811
{
912
"type": "lldb",
1013
"request": "launch",
11-
"name": "Cargo test",
14+
"name": "Debug example 'guest-debugging'",
15+
"cargo": {
16+
"args": [
17+
"build",
18+
"--example=guest-debugging",
19+
"--package=hyperlight-wasm",
20+
"--features=gdb",
21+
],
22+
"filter": {
23+
"name": "guest-debugging",
24+
"kind": "example"
25+
}
26+
},
27+
"env": {
28+
"RUST_DIR_FOR_DEBUGGING_TESTS": "${workspaceFolder}/src/hyperlight_wasm",
29+
},
30+
"args": [],
31+
"cwd": "${workspaceFolder}"
32+
},
33+
{
34+
"type": "lldb",
35+
"request": "launch",
36+
"name": "Debug example 'rust_wasm_examples'",
1237
"cargo": {
13-
"args": [
14-
"test",
15-
"--profile=dev",
16-
"--lib",
17-
"--no-run"
18-
19-
],
20-
"filter": {
21-
"name": "hyperlight_wasm",
22-
"kind": "lib"
23-
}
38+
"args": [
39+
"build",
40+
"--example=rust_wasm_examples",
41+
"--package=hyperlight-wasm",
42+
],
43+
"filter": {
44+
"name": "rust_wasm_examples",
45+
"kind": "example"
46+
}
2447
},
2548
"env": {
26-
"RUST_DIR_FOR_DEBUGGING_TESTS": "${workspaceFolder}/src/hyperlight_wasm"
49+
"RUST_DIR_FOR_DEBUGGING_TESTS": "${workspaceFolder}/src/hyperlight_wasm",
50+
},
51+
"args": [],
52+
"cwd": "${workspaceFolder}"
53+
},
54+
{
55+
"name": "Remote GDB attach",
56+
"type": "cppdbg",
57+
"request": "launch",
58+
"program": "${input:program}",
59+
"args": [],
60+
"stopAtEntry": true,
61+
"hardwareBreakpoints": {
62+
"require": false,
63+
"limit": 4
2764
},
28-
"args": [
29-
"--exact",
30-
"sandbox::loaded_wasm_sandbox::tests::test_call_host_func_with_vecbytes"
65+
"cwd": "${workspaceFolder}",
66+
"environment": [],
67+
"externalConsole": false,
68+
"MIMode": "gdb",
69+
"miDebuggerPath": "/usr/bin/gdb",
70+
"miDebuggerServerAddress": "localhost:8080",
71+
"setupCommands": [
72+
{
73+
"description": "Enable pretty-printing for gdb",
74+
"text": "-enable-pretty-printing",
75+
"ignoreFailures": true
76+
},
77+
{
78+
"description": "Set Disassembly Flavor to Intel",
79+
"text": "-gdb-set disassembly-flavor intel",
80+
"ignoreFailures": true
81+
},
82+
//{
83+
//"description": "Add symbols",
84+
//"text": "symbol-file ${workspaceFolder}/x64/debug/rust_wasm_samples.wasm",
85+
//"ignoreFailures": true
86+
//}
3187
]
32-
}
88+
},
89+
{
90+
"name": "Remote LLDB attach",
91+
"type": "lldb",
92+
"request": "launch",
93+
"targetCreateCommands": [
94+
"target create ${input:program}",
95+
],
96+
"processCreateCommands": [
97+
"gdb-remote localhost:8080"
98+
],
99+
},
33100
]
34101
}

Cargo.lock

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Justfile

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ensure-tools:
1919
cargo install cargo-component --locked --version 0.21.1
2020
cargo install wit-bindgen-cli --locked --version 0.43.0
2121

22-
build-all target=default-target: (build target) (build-wasm-examples target) (build-rust-wasm-examples target) (build-rust-component-examples target) (build-wasm-runtime target)
22+
build-all target=default-target features="": (build target features) (build-wasm-examples target features) (build-rust-wasm-examples target features) (build-rust-component-examples target) (build-wasm-runtime target features)
2323

2424
build target=default-target features="": (fmt-check)
2525
cargo build {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --verbose --profile={{ if target == "debug" {"dev"} else { target } }}
@@ -32,23 +32,23 @@ compile-wit:
3232
wasm-tools component wit ./src/wasmsamples/components/runcomponent.wit -w -o ./src/wasmsamples/components/runcomponent-world.wasm
3333
wasm-tools component wit ./src/component_sample/wit/example.wit -w -o ./src/component_sample/wit/component-world.wasm
3434

35-
build-wasm-runtime target=default-target:
36-
cd ./src/wasm_runtime && cargo build --verbose --profile={{ if target == "debug" {"dev"} else { target } }} && rm -R target
35+
build-wasm-runtime target=default-target features="":
36+
cd ./src/wasm_runtime && cargo build --verbose {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} && rm -R target
3737

38-
build-wasm-examples target=default-target: (compile-wit)
39-
{{ build-wasm-examples-command }} {{target}}
38+
build-wasm-examples target=default-target features="": (compile-wit)
39+
{{ build-wasm-examples-command }} {{target}} {{features}}
4040

41-
build-rust-wasm-examples target=default-target: (mkdir-redist target)
41+
build-rust-wasm-examples target=default-target features="": (mkdir-redist target)
4242
rustup target add wasm32-unknown-unknown
4343
cd ./src/rust_wasm_samples && cargo build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
44-
cargo run -p hyperlight-wasm-aot compile ./src/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot
44+
cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile ./src/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot
4545

46-
build-rust-component-examples target=default-target: (compile-wit)
46+
build-rust-component-examples target=default-target features="": (compile-wit)
4747
# use cargo component so we don't get all the wasi imports https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#relationship-with-wasm32-wasip2
4848
# we also explicitly target wasm32-unknown-unknown since cargo component might try to pull in wasi imports https://github.com/bytecodealliance/cargo-component/issues/290
4949
rustup target add wasm32-unknown-unknown
5050
cd ./src/component_sample && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
51-
cargo run -p hyperlight-wasm-aot compile --component ./src/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./x64/{{ target }}/component_sample.aot
51+
cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile --component ./src/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./x64/{{ target }}/component_sample.aot
5252

5353
check target=default-target:
5454
cargo check --profile={{ if target == "debug" {"dev"} else { target } }}

src/hyperlight_wasm/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ name = "helloworld"
2929
path = "examples/helloworld/main.rs"
3030
test = true
3131

32+
[[example]]
33+
name = "guest-debugging"
34+
path = "examples/guest-debugging/main.rs"
35+
test = true
36+
3237
[[example]]
3338
name = "hostfuncs"
3439
path = "examples/hostfuncs/main.rs"
@@ -52,6 +57,7 @@ tracing = "0.1.27"
5257
log = "0.4.27"
5358
cfg-if = { version = "1" }
5459
metrics = "0.24.2"
60+
env_logger = "0.11.8"
5561

5662
[target.'cfg(windows)'.dependencies]
5763
windows = { version = "0.61", features = ["Win32_System_Threading"] }
@@ -81,6 +87,7 @@ function_call_metrics = ["hyperlight-host/function_call_metrics"]
8187
seccomp = ["hyperlight-host/seccomp"]
8288
print_debug = ["hyperlight-host/print_debug"]
8389
crashdump = ["hyperlight-host/crashdump"]
90+
gdb = ["hyperlight-host/gdb"]
8491
kvm = ["hyperlight-host/kvm"]
8592
mshv2 = ["hyperlight-host/mshv2"]
8693
mshv3 = ["hyperlight-host/mshv3"]

src/hyperlight_wasm/build.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fn build_wasm_runtime() -> PathBuf {
125125
env_vars.retain(|(key, _)| !key.starts_with("CARGO_"));
126126

127127
let mut cargo_cmd = std::process::Command::new(&cargo_bin);
128-
let cmd = cargo_cmd
128+
let mut cmd = cargo_cmd
129129
.arg("build")
130130
.arg("--profile")
131131
.arg(cargo_profile)
@@ -137,6 +137,12 @@ fn build_wasm_runtime() -> PathBuf {
137137
.envs(env_vars)
138138
.env("PATH", path_with(&toolchain_dir))
139139
.env("HYPERLIGHT_GUEST_TOOLCHAIN_ROOT", &toolchain_dir);
140+
141+
// Add --features gdb if the gdb feature is enabled for this build script
142+
if std::env::var("CARGO_FEATURE_GDB").is_ok() {
143+
cmd = cmd.arg("--features").arg("gdb");
144+
}
145+
140146
let status = cmd
141147
.status()
142148
.unwrap_or_else(|e| panic!("could not run cargo build wasm_runtime: {}", e));
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
Copyright 2025 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
use examples_common::get_wasm_module_path;
18+
use hyperlight_host::HyperlightError;
19+
use hyperlight_wasm::{Result, SandboxBuilder};
20+
21+
fn get_time_since_boot_microsecond() -> Result<i64> {
22+
let res = std::time::SystemTime::now()
23+
.duration_since(std::time::SystemTime::UNIX_EPOCH)?
24+
.as_micros();
25+
i64::try_from(res).map_err(HyperlightError::IntConversionFailure)
26+
}
27+
28+
fn main() -> Result<()> {
29+
let tests = [
30+
(
31+
"HelloWorld.aot",
32+
"HelloWorld",
33+
"Message from Rust Example to Wasm Function".to_string(),
34+
),
35+
// (
36+
// "rust_wasm_samples.aot",
37+
// "add",
38+
// (5i32, 3i32),
39+
// ),
40+
];
41+
for (idx, case) in tests.iter().enumerate() {
42+
let (mod_path, fn_name, params_opt) = case;
43+
44+
let mut sandbox = SandboxBuilder::new()
45+
.with_guest_input_buffer_size(2 * 1024 * 1024) // 2 MiB
46+
.with_guest_heap_size(10 * 1024 * 1024) // 4 MiB
47+
.with_debugging_enabled(8080)
48+
.build()?;
49+
50+
let wasm_sandbox = match mod_path.starts_with("RunWasm") {
51+
true => {
52+
sandbox
53+
.register(
54+
"GetTimeSinceBootMicrosecond",
55+
get_time_since_boot_microsecond,
56+
)
57+
.unwrap();
58+
59+
sandbox.load_runtime()?
60+
}
61+
false => sandbox.load_runtime()?,
62+
};
63+
64+
let mod_path = get_wasm_module_path(mod_path)?;
65+
66+
// Load a Wasm module into the sandbox
67+
let mut loaded_wasm_sandbox = wasm_sandbox.load_module(mod_path)?;
68+
69+
if *fn_name == "Echo" {
70+
// Call a function in the Wasm module
71+
let result: String =
72+
loaded_wasm_sandbox.call_guest_function(fn_name, params_opt.clone())?;
73+
println!(
74+
"Result from calling Echo Function in Wasm Module \
75+
test case {idx}) is: {}",
76+
result
77+
);
78+
} else if *fn_name == "HelloWorld" {
79+
// Call a function in the Wasm module
80+
let result: i32 =
81+
loaded_wasm_sandbox.call_guest_function(fn_name, params_opt.clone())?;
82+
83+
println!(
84+
"Result from calling HelloWorld Function in Wasm Module \
85+
test case {idx}) is: {}",
86+
result
87+
);
88+
}
89+
}
90+
Ok(())
91+
}

0 commit comments

Comments
 (0)