Skip to content
| Marketplace
Sign in
Visual Studio Code>Debuggers>WinDBG for VS CodeNew to Visual Studio Code? Get it now.
WinDBG for VS Code

WinDBG for VS Code

tmidorikawa

|
14 installs
| (0) | Free
Read-only Windows crash dump analysis with WinDBG-compatible commands and LLVM-based symbol resolution. Runs on macOS and Windows without DbgEng.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

windbg-vscode

A VS Code extension for analyzing Windows crash dumps (.dmp) and, in a future release, TTD traces (.run).

It runs on macOS and Windows. There is no dependency on DbgEng.dll or dbghelp: the dump is parsed from scratch, and symbol resolution, disassembly and type information are provided by the LLVM tools installed on your machine.

Table of Contents

  • windbg-vscode
    • Table of Contents
    • Features
    • Requirements
    • Getting Started
    • Usage
      • Open a capture and see what it is
      • Find out why it crashed
      • Work through the threads
    • Commands
    • GitHub Copilot
    • Settings
    • Supported Files
    • Limitations
    • Roadmap
    • Privacy
    • License

Features

  • WinDBG-compatible experience
    • A classic WinDBG-style command window
    • Clickable command-output links for module details, thread selection, disassembly and memory inspection
    • Compatibility with the debugger commands
    • Analysis of .dmp crash dumps
    • Analysis of .run traces recorded by TTTracer (planned)
  • Symbol resolution through symbol servers
  • Invocation from GitHub Copilot for VS Code through seven bounded analysis tools

Requirements

Tool Version Purpose
Visual Studio Code 1.129.0 or later Runs the extension
LLVM 22 or later Symbol resolution, disassembly and type information
Azure CLI Current Optional authentication for runtime-configured private symbol servers

Install LLVM with brew install llvm on macOS, or use an official LLVM release on Windows. The extension discovers llvm-symbolizer, llvm-pdbutil and llvm-mc from PATH, from the standard Homebrew location, and from the standard Windows install locations. You can also point windbg.llvm.toolPath at the directory that contains them.

Without LLVM you can still open a dump and inspect its structure; commands that need symbols, disassembly or type information report that the tools are unavailable.

Private symbol server addresses and token audiences are never embedded in the repository or VSIX. Set endpoints through the machine-scoped windbg.symbols.servers setting or WINDBG_VSCODE_SYMBOL_SERVERS, then give each private endpoint a profile in the machine-scoped windbg.symbols.authentication setting (or WINDBG_VSCODE_SYMBOL_AUTHENTICATION at runtime). Two schemes are supported.

Personal access token, the scheme Azure DevOps symbol servers document:

{ "endpoint": "https://artifacts.dev.azure.com/<organization>/_apis/symbol/symsrv", "kind": "personalAccessToken" }

Create a token with the Symbols (read) scope, then run WinDBG: Set Symbol Server Credential and paste it. It is held in the operating system keychain through VS Code's secret storage, never in a setting or a synced file, and is sent as HTTP Basic with an empty user name. WinDBG: Clear Symbol Server Credential removes it.

Azure CLI, for endpoints that accept a Microsoft Entra token:

{ "endpoint": "https://symbols.example.test/store", "kind": "azureCli", "argument": "scope", "audience": "api://symbols.example.test/.default" }

argument is resource or scope. Sign in with az login first.

az login alone does not authenticate a symbol endpoint: the extension still needs one windbg.symbols.authentication profile per private endpoint to select the token resource or scope.

In both cases the credential is attached only when the normalized request endpoint exactly matches its profile, and is never forwarded to the signed blob URL the server redirects to.

Requests to an endpoint without a matching authentication profile are unauthenticated. Public servers may accept them; private servers may return a sign-in page or a refusal instead of an artifact. These responses are reported rather than retried: run WinDBG: Show Symbol Diagnostics to see what each endpoint answered, by position and HTTP status.

