Skip to content

Commit afce165

Browse files
committed
Debugging: add the debug-main world.
This PR "draws the rest of the owl" for the debug-main world (bytecodealliance/rfcs#45). This includes a WIT world that hosts debug components that have access to "host debug powers" via a debugging API, and the ability to load such a debug-component and give it control of the main program as a debuggee when using `wasmtime run`. The WIT is namespaced to `bytecodealliance:wasmtime` and is slightly aspirational in places: for example, the host does not yet implement injection of early return values or exception-throws. I intend to fill out a series of TODO issues once this all lands to track followup ("post-MVP") work. This PR does not include any debug components. I separately have a gdbstub component, with which I tested and co-developed this host-side implementation. My plan is to land it in a followup PR as a component that will be embedded in/shipped with the Wasmtime CLI and available under an easy-to-use CLI option. Once we have that gdbstub component, we can also implement end-to-end integration tests that boot up LLDB and run through an expected interaction. (Separately, those integration tests will require a release of wasi-sdk to ship an LLDB binary that we can use.) As such, there are no real tests in this PR: interesting behaviors only really occur with a full end-to-end flow. The integration with the CLI is a little awkward (we internally build another `wasmtime run` command that invokes the debug component, and tie it together with the debuggee via a special `invoke_debugger` API; this seemed less bad than reworking all of the WASI setup to be more reusable). Happy to take more ideas here.
1 parent 9593a3a commit afce165

16 files changed

Lines changed: 4704 additions & 38 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ wasmtime-wasi-threads = { workspace = true, optional = true }
6060
wasmtime-wasi-http = { workspace = true, optional = true }
6161
wasmtime-unwinder = { workspace = true }
6262
wasmtime-wizer = { workspace = true, optional = true, features = ['clap', 'wasmtime'] }
63+
wasmtime-debugger = { workspace = true, optional = true }
6364
clap = { workspace = true }
6465
clap_complete = { workspace = true, optional = true }
6566
target-lexicon = { workspace = true }
@@ -591,6 +592,7 @@ run = [
591592
"dep:tokio",
592593
"wasmtime-cli-flags/async",
593594
"wasmtime-wasi-http?/p2",
595+
"dep:wasmtime-debugger",
594596
]
595597
completion = ["dep:clap_complete"]
596598
objdump = [

crates/cli-flags/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@ wasmtime_option_group! {
273273
pub log_to_files: Option<bool>,
274274
/// Enable coredump generation to this file after a WebAssembly trap.
275275
pub coredump: Option<String>,
276+
/// Load the given debugger component and attach it to the
277+
/// main module or component.
278+
pub debugger: Option<PathBuf>,
279+
/// Pass the given command-line arguments to the debugger
280+
/// component. May be specified multiple times.
281+
#[serde(default)]
282+
pub debugger_arg: Vec<String>,
276283
}
277284

278285
enum Debug {
@@ -491,6 +498,9 @@ wasmtime_option_group! {
491498
///
492499
/// This option can be further overwritten with `--env` flags.
493500
pub inherit_env: Option<bool>,
501+
/// Inherit stdin/stdout from the parent process. On by
502+
/// default.
503+
pub inherit_stdin_stdout: Option<bool>,
494504
/// Pass a wasi config variable to the program.
495505
#[serde(skip)]
496506
pub config_var: Vec<KeyValuePair>,

crates/cli-flags/src/opt.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::{KeyValuePair, WasiNnGraph};
99
use clap::builder::{StringValueParser, TypedValueParser, ValueParserFactory};
1010
use clap::error::{Error, ErrorKind};
1111
use serde::de::{self, Visitor};
12+
use std::path::PathBuf;
13+
use std::str::FromStr;
1214
use std::time::Duration;
1315
use std::{fmt, marker};
1416
use wasmtime::{Result, bail};
@@ -344,6 +346,20 @@ impl WasmtimeOptionValue for String {
344346
}
345347
}
346348

349+
impl WasmtimeOptionValue for PathBuf {
350+
const VAL_HELP: &'static str = "=path";
351+
fn parse(val: Option<&str>) -> Result<Self> {
352+
match val {
353+
Some(val) => Ok(PathBuf::from_str(val)?),
354+
None => bail!("value must be specified with key=val syntax"),
355+
}
356+
}
357+
358+
fn display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359+
write!(f, "{self:?}")
360+
}
361+
}
362+
347363
impl WasmtimeOptionValue for u32 {
348364
const VAL_HELP: &'static str = "=N";
349365
fn parse(val: Option<&str>) -> Result<Self> {

crates/debugger/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ rust-version.workspace = true
1212
workspace = true
1313

1414
[dependencies]
15-
wasmtime = { workspace = true, features = ["debug", "std", "async"] }
15+
wasmtime = { workspace = true, features = ["debug", "std", "async", "component-model", "gc", "gc-drc"] }
16+
wasmtime-wasi = { workspace = true }
17+
wasmtime-wasi-io = { workspace = true }
1618
tokio = { workspace = true, features = ["rt", "sync", "macros"] }
1719
log = { workspace = true }
20+
async-trait = { workspace = true }
1821

1922
[dev-dependencies]
2023
# Depend on `wasmtime` again to get `cranelift` and `wat` so we can

0 commit comments

Comments
 (0)