mirror of
https://github.com/svnscha/mcp-windbg.git
synced 2026-10-19 14:22:23 +08:00
306 lines
14 KiB
Markdown
306 lines
14 KiB
Markdown
# Tools
|
|
|
|
The server exposes these MCP tools. You rarely name them directly, the model picks the right
|
|
one from your request, but this is the precise contract for each.
|
|
|
|
| Tool | Purpose |
|
|
| --- | --- |
|
|
| [`list_dumps`](#list_dumps) | List crash dump files in a directory. |
|
|
| [`open_cdb_dump`](#open_cdb_dump) | Open a dump and run the standard triage commands (`cdb.exe`). |
|
|
| [`open_cdb_remote`](#open_cdb_remote) | Attach to a user-mode remote debug server (`-remote`). |
|
|
| [`open_kd_session`](#open_kd_session) | Attach to a kernel debugging target (`-k`, `kd.exe`). |
|
|
| [`open_kd_dump`](#open_kd_dump) | Open a kernel crash dump and run the standard triage commands (`kd.exe`). |
|
|
| [`run_cdb_command`](#run_cdb_command) | Run a command on a user-mode (cdb) session. |
|
|
| [`run_kd_command`](#run_kd_command) | Run a command on a kernel (kd) session. |
|
|
| [`close_cdb_session`](#close_cdb_session) | Close a user-mode session. |
|
|
| [`close_kd_session`](#close_kd_session) | Close a kernel session. |
|
|
| [`send_ctrl_break`](#send_ctrl_break) | Break into a running target. |
|
|
| [`wait_for_break`](#wait_for_break) | Wait for a resumed target to stop. |
|
|
|
|
## Sessions and session ids
|
|
|
|
Every `open_*` tool starts a debugger process and returns an opaque **`session_id`** on the
|
|
first line of its output, for example:
|
|
|
|
```
|
|
session_id: cdb-1a2b3c4d
|
|
```
|
|
|
|
Pass that id to every follow-up call for the session - `run_*`, `close_*`, `send_ctrl_break`,
|
|
and `wait_for_break`. Sessions are persistent (the `cdb.exe`/`kd.exe` process stays alive between
|
|
calls), and several can be open at once, so you can compare dumps side by side. Close sessions
|
|
when you finish to free resources.
|
|
|
|
User-mode targets (dumps and `-remote`) run under **`cdb.exe`** and use the `cdb` tools; kernel
|
|
targets and kernel dumps run under **`kd.exe`** and use the `kd` tools. The id itself is prefixed (`cdb-…` /
|
|
`kd-…`), and the server rejects a mismatch - calling [`run_kd_command`](#run_kd_command) with a
|
|
`cdb` id returns a tool error telling you which tool to use.
|
|
|
|
## Timeouts
|
|
|
|
Each `open_*` / `run_*` call accepts an optional `timeout_seconds` to override the default for
|
|
that call. Defaults: `open_cdb_dump` and `open_kd_dump` 180s (they run `!analyze -v`), connects 60s,
|
|
`run_cdb_command` 60s, `run_kd_command` 120s (kernel memory reads over KDNET can be slow). The
|
|
server-wide [`--timeout`](cli.md) is a floor for these. On a **live** session (remote or
|
|
kernel) a command that outruns its timeout is broken into with CTRL+BREAK and the session is
|
|
resynchronized, so a slow command reports a timeout instead of wedging the session.
|
|
|
|
---
|
|
|
|
## list_dumps
|
|
|
|
List crash dump files in a directory.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `directory_path` | no | Directory to search. Defaults to the configured local crash dump location. |
|
|
| `recursive` | no | Search subdirectories as well. Defaults to `false`. |
|
|
|
|
Used by [Triage multiple dumps](../scenarios/triage.md).
|
|
|
|
---
|
|
|
|
## open_cdb_dump
|
|
|
|
Open a user-mode crash dump and run the common analysis commands (`.lastevent`, `!analyze -v`,
|
|
and optionally stack, modules, threads). Returns a `session_id`. For a kernel dump from a
|
|
bugcheck use [`open_kd_dump`](#open_kd_dump).
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `dump_path` | yes | Path to the `.dmp` file. |
|
|
| `include_stack_trace` | no | Include the stack trace (`kb`). Defaults to `false`. |
|
|
| `include_modules` | no | Include loaded module information (`lm`). Defaults to `false`. |
|
|
| `include_threads` | no | Include thread information (`~`). Defaults to `false`. |
|
|
| `symbols_path` | no | Extra symbol search path. |
|
|
| `timeout_seconds` | no | Override the open/analysis timeout (default 180s). |
|
|
|
|
Used by [Analyze a crash dump](../scenarios/crash-dump.md).
|
|
|
|
---
|
|
|
|
## open_cdb_remote
|
|
|
|
Attach to a user-mode remote debug server (a `cdb`/WinDbg `-server`), launched with `-remote`.
|
|
Returns a `session_id`. For kernel targets use [`open_kd_session`](#open_kd_session) instead:
|
|
`-remote` cannot drive a kernel cable.
|
|
|
|
If the target is running when the client attaches, the initial triage (`!peb`, `r`) breaks into
|
|
it and the result says so under `Target State`. The target stays stopped until it is resumed
|
|
with `g` or the session is closed, which detaches and resumes it.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `connection_string` | yes | Remote connection string, see formats below. |
|
|
| `include_stack_trace` | no | Include the stack trace. Defaults to `false`. |
|
|
| `include_modules` | no | Include loaded module information. Defaults to `false`. |
|
|
| `include_threads` | no | Include thread information. Defaults to `false`. |
|
|
| `symbols_path` | no | Extra symbol search path. |
|
|
| `timeout_seconds` | no | Override the connect timeout (default 60s). |
|
|
|
|
Connection string formats:
|
|
|
|
| Transport | Example |
|
|
| --- | --- |
|
|
| TCP | `tcp:Port=5005,Server=192.168.0.100` |
|
|
| Named pipe | `npipe:Pipe=MyPipe,Server=MyServer` |
|
|
| COM | `com:Port=COM1,Baud=115200` |
|
|
|
|
Used by [Debug a remote target](../scenarios/remote-debugging.md).
|
|
|
|
---
|
|
|
|
## open_kd_session
|
|
|
|
Attach to a kernel debugging target, launched with `-k` using `kd.exe`. Waits for the target to
|
|
connect, breaks in, and returns a `session_id`. This is a different mechanism from
|
|
[`open_cdb_remote`](#open_cdb_remote): kernel debugging (`-k`) and user-mode remote debugging
|
|
(`-remote`) are not interchangeable.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `connection_string` | yes | Kernel connection string, see formats below. |
|
|
| `include_stack_trace` | no | Include the stack trace. Defaults to `false`. |
|
|
| `include_modules` | no | Include loaded module information. Defaults to `false`. |
|
|
| `include_threads` | no | Include thread information. Defaults to `false`. |
|
|
| `symbols_path` | no | Extra symbol search path. |
|
|
| `timeout_seconds` | no | Override the connect/break-in timeout (default 60s). |
|
|
|
|
Connection string formats:
|
|
|
|
| Transport | Example |
|
|
| --- | --- |
|
|
| KDNET (network) | `net:port=50000,key=1.2.3.4` |
|
|
| Named pipe (VM) | `com:pipe,port=\\.\pipe\com_1,baud=115200,reconnect,resets=0` |
|
|
| Serial | `com:port=COM1,baud=115200` |
|
|
|
|
Pass the named-pipe path with real single backslashes. Because JSON escapes each backslash,
|
|
`\\.\pipe\com_1` is written `"\\\\.\\pipe\\com_1"` in a tool call. Do not add extra backslashes.
|
|
|
|
A timeout mentioning `no_debuggee` means the target is not transmitting on the transport (not
|
|
booted with debugging enabled, or another debugger already holds the connection - KDNET is
|
|
point-to-point). That is an environment issue, not a tool failure.
|
|
|
|
Used by [Debug a kernel target](../scenarios/kernel-debugging.md).
|
|
|
|
---
|
|
|
|
## open_kd_dump
|
|
|
|
Open a kernel-mode crash dump with `kd.exe` (`-z`) and run the common analysis commands
|
|
(`vertarget`, `!analyze -v`, and optionally stack, modules, threads), after any
|
|
[init commands](cli.md#init-commands). Returns a `kd` session id. It takes a complete, kernel, or
|
|
bitmap memory dump (`C:\Windows\MEMORY.DMP`) or a small memory dump
|
|
(`C:\Windows\Minidump\*.dmp`). A dump is static: there is nothing to break into or resume, so
|
|
[`send_ctrl_break`](#send_ctrl_break) and [`wait_for_break`](#wait_for_break) do not apply.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `dump_path` | yes | Path to the kernel dump file. |
|
|
| `include_stack_trace` | no | Include the stack trace (`kb`). Defaults to `false`. |
|
|
| `include_modules` | no | Include loaded module information (`lm`). Defaults to `false`. |
|
|
| `include_threads` | no | Include thread information (`~`). Defaults to `false`. |
|
|
| `symbols_path` | no | Extra symbol search path. |
|
|
| `timeout_seconds` | no | Override the open/analysis timeout (default 180s). |
|
|
|
|
Used by [Analyze a crash dump](../scenarios/crash-dump.md#kernel-dumps).
|
|
|
|
---
|
|
|
|
## run_cdb_command
|
|
|
|
Run any WinDbg command on an open user-mode (cdb) session and return its output.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `session_id` | yes | A `cdb` session id from [`open_cdb_dump`](#open_cdb_dump) or [`open_cdb_remote`](#open_cdb_remote). |
|
|
| `command` | yes | The command to run, for example `kb` or `!analyze -v`. |
|
|
| `timeout_seconds` | no | Override the command timeout (default 60s). |
|
|
|
|
---
|
|
|
|
## run_kd_command
|
|
|
|
Run any command on an open kernel (kd) session and return its output.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `session_id` | yes | A `kd` session id from [`open_kd_session`](#open_kd_session) or [`open_kd_dump`](#open_kd_dump). |
|
|
| `command` | yes | The command to run, for example `!process 0 0` or `vertarget`. |
|
|
| `timeout_seconds` | no | Override the command timeout (default 120s). |
|
|
|
|
---
|
|
|
|
## close_cdb_session
|
|
|
|
Close a user-mode session and release its `cdb.exe` process.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `session_id` | yes | The `cdb` session id to close. |
|
|
|
|
---
|
|
|
|
## close_kd_session
|
|
|
|
Close a kernel session and release its `kd.exe` process. By default this **resumes the target
|
|
machine** (sends `g`) so it runs again - a kernel target left halted at a break freezes the
|
|
whole machine. Always close a kernel session when done.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `session_id` | yes | The `kd` session id to close. |
|
|
| `resume` | no | Resume the machine on close. Defaults to `true`. Set `false` to intentionally leave it halted at the break (it stays frozen until a debugger resumes it). Ignored for a dump. |
|
|
|
|
---
|
|
|
|
## send_ctrl_break
|
|
|
|
Send a CTRL+BREAK to a live session (remote or kernel) to break into a running target. Useful
|
|
before inspecting a running remote session, or to halt a kernel target.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `session_id` | yes | A live session id (cdb remote or kd) to break into. |
|
|
|
|
A dump session has no running target, so this returns an error for `cdb` dump ids. Used by
|
|
[Debug a remote target](../scenarios/remote-debugging.md) and
|
|
[Debug a kernel target](../scenarios/kernel-debugging.md).
|
|
|
|
---
|
|
|
|
## wait_for_break
|
|
|
|
Block until a target you resumed stops again - on a bugcheck, a breakpoint, or a CTRL+BREAK from
|
|
elsewhere - and return everything the debugger printed when it did.
|
|
|
|
| Parameter | Required | Description |
|
|
| --- | --- | --- |
|
|
| `session_id` | yes | A live session id (cdb remote or kd) whose target is running. |
|
|
| `timeout_seconds` | no | How long to wait. Defaults to 300. |
|
|
|
|
It asks the debugger rather than trusting a flag, so it is right about a target that is running
|
|
for reasons this server never caused - one resumed from the machine's own console, say. If the
|
|
target is already stopped it returns immediately. If the wait expires the target is **left
|
|
running**: wait again, or halt it with [`send_ctrl_break`](#send_ctrl_break).
|
|
|
|
---
|
|
|
|
## Letting the target run
|
|
|
|
`g` and its relatives (`gh`, `gn`, `gN`, `gc`, `gu`) are different from every other command: they
|
|
hand the CPU back to the target, and the debugger prints nothing more until it stops. Sent through
|
|
[`run_cdb_command`](#run_cdb_command) or [`run_kd_command`](#run_kd_command) on a live session they
|
|
return straight away, leaving the target running - they do not wait for output, and they do not
|
|
count against the command timeout.
|
|
|
|
The server confirms the debugger actually took the resume before reporting it. Two things follow.
|
|
If the target stops again immediately - a `gu` that returns in microseconds, or a breakpoint hit
|
|
at once - you get that output instead of the "target resumed" message, because it never really
|
|
left. And a [`send_ctrl_break`](#send_ctrl_break) issued in the same breath as the `g` still
|
|
reaches the target, rather than being answered by a debugger that had not read the `g` yet.
|
|
|
|
From there you have three options:
|
|
|
|
- [`wait_for_break`](#wait_for_break) - block until the target stops, and collect the bugcheck or
|
|
breakpoint report.
|
|
- [`send_ctrl_break`](#send_ctrl_break) - halt it now.
|
|
- Just send another command. The server breaks in for you first and puts whatever the target
|
|
printed on the way to stopping - the bugcheck banner, the breakpoint report - at the head of
|
|
that command's output, so the reason it stopped is never lost.
|
|
|
|
Qualified and compound forms count too. `~0 g` and `~*g` resume the target, and in
|
|
`bp nt!NtCreateFile; g` the breakpoint runs first with its result returned to you - so a typo'd
|
|
symbol shows up as `Couldn't resolve error` instead of a wait for a break that can never come.
|
|
A `;` inside a quoted command string (`bp X ".echo hit; g"`) belongs to the breakpoint, not to
|
|
you, and is left alone.
|
|
|
|
Stepping commands (`p`, `t`, `pa`, `ta`, ...) are *not* in this family: they run a single
|
|
instruction or line and come back to the prompt, so they behave like any other command.
|
|
|
|
A second `g` while the target really is still running is refused rather than queued - it would
|
|
have resumed the target again the instant it stopped.
|
|
|
|
While [`wait_for_break`](#wait_for_break) is parked on a session, other calls on that **same**
|
|
session are refused immediately with a message pointing at
|
|
[`send_ctrl_break`](#send_ctrl_break); other sessions keep working normally, and closing the
|
|
session ends the wait.
|
|
|
|
---
|
|
|
|
## Common WinDbg commands
|
|
|
|
You can describe what you want instead of memorizing these, but they are handy to know. Run them
|
|
through [`run_cdb_command`](#run_cdb_command) (user mode) or [`run_kd_command`](#run_kd_command)
|
|
(kernel).
|
|
|
|
| Area | Commands |
|
|
| --- | --- |
|
|
| Stack | `k`, `kb`, `kv`, `~*k`, `.ecxr` |
|
|
| Memory | `db` / `dw` / `dd` / `dp <address>`, `!address <address>` |
|
|
| Heap | `!heap -p -a <address>`, `!heap -stat` |
|
|
| Threads | `~`, `~*k`, `!runaway`, `!locks` |
|
|
| Modules | `lm`, `lmv`, `!lmi <module>` |
|
|
| Analysis | `!analyze -v`, `.lastevent` |
|
|
| Kernel | `!process 0 0`, `!thread`, `vertarget`, `!pcr`, `lm m nt` |
|