The extension imposes no artifact-size limit. Large product PDBs can exceed 5 GB, so automatic resolution may use substantial network bandwidth, disk space and time. An individual artifact transfer times out after nine hours. Large authenticated downloads are split into resumable parts and transient failures are retried while data continues arriving. If a server sends no data for 60 seconds, its transfer is stopped and the next configured server is tried. Run the command again to continue from saved parts after a timeout or stalled transfer. Every requested artifact is queued with at most four active acquisitions, and simultaneous requests for the same cache entry share its in-flight work. Closing the panel cancels the downloads it started. The status line shows completed artifacts out of the batch total and names an artifact still being processed. When its transfer size is known, it also shows the actual downloaded percentage and byte counts, for example Downloading (7/8): large.pdb - 50% (3.0 GiB / 6.0 GiB). Resumed parts are included without counting retries twice; unknown sizes show downloaded bytes without a percentage. The percentage describes the transferred file (the compressed form when applicable), not the whole batch. Assembly, expansion, validation and retries have distinct status labels. The command input stays disabled until the batch and command finish; incomplete acquisition and stalled transfers are reported per endpoint in WinDBG: Show Symbol Diagnostics.

Getting Started

  1. Install the extension.
  2. Open a .dmp file. It opens in the WinDBG Dump Analyzer editor.
  3. Type a command in the command window at the bottom and press Enter.

If the file opens as text instead, right-click it and choose Open With… → WinDBG Dump Analyzer.

The command input becomes available after the capture loads successfully. Unsupported files and failed loads keep it disabled with an explanation; close and reopen the capture to retry.

Usage

Command results contain WinDBG-style links. Click a module name to show its details (lmv a ...), a thread number to switch threads (~<n>s), a stack call site to disassemble it (u ...), or a memory address to inspect bytes or pointers (db ... / dps ...). Hover over a link to see its command, or use Tab and Enter to activate it from the keyboard. Linked commands use the same history and execution path as typed commands, leave unfinished input intact, and are disabled while a command or symbol download is running. Output layout and copied plain text are unchanged.

Open a capture and see what it is

The dump is parsed on a worker thread, so the editor stays responsive even for a capture of several hundred megabytes. The banner reports the architecture, the module and thread counts, and the recorded exception. vertarget describes the machine that produced the capture, and lm lists the loaded modules with the symbol state of each one.

The command window after opening a capture, showing vertarget and lm output

Find out why it crashed

!analyze -v classifies the fault, names the faulting module and thread, and prints the stack. It reports what the capture actually supports: frames recovered by scanning are labelled as such, and the output says when function names would need symbols.

!analyze -v output, showing the failure bucket, the faulting instruction and the stack

Work through the threads

~ lists the threads with their names, and k walks the current one. Switch threads with ~<n>s and walk again. A command that needs symbols fetches them for the modules it touched and then runs again, so names resolve on the first attempt; .reload loads every module at once, and windbg.symbols.autoLoad turns the automatic behaviour off.

The thread list and a stack walk

GitHub Copilot can perform the same triage through the language model tools, without changing the command window's current thread or starting an unapproved symbol download.

Automatic symbol retry freezes aliases and ENTER history before a download. Only replay-safe commands are rerun. Commands or chains that change session state or advance display positions run once, retain their output and show a warning instead; run .reload first when they need symbols. An explicit .reload, including an alias, ENTER repeat or command chain, acquires symbols before the prepared command executes.

ThreadEx lists and captured thread stacks are also used when a separate memory stream is absent. Adjacent captured ranges can be read together, with deterministic handling of overlaps. Context flags determine which registers are available: CONTROL-only contexts remain usable, while an uncaptured frame pointer is reported as unavailable rather than zero.

Commands

The command window implements the commands below. Every command in the debugger's command reference is recognized. Implemented commands check their switches against the reference, and unavailable execution, port, MSR and script commands validate their full operand grammar before reporting what they need. A mistyped switch is therefore a syntax error rather than a silently ignored argument. Breakpoint and event-filter commands retain non-firing session setup state. Type .help for the whole set grouped by category, or .help memory for one group. The 100-entry Microsoft Learn table and the extension-command table are generated directly from the command registry, so their syntax and availability columns are the same data .help and command dispatch use.

Microsoft Learn entry Registered syntax Availability in this analyzer
ENTER (Repeat Last Command) ENTER Implemented; capture-specific limits apply
$<, $><, $$<, $$><, $$>a< (Run Script File) $<File | $><File | $$<File | $$><File | $$>a<File [Args] Syntax validated; command programs are not executed
? (Command Help) ? [Expression] Implemented; capture-specific limits apply
? (Evaluate Expression) ? [Expression] Implemented; capture-specific limits apply
?? (Evaluate C++ Expression) ?? Expression Implemented; capture-specific limits apply
# (Search for Disassembly Pattern) # [Pattern] [Address [L Size]] Implemented; capture-specific limits apply
|| (System Status) || [SystemNumber] Implemented; capture-specific limits apply
||s (Set Current System) ||SystemNumber s Implemented; capture-specific limits apply
| (Process Status) | [ProcessNumber] Implemented; capture-specific limits apply
|s (Set Current Process) |ProcessNumber s Implemented; capture-specific limits apply
~ (Thread Status) ~ [ThreadNumber] Implemented; capture-specific limits apply
~e (Thread-Specific Command) ~Thread e Command Implemented; capture-specific limits apply
~f (Freeze Thread) ~Thread f Implemented; capture-specific limits apply
~u (Unfreeze Thread) ~Thread u Implemented; capture-specific limits apply
~n (Suspend Thread) ~Thread n Implemented; capture-specific limits apply
~m (Resume Thread) ~Thread m Implemented; capture-specific limits apply
~s (Set Current Thread) ~Thread s Implemented; capture-specific limits apply
~s (Change Current Processor) ~Thread s Implemented; capture-specific limits apply
a (Assemble) a Address Instruction Implemented; capture-specific limits apply
ad (Delete Alias) ad [/q] Name Implemented; capture-specific limits apply
ah (Assertion Handling) ah | ah{b|i|d} [Address] | ahc Implemented; capture-specific limits apply
al (List Aliases) al Implemented; capture-specific limits apply
as, aS (Set Alias) as [Options] Name Value Implemented; capture-specific limits apply
ba (Break on Access) ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"] Implemented; capture-specific limits apply
bc (Breakpoint Clear) bc Breakpoints Implemented; capture-specific limits apply
bd (Breakpoint Disable) bd Breakpoints Implemented; capture-specific limits apply
be (Breakpoint Enable) be Breakpoints Implemented; capture-specific limits apply
bl (Breakpoint List) bl [/L] [Breakpoints] Implemented; capture-specific limits apply
bp, bu, bm (Set Breakpoint) bp[ID] [Options] [Address [Passes]] ["CommandString"] Implemented; capture-specific limits apply
br (Breakpoint Renumber) br OldID NewID [OldID2 NewID2 ...] Implemented; capture-specific limits apply
bs (Update Breakpoint Command) bs ID ["CommandString"] Implemented; capture-specific limits apply
bsc (Update Conditional Breakpoint) bsc ID Condition ["CommandString"] Implemented; capture-specific limits apply
c (Compare Memory) c Range Address Implemented; capture-specific limits apply
d, da, db, dc, dd, dD, df, dp, dq, du, dw, dW, dyb, dyd (Display Memory) d [Options] [Range]
da [Options] [Range]
db [Options] [Range]
dc [Options] [Range]
dd [Options] [Range]
dD [Options] [Range]
df [Options] [Range]
dp [Options] [Range]
dq [Options] [Range]
du [Options] [Range]
dw [Options] [Range]
dW [Options] [Range]
dyb [Options] [Range]
dyd [Options] [Range]
Implemented; capture-specific limits apply
dda, ddp, ddu, dpa, dpp, dpu, dqa, dqp, dqu (Display Referenced Memory) dda [Options] [Range]
ddp [Options] [Range]
ddu [Options] [Range]
dpa [Options] [Range]
dpp [Options] [Range]
dpu [Options] [Range]
dqa [Options] [Range]
dqp [Options] [Range]
dqu [Options] [Range]
Implemented; capture-specific limits apply
dds, dps, dqs (Display Words and Symbols) dps [Options] [Range] Implemented; capture-specific limits apply
dg (Display Selector) dg FirstSelector [LastSelector] Unavailable; the command reports the specific reason
dl (Display Linked List) dl [Options] ListAddress MaxCount Size Implemented; capture-specific limits apply
ds, dS (Display String) ds [/c Width] Address Implemented; capture-specific limits apply
dt (Display Type) dt [Options] [Type] [Address] Implemented; capture-specific limits apply
dtx (Display Type - Extended Debugger Object Model Information) dtx [-h] [-a] [-r[n]] [Module!]Name Address Implemented; capture-specific limits apply
dv (Display Local Variables) dv [Options] [Pattern] Implemented; capture-specific limits apply
dx (Display Debugger Object Model Expression) dx [Options] Expression Implemented; capture-specific limits apply
e, ea, eb, ed, eD, ef, ep, eq, eu, ew, eza, ezu (Enter Values) e Address Values
ea Address "String"
eb Address Values
ed Address Values
eD Address Values
ef Address Values
ep Address Values
eq Address Values
eu Address "String"
ew Address Values
eza Address "String"
ezu Address "String"
Implemented; capture-specific limits apply
f, fp (Fill Memory) f Range Pattern
fp Range Pattern
Implemented; capture-specific limits apply
Syntax validated; requires physical memory
g (Go) g[a] [= StartAddress] [BreakAddress ... [; BreakCommands]] Syntax validated; requires a live target
gc (Go from Conditional Breakpoint) gc Syntax validated; requires a live target
gh (Go with Exception Handled) gh[a] [= StartAddress] [BreakAddress ...] Syntax validated; requires a live target
gn, gN (Go with Exception Not Handled) gn[a] [= StartAddress] [BreakAddress ...] Syntax validated; requires a live target
gu (Go Up) gu Syntax validated; requires a live target
ib, iw, id (Input from Port) ib Port Syntax validated; requires a kernel target
j (Execute If - Else) j Expression Command1 ; Command2 Syntax validated; command programs are not executed
k, kb, kc, kd, kp, kP, kv (Display Stack Backtrace) k [Options] [FrameCount] Implemented; capture-specific limits apply
l+, l- (Set Source Options) l{+|-}[Option] Unavailable; the command reports the specific reason
ld (Load Symbols) ld Module [/f Filename] Implemented; capture-specific limits apply
lm (List Loaded Modules) lm [Options] [a Address] [m Pattern] Implemented; capture-specific limits apply
ln (List Nearest Symbols) ln [/D] Address Implemented; capture-specific limits apply
ls, lsa (List Source Lines) ls [.] [First] [, Count]
lsa [.] Address [, First [, Count]]
Implemented; capture-specific limits apply
lsc (List Current Source) lsc Implemented; capture-specific limits apply
lse (Launch Source Editor) lse Implemented; capture-specific limits apply
lsf, lsf- (Load or Unload Source File) lsf File
lsf- File
Implemented; capture-specific limits apply
lsp (Set Number of Source Lines) lsp [-a] [LeadingLines [TrailingLines]] Implemented; capture-specific limits apply
m (Move Memory) m Range Address Implemented; capture-specific limits apply
n (Set Number Base) n [Radix] Implemented; capture-specific limits apply
ob, ow, od (Output to Port) ob Port Value Syntax validated; requires a kernel target
p (Step) p[r] [= StartAddress] [Count] ["Command"] Syntax validated; requires a live target
pa (Step to Address) pa [r] [= StartAddress] StopAddress ["Command"] Syntax validated; requires a live target
pc (Step to Next Call) pc [r] [= StartAddress] [Count] Syntax validated; requires a live target
pct (Step to Next Call or Return) pct [r] [= StartAddress] [Count] Syntax validated; requires a live target
ph (Step to Next Branching Instruction) ph [r] [= StartAddress] [Count] Syntax validated; requires a live target
pt (Step to Next Return) pt [r] [= StartAddress] [Count] ["Command"] Syntax validated; requires a live target
q, qq (Quit) q
qq
Implemented; capture-specific limits apply
qd (Quit and Detach) qd Implemented; capture-specific limits apply
r (Registers) r [Options] [Register[=Value]] Implemented; capture-specific limits apply
rdmsr (Read MSR) rdmsr MSR Syntax validated; requires a kernel target
rm (Register Mask) rm [Mask] Implemented; capture-specific limits apply
s (Search Memory) s [Options] Range Pattern Implemented; capture-specific limits apply
so (Set Kernel Debugging Options) so [NOEXTWARNING] [NOVERSIONCHECK] Implemented; capture-specific limits apply
sq (Set Quiet Mode) sq | sq{e|d} Implemented; capture-specific limits apply
ss (Set Symbol Suffix) ss {a|w|n} Implemented; capture-specific limits apply
sx, sxd, sxe, sxi, sxn, sxr, sx- (Set Exceptions) sx
sxd [-c Cmd1] [-c2 Cmd2] [-h] Event
sxe [-c Cmd1] [-c2 Cmd2] [-h] Event
sxi [-c Cmd1] [-c2 Cmd2] [-h] Event
sxn [-c Cmd1] [-c2 Cmd2] [-h] Event
sxr
sx- [-c Cmd1] [-c2 Cmd2] Event
Implemented; capture-specific limits apply
t (Trace) t [r] [= StartAddress] [Count] ["Command"] Syntax validated; requires a live target
ta (Trace to Address) ta [r] [= StartAddress] StopAddress Syntax validated; requires a live target
tb (Trace to Next Branch) tb [r] [= StartAddress] [Count] Syntax validated; requires a live target
tc (Trace to Next Call) tc [r] [= StartAddress] [Count] Syntax validated; requires a live target
tct (Trace to Next Call or Return) tct [r] [= StartAddress] [Count] Syntax validated; requires a live target
th (Trace to Next Branching Instruction) th [r] [= StartAddress] [Count] Syntax validated; requires a live target
tt (Trace to Next Return) tt [r] [= StartAddress] [Count] Syntax validated; requires a live target
u (Unassemble) u [Range]
ub [Range]
uu [Range]
Implemented; capture-specific limits apply
uf (Unassemble Function) uf [Options] Address Implemented; capture-specific limits apply
up (Unassemble from Physical Memory) up Range Syntax validated; requires physical memory
ur (Unassemble Real Mode BIOS) ur Range Unavailable; the command reports the specific reason
ux (Unassemble x86 BIOS) ux Range Unavailable; the command reports the specific reason
vercommand (Show Debugger Command Line) vercommand Implemented; capture-specific limits apply
version (Show Debugger Version) version Implemented; capture-specific limits apply
vertarget (Show Target Computer Version) vertarget Implemented; capture-specific limits apply
wrmsr (Write MSR) wrmsr MSR Value Syntax validated; requires a kernel target
wt (Trace and Watch Data) wt [WatchOptions] [= StartAddress] [EndAddress] Syntax validated; requires a live target
x (Examine Symbols) x [Options] Module!Symbol Implemented; capture-specific limits apply
z (Execute While) Command ; [Processor] z(Expression) Syntax validated; command programs are not executed

Extension commands

Extension command Registered syntax Availability in this analyzer
.reload (Reload Symbols) .reload Implemented; capture-specific limits apply
.ecxr (Display Exception Context) .ecxr Implemented; capture-specific limits apply
.exr (Display Exception Record) .exr [Address] Implemented; capture-specific limits apply
.lastevent (Display Last Event) .lastevent Implemented; capture-specific limits apply
.dumpdebug (Display Dump Stream Directory) .dumpdebug Implemented; capture-specific limits apply
.help, help (Command Help) .help [Category] Implemented; capture-specific limits apply
!teb (Display the TEB) !teb Implemented; capture-specific limits apply
!peb (Display the PEB) !peb Implemented; capture-specific limits apply
!process (Display the Process) !process Implemented; capture-specific limits apply
!thread (Display the Current Thread) !thread Implemented; capture-specific limits apply
!handle (Display Handles) !handle [Type] Implemented; capture-specific limits apply
!analyze (Analyze the Recorded Fault) !analyze [-v] Implemented; capture-specific limits apply

Expressions are hexadecimal by default; n changes that, and 0x, 0n, 0t and 0y override it for a single number. The MASM operator set is supported with its documented precedence — * / mod, + -, << >> >>>, the comparisons, and, xor and or — together with not, hi, low, the poi, by, wo, dwo and qwo dereferences, and $vvalid, $iment, $scmp, $sicmp and $spat. Registers are reached with @rip and pseudo-registers such as $ip, $teb, $peb, $ra, $exr_code and $t0 with or without the at sign; one a capture cannot answer for reports what it needs. A range is written as <address> L<count> or <address> <end address>.

Thread selectors accept an index (~1), raw TID (~~[1a4]) or expression (~[@$tid]); process selectors likewise accept an index, |~[PID] or |[Expression]. rm defaults to the basic integer registers. It can enable the segment, floating-point, MMX, debug and SIMD groups when the selected thread's saved CONTEXT contains them; rM, rF and rX override the mask for one display without changing that default. r reads or assigns comma-separated named registers, including x86/x64 subregisters, flags and vector formats; assignments are isolated per thread in the analyzer session. r. shows the registers referenced by the current decoded instruction. ~f / ~u and ~n / ~m retain synthetic freeze and suspend state for one or all threads. This state is inspectable but cannot stop or resume the captured process.

lm implements the reference filters, columns and 1m/sm forms. x implements its address/name columns, quoting, public code/data classification, wildcard filtering and sort modes; type and size fields that are absent from the public-symbol index are shown as unknown. The k variants retain their distinct clean/raw/argument/parameter/FPO presentations without inventing private parameter names. u defaults to eight instructions, uu continues across uncaptured gaps, ub reconstructs the preceding instruction boundary in one batched LLVM invocation, and uf supports call-only and instruction-count output. ARM64 encoding lengths are read from LLVM's architecture-specific output.

dt fully parses its documented options and supports the built-in _TEB / _PEB prefixes plus arbitrary structures from a cached private PDB. Array expansion, field filters, values and recursive nested pointer or structure views use llvm-pdbutil dump --types; dtx uses the same typed records. dv reads parameters and locals from dump --symbols, with its documented filters, location display and sorting options. A record's offset is measured from the register it names, or from the frame register its procedure declares; when a record declares neither, the location is reported as unavailable instead of being guessed from another register. Missing or optimized-away records are reported rather than fabricated.

MASM remains the default expression syntax. ??, @@c++( ) and @@( ) implement decimal C++ precedence, casts, sizeof, logical and bitwise operators, typed pointer arithmetic, dereference, indexing and built-in or private-PDB structure members. Short-circuited and sizeof operands are parsed without being evaluated. @@masm( ) selects MASM explicitly.

An alias defined with as or aS is substituted into a later command line wherever its name stands alone, and ${Alias}, ${/v:Alias}, ${/d:Alias}, ${/f:Alias} and ${/n:Alias} behave as documented. Aliases belong to the command window: the language model tools run the text they were given, so an alias cannot change what a command does there.

bp/bu/bm/ba retain IDs, enabled state, pass counts, commands, conditions and documented restrictions. bl supports ID lists, ranges and quoted symbolic wildcards; bc/bd/be, br, bs and bsc update that table. Address expressions may contain spaces; a trailing pass count is separated only after a complete address expression. Processor breakpoints reject duplicates whose only difference is the command string. bs clears a condition created by bsc, while a /w condition remains independent. The sx family starts from the documented exception/event defaults and retains break/handling status plus first- and second-chance commands; sxr restores the defaults. ah, so and sq retain their corresponding setup. All of this state belongs only to the open analyzer session: a post-mortem capture cannot execute, hit a breakpoint, decrement a pass counter or receive an event, and every relevant display says so.

lsf explicitly loads a local UTF-8 source file into the analyzer session; ls, lsa, lsc and lsp navigate or configure the bounded source view, lsf- unloads it, and lse opens the current line in VS Code. A session accepts at most 64 source files, 4 MiB each, and displays at most 1,000 source lines per command. Address-to-source lookup uses available symbol line records and reports when no mapping exists. l+ and l- are recognized, but their source-mode stepping and display options are not applied; this analyzer uses lsf and lsp for its source view.

The live execution families (g*, p*, t*, wt) and port/MSR commands parse their documented flags and expressions before returning the live-target or kernel-target limitation. WinDbg can run j, z and all five $< script-file forms against a crash dump; this analyzer currently validates their quoted commands, processor prefix, file names and arguments before reporting its scripting limitation. It does not execute a command program or resume the captured process.

A display command with no range continues from where the last one stopped, and starts at the instruction pointer when there has been none; /c8 and /c 8 both set how many items go on a row. A range is <address> <end address>, where the end address is part of the range, or <address> L<count>, with L-<count> ending at the address and L?<count> lifting the debugger's own guard. The count is read in the current radix; for du it counts UTF-16 characters. A minidump holds only part of the address space, so bytes it does not contain are shown as question marks rather than as zeroes or as a refusal of the whole request, and c treats a byte it cannot read as a difference rather than a match. STRING and UNICODE_STRING output follows the structure's length, so an embedded NUL is invisible without ending the value and valid surrogate pairs remain Unicode. e*, f and m write to a bounded copy-on-write memory overlay, and a assembles one instruction with llvm-mc into that overlay. Expressions, dumps, disassembly, stack walking and typed views all read the overlaid bytes. The source dump file is never modified, and closing the analyzer discards the overlay.

Commands can be chained with ;. An unsupported z segment reports its limitation without discarding output from ordinary segments before or after it. Editor actions from a chain are applied in order. Pressing ENTER on an empty line reissues the previous command line. A thread selector binds to the command that follows it, so ~0 shows a single thread, ~1k walks thread 1 without making it current, and ~*k walks the stack of every thread.

Command echoes use the current thread's prompt. ENTER repeat also works with history disabled; IME confirmation does not submit a command. Input exceeding 2,048 characters is reported and kept for correction. Clipboard failures are reported instead of claiming that copying succeeded. Large outputs trim scrollback once per received chunk while retaining the configured line limit.

The VS Code command palette also offers:

Command Description
WinDBG: Open Crash Dump Pick a dump file and open it in the analyzer
WinDBG: Run Debugger Command Focus the command window of the active analyzer
WinDBG: Clear Command Output Clear the output log
WinDBG: Copy Command Output Copy the output log to the clipboard
WinDBG: Clear Symbol Cache Delete cached artifacts and their staging files, preserving unrelated neighboring files
WinDBG: Show Symbol Diagnostics Show the detected LLVM tools and symbol server status
WinDBG: Set Symbol Server Credential Store the access token for a symbol server in the operating system keychain
WinDBG: Clear Symbol Server Credential Remove a stored symbol server access token

GitHub Copilot

The extension contributes seven language model tools, so Copilot can analyze a dump directly: windbg_openDump, windbg_analyze, windbg_stack, windbg_modules, windbg_threads, windbg_runCommand and windbg_symbolStatus. Reference them in a prompt with #windbgOpen, #windbgAnalyze, #windbgStack, #windbgModules, #windbgThreads, #windbgCommand and #windbgSymbols.

The tools share the same worker as the editor, so a dump opened in both is parsed once. They are read-only and bounded, and windbg_runCommand accepts only an allowlist of analysis commands. windbg_openDump requires an absolute path; concurrent opens wait for the actual capture result, and a failed open can be retried. A supplied windbg_stack thread index must be an integer from 0 to 4,095. Tool output is bounded to 128 KiB of UTF-8, including its truncation notice, without splitting Unicode characters. Cancelled tool invocations stop waiting and release their pending results without closing the user's shared editor. Commands that return process memory contents (db, da, du, dq, dps, s, u, uf, ub), the file and object paths recorded in the capture (lm v, lm f, lm p, lm M, !handle), or that would start a download (.reload) are not reachable from the model. The allowlist reads the command as it was written, and the tools run without alias substitution, so an alias defined in the command window cannot change what a command does for the model. ln, rm, expression-based target selectors, lm a, custom k contexts, expression-sized x /s and expression-valued rM are also excluded because their numeric expressions can dereference an address with poi; literal stack counts, symbol sizes and register masks remain available. Breakpoint, event-filter, assertion, kernel-option, quiet-mode, symbol-suffix and thread selection/freeze/suspend commands are also excluded because that mutable state belongs to the user's command-window session. The dedicated stack tool scopes a requested thread to one stack walk and restores the user's current thread.

A ready-made WinDBG Analyst agent ships with the extension at agents/windbg-analyst.agent.md. Copy it into your workspace's .github/agents/ folder to use it.

Settings

Setting Default Description
windbg.symbols.servers [] Ordered symbol server endpoints. Each entry must be an absolute https:// URL without credentials, query or fragment. Microsoft Public Symbols is always appended last. Endpoints named in an authentication profile use its selected authentication method
windbg.symbols.authentication [] Authentication profiles for private symbol servers, each { endpoint, kind, argument, audience }. kind is azureCli (default) or personalAccessToken. A credential is attached only when the request endpoint matches a profile exactly, and never reaches the signed blob URL. No credential is stored here
windbg.symbols.cachePath "" Directory used to cache downloaded PE and PDB artifacts. Must be an absolute path at least two levels below the filesystem root. Empty, or rejected, uses the extension's global storage
windbg.symbols.offline false Resolve symbols only from the verified local cache and never start a network request
windbg.symbols.autoLoad true Fetch symbols for replay-safe commands automatically. Stateful and continuation-dependent commands are not rerun; use .reload first
windbg.llvm.toolPath "" Directory containing llvm-symbolizer, llvm-pdbutil and llvm-mc. Empty auto-detects
windbg.command.historySize 200 Number of entered commands kept in the session-only history. Zero disables recall, not ENTER repeat
windbg.output.maxLines 10000 Maximum number of output lines retained per command
windbg.disassembly.syntax intel Assembly syntax used by the disassembly commands

Supported Files

Extension Status
.dmp, .mdmp, .hdmp User-mode minidump. Supported
.run TTD trace. Recognized, analysis planned

File associations accept every casing of these extensions, including .DMP, .MDMP, .HDMP and .RuN.

Limitations

  • Read-only capture file. The extension never writes to the dump and does not support live debugging. Memory and register edits, thread freeze/suspend state, breakpoints and event filters exist only in the analyzer session; they never change or resume the captured process.
  • User-mode dumps only. Kernel crash dumps are planned for a later release.
  • No TTD replay. Replaying a .run trace requires the Windows-only TTD replay engine, so it cannot run on macOS. A future release will extract trace metadata instead.
  • No managed (.NET) analysis. SOS-style commands are planned for a later release.
  • No debugger command-program execution. j, z and the $< script-file forms validate their syntax but do not execute scripts from a capture.
  • ARM64 stack unwinding is derived from the specification and is still waiting for verification against a real ARM64 capture. Results are labelled accordingly.
  • Stack frames recovered by scanning the captured stack are labelled as such. A minidump normally captures thread stacks but not the module images. Once .reload has fetched an image, frames inside it are unwound exactly from its exception directory; everything past that is recovered by scanning and is marked so the two are never confused. Scanning stays within the selected thread's stack. x64 prologue, epilogue and saved-frame-register recovery uses only captured data; unsupported unwind forms retain the scan label. Cached image payloads have a 128 MiB budget per worker. Larger images still provide bounded metadata and symbol lookup, but unwinding that needs unretained image bytes falls back to labelled scanning.
  • Private typed views depend on PDB records. _TEB and _PEB have stable built-in prefixes; other dt / dtx types and dv locals require a cached private PDB. A local whose record names no base register, and one the compiler optimized away, are reported as unavailable.

Roadmap

  • [x] Read-only custom editor and command window shell
  • [x] Minidump stream parsing and the lm / ~ / r / d* command family
  • [x] Stack walking (k), ln and expression evaluation
  • [x] Symbol server configuration, LLVM tool discovery and .reload
  • [x] Disassembly (u) and symbol-annotated pointer dumps (dps)
  • [x] Type-aware commands (dt, dx, !peb, !teb, !process, !thread, !handle)
  • [x] !analyze -v
  • [x] Session-only breakpoint, assertion and exception-filter setup
  • [x] Session source-file loading and opening the current line in VS Code
  • [x] GitHub Copilot integration
  • [ ] A detachable memory and disassembly window
  • [ ] TTD .run trace metadata extraction
  • [ ] Kernel crash dump analysis
  • [ ] SOS-style managed .NET analysis

Privacy

The capture file is strictly read-only. Symbol loading is automatic by default when a command needs it; enable windbg.symbols.offline to prevent network requests. Language model tools never start symbol downloads. Full file paths, memory contents, command lines, symbol paths and LLVM tool paths are never written to logs, to persistent state, or to test and benchmark output. Symbol downloads use configured endpoints followed by Microsoft Public Symbols, and a downloaded image or PDB is cached only when its own identity matches the one recorded in the capture. Direct responses must deliver their declared byte count, and a PDB must contain every block its MSF superblock declares before its GUID is accepted. Cache hits are revalidated; unreadable or inconclusive entries are not reported as verified. Resumable parts are tied to the source and representation rather than reused by length alone, and compressed artifacts are expanded with bounded reads instead of loading the whole archive. Local LLVM symbolization explicitly disables debuginfod downloads.

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft