reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
---
|
||||
name: windbg-diagnostic-method
|
||||
description: Use with every WinDbg plugin investigation to apply evidence-first reasoning, confidence calibration, contrarian review, structured reporting, and deterministic validation. Not a bug-family-specific triage skill.
|
||||
user-invocable: false
|
||||
---
|
||||
# WinDbg Diagnostic Method
|
||||
|
||||
Apply this method alongside the bug-family-specific skill selected for an
|
||||
investigation. Pattern matches route the investigation; they do not prove the
|
||||
root cause.
|
||||
|
||||
## Evidence ladder
|
||||
|
||||
Prefer direct evidence in this order:
|
||||
|
||||
1. Faulting instruction/context, bugcheck or exception parameters, and resource
|
||||
owners/waiters from the actual dump or trace.
|
||||
2. Matching symbols and the user's authorized source for the involved build.
|
||||
3. Allocation/free, Verifier, IRP, lock, ETW, WCT, or TTD history captured for
|
||||
the same failure.
|
||||
4. Controlled reproduction and instrumentation.
|
||||
5. Pattern guidance as a hypothesis only.
|
||||
|
||||
Never claim commands, source access, or artifacts that are unavailable in the
|
||||
session.
|
||||
|
||||
## First-pass normalization
|
||||
|
||||
- Confirm process dump versus kernel dump and target architecture/build.
|
||||
- Load public Windows symbols and matching symbols for user/vendor modules.
|
||||
- Record missing pages, symbols, related-process dumps, trace scope, and tool
|
||||
availability.
|
||||
- User-mode exception: `.exr -1`, `.ecxr`, stack, and registers.
|
||||
- Kernel bugcheck: `.bugcheck`, `!analyze -v`, then documented context/trap
|
||||
recovery for that code.
|
||||
- Hang: identify the affected operation, wait type, owner/server, and deepest
|
||||
supported blocker.
|
||||
- Memory: distinguish corruption, address-space pressure, and commit/limit
|
||||
failures before choosing a fix.
|
||||
|
||||
## Five-phase investigation
|
||||
|
||||
1. **OBSERVE**: establish dump/trace type, architecture, symbols, code, stack,
|
||||
registers, thread/resource state, and missing evidence.
|
||||
2. **HYPOTHESIZE**: form a specific primary mechanism and at least two plausible
|
||||
alternatives when the evidence permits.
|
||||
3. **TEST**: identify direct debugger, source, trace, or reproduction evidence
|
||||
that distinguishes the hypotheses. Absence of evidence is not evidence of
|
||||
absence.
|
||||
4. **EVALUATE**: record supporting, contradictory, and missing evidence.
|
||||
5. **CONCLUDE or PIVOT**: name the violated invariant and verification plan, or
|
||||
remain `candidate-pending-verification`.
|
||||
|
||||
## Routing index
|
||||
|
||||
| Evidence | Skill |
|
||||
|---|---|
|
||||
| Native user-mode exception in an app, service, or UMDF/user-mode driver host | `windbg-user-exception-triage` |
|
||||
| User-mode heap corruption or allocation/free history | `windbg-user-heap-corruption-investigation` |
|
||||
| Cross-thread/process, COM/RPC, or service wait | `windbg-user-wait-chain-analysis` |
|
||||
| User-mode TTD history question | `windbg-user-ttd-reverse-debugging-triage` |
|
||||
| User-mode VA fragmentation, allocation failure, or commit pressure | `windbg-user-virtual-memory-exhaustion` |
|
||||
| Thread-affine lock across coroutine suspension | `windbg-user-mutex-held-across-co-await` |
|
||||
| Kernel bugcheck, trap frame, or saved context | `windbg-kernel-bugcheck-triage` |
|
||||
| Driver Verifier violation | `windbg-kernel-verifier-triage` |
|
||||
| Outstanding/power IRP, completion, or cancellation | `windbg-kernel-irp-lifecycle-triage` |
|
||||
| Kernel lock owner/waiter chain | `windbg-kernel-lock-deadlock-triage` |
|
||||
|
||||
These are the complete bug-family routes. Continue evidence-led reasoning for
|
||||
unsupported families; never dispatch to an absent skill.
|
||||
|
||||
## Routing depth
|
||||
|
||||
- **Fast (indicative diagnosis confidence >=0.80)**: validate the apparent
|
||||
pattern, its required evidence, and plausible alternatives.
|
||||
- **Validate (0.40-0.79)**: test the leading pattern and at least one plausible
|
||||
alternative through the full cycle.
|
||||
- **Full reasoning (<0.40 or no match)**: reason from observations and preserve
|
||||
explicit uncertainty.
|
||||
|
||||
Confidence is explanatory judgment, not measured probability.
|
||||
|
||||
## Trigger and fix gates
|
||||
|
||||
- Verify the trigger in the dump, disassembly, source, trace, or controlled
|
||||
reproduction before declaring a final fix.
|
||||
- Name the violated invariant and the parties or path that violate it.
|
||||
- Separate the detector or victim from the original writer, freeing actor, or
|
||||
resource holder.
|
||||
- A fix must restore the violated invariant, not merely suppress the reproducer.
|
||||
- If the trigger is unverified, use `candidate-pending-verification`, set the
|
||||
fix to null or a verification plan, and name the evidence/fix matrix needed.
|
||||
- Do not blame a module solely from a bucket or `MODULE_NAME`.
|
||||
|
||||
## Fix-confidence calibration
|
||||
|
||||
Diagnosis confidence and fix confidence are separate. Every proposed fix must
|
||||
declare `fix_confidence` and one `fix_code_path_coverage` value:
|
||||
|
||||
| Fix confidence | Required coverage |
|
||||
|---|---|
|
||||
| `>=0.90` | `read-this-session`: the actual fix path was read in this investigation. |
|
||||
| `0.70-0.89` | `read-prior-session` or `symbol-or-disassembly`: direct coverage exists, but the complete source path was not read in this investigation. |
|
||||
| `0.50-0.69` | `pattern-only`, or incomplete symbol/disassembly evidence. Treat the fix as a candidate. |
|
||||
| `<0.50` | `not-read`: no direct fix-path coverage. Keep the diagnosis candidate-pending-verification and set the fix to null or a verification plan. |
|
||||
|
||||
Lower confidence is always allowed when evidence quality, path coverage, or
|
||||
alternatives warrant it. Never raise confidence to fit the table.
|
||||
|
||||
## Independent review
|
||||
|
||||
Before finalizing a full diagnosis:
|
||||
|
||||
1. When the host supports the bundled Copilot agents, invoke the `contrarian`
|
||||
agent once with the complete proposed diagnosis.
|
||||
2. When the host cannot run that agent, state that the independent review did
|
||||
not run; do not silently substitute inline self-review.
|
||||
3. If the verdict is `CHALLENGED`, test the counter-hypothesis with direct
|
||||
evidence, then downgrade confidence or remain pending verification.
|
||||
4. Stop after one loopback. A second challenge remains pending verification.
|
||||
|
||||
Record `contrarian_loopback` as the Boolean `true` or `false`.
|
||||
|
||||
## Report contract
|
||||
|
||||
A full report contains these H2 sections in order:
|
||||
|
||||
1. Analysis
|
||||
2. Root Cause
|
||||
3. Fix
|
||||
4. Reasoning Chain
|
||||
5. Alternatives Considered
|
||||
6. Trigger Verification
|
||||
7. Mermaid
|
||||
8. Contrarian Verdict
|
||||
9. JSON Output Contract Summary
|
||||
|
||||
The Trigger Verification section must distinguish observed, contradictory, and
|
||||
missing evidence plus fix validation. Mermaid must reflect verified evidence.
|
||||
The JSON summary must include:
|
||||
|
||||
- `diagnosis_status`
|
||||
- `routing_path`
|
||||
- `root_cause`
|
||||
- `confidence`
|
||||
- `fix_confidence`
|
||||
- `fix_code_path_coverage`
|
||||
- `contrarian_review`
|
||||
- `contrarian_loopback`
|
||||
|
||||
## Deterministic report validation
|
||||
|
||||
After writing the report, run the bundled validator with PowerShell 7:
|
||||
|
||||
```powershell
|
||||
pwsh -NoProfile -File <skill-directory>\scripts\validate-diagnosis-output.ps1 `
|
||||
-Path <diagnosis-markdown-path>
|
||||
```
|
||||
|
||||
Use the installed `windbg-diagnostic-method` directory for
|
||||
`<skill-directory>`. The script checks each section body independently,
|
||||
requires at least two alternatives, accepts explicit or implicit Mermaid
|
||||
participants, parses the JSON summary, and exits nonzero on failure.
|
||||
|
||||
Correct failed checks and rerun the script before presenting the report as
|
||||
structurally complete. Structural validation does not replace technical review.
|
||||
|
||||
## Safety and privacy
|
||||
|
||||
Dumps, traces, ETLs, CABs, source, paths, tokens, and memory contents can be
|
||||
sensitive. Obtain authorization before capture, configuration changes, or
|
||||
sharing. Verifier and Page Heap can disrupt workloads and require a recoverable
|
||||
test plan plus restoration steps. Public feedback follows `FEEDBACK.md` and
|
||||
defaults to a minimal reviewed summary with no automatic attachments.
|
||||
|
||||
## Feedback
|
||||
|
||||
For feedback about this method or validator, follow the package `FEEDBACK.md`.
|
||||
Do not attach private diagnosis files automatically.
|
||||
@@ -0,0 +1,169 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
|
||||
throw "Diagnosis file not found: $Path"
|
||||
}
|
||||
|
||||
$resolvedPath = (Resolve-Path -LiteralPath $Path).Path
|
||||
$content = Get-Content -LiteralPath $resolvedPath -Raw
|
||||
|
||||
function Get-SectionMatch {
|
||||
param([Parameter(Mandatory = $true)][string]$HeadingPattern)
|
||||
|
||||
$pattern = "(?ims)^##\s+(?:$HeadingPattern)\b[^\r\n]*\r?\n(?<body>.*?)(?=^##\s+|\z)"
|
||||
return [regex]::Match($content, $pattern)
|
||||
}
|
||||
|
||||
function Test-MermaidDiagram {
|
||||
$blocks = [regex]::Matches($content, '(?ims)^```mermaid\s*\r?\n(?<body>.*?)^```\s*$')
|
||||
foreach ($block in $blocks) {
|
||||
$body = $block.Groups["body"].Value
|
||||
|
||||
if ($body -match '(?im)^\s*sequenceDiagram\s*$') {
|
||||
$actors = [System.Collections.Generic.HashSet[string]]::new(
|
||||
[System.StringComparer]::OrdinalIgnoreCase
|
||||
)
|
||||
|
||||
foreach ($match in [regex]::Matches(
|
||||
$body,
|
||||
'(?im)^\s*(?:participant|actor)\s+([A-Za-z0-9_.-]+)'
|
||||
)) {
|
||||
[void]$actors.Add($match.Groups[1].Value)
|
||||
}
|
||||
|
||||
foreach ($match in [regex]::Matches(
|
||||
$body,
|
||||
'(?im)^\s*([A-Za-z0-9_.-]+)\s*(?:--?>>|->>|--?>|--x|-x|--\)|-\))\s*([A-Za-z0-9_.-]+)\s*:'
|
||||
)) {
|
||||
[void]$actors.Add($match.Groups[1].Value)
|
||||
[void]$actors.Add($match.Groups[2].Value)
|
||||
}
|
||||
|
||||
if ($actors.Count -ge 2) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($body -match '(?im)^\s*(?:flowchart|graph)\b') {
|
||||
$nodes = [System.Collections.Generic.HashSet[string]]::new(
|
||||
[System.StringComparer]::OrdinalIgnoreCase
|
||||
)
|
||||
|
||||
foreach ($match in [regex]::Matches(
|
||||
$body,
|
||||
'(?im)^\s*([A-Za-z0-9_]+).*?(?:-->|---|-.->|==>)\s*([A-Za-z0-9_]+)'
|
||||
)) {
|
||||
[void]$nodes.Add($match.Groups[1].Value)
|
||||
[void]$nodes.Add($match.Groups[2].Value)
|
||||
}
|
||||
|
||||
if ($nodes.Count -ge 2) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
$analysis = Get-SectionMatch "Analysis"
|
||||
$rootCause = Get-SectionMatch "Root Cause"
|
||||
$fix = Get-SectionMatch "Fix"
|
||||
$reasoning = Get-SectionMatch "Reasoning Chain"
|
||||
$alternatives = Get-SectionMatch "Alternatives(?: Considered)?"
|
||||
$trigger = Get-SectionMatch "Trigger Verification"
|
||||
$contrarian = Get-SectionMatch "Contrarian Verdict"
|
||||
|
||||
$alternativeCount = 0
|
||||
if ($alternatives.Success) {
|
||||
$alternativeCount = [regex]::Matches(
|
||||
$alternatives.Groups["body"].Value,
|
||||
'(?m)^\s*(?:[-*+]\s+|\d+[.)]\s+)'
|
||||
).Count
|
||||
}
|
||||
|
||||
$triggerBody = if ($trigger.Success) { $trigger.Groups["body"].Value } else { "" }
|
||||
$triggerTableRows = [regex]::Matches($triggerBody, '(?m)^\s*\|.*\|\s*$').Count
|
||||
|
||||
$contrarianBody = if ($contrarian.Success) {
|
||||
$contrarian.Groups["body"].Value
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
$results = [ordered]@{
|
||||
AnalysisHeading = $analysis.Success
|
||||
RootCauseHeading = $rootCause.Success
|
||||
FixHeading = $fix.Success
|
||||
ReasoningChain = (
|
||||
$reasoning.Success -and
|
||||
$reasoning.Groups["body"].Value -match 'OBSERVE|HYPOTHESIZE|TEST|EVALUATE|CONCLUDE'
|
||||
)
|
||||
Alternatives = ($alternatives.Success -and $alternativeCount -ge 2)
|
||||
TriggerVerification = (
|
||||
$trigger.Success -and
|
||||
$triggerTableRows -ge 3 -and
|
||||
$triggerBody -match '(?i)\bVERIFIED\b|\bUNVERIFIED\b|verified by'
|
||||
)
|
||||
MermaidDiagram = Test-MermaidDiagram
|
||||
ContrarianVerdict = (
|
||||
$contrarian.Success -and
|
||||
$contrarianBody -match '\bACCEPTED\b|\bCHALLENGED\b' -and
|
||||
$contrarianBody -match '(?i)contrarian_loopback[^:\r\n]*:\s*(?:true|false)\b'
|
||||
)
|
||||
JsonSummary = $false
|
||||
}
|
||||
|
||||
$requiredJsonProperties = @(
|
||||
"diagnosis_status",
|
||||
"routing_path",
|
||||
"root_cause",
|
||||
"confidence",
|
||||
"fix_confidence",
|
||||
"fix_code_path_coverage",
|
||||
"contrarian_review",
|
||||
"contrarian_loopback"
|
||||
)
|
||||
|
||||
foreach ($block in [regex]::Matches($content, '(?is)```json\s*(?<body>.*?)```')) {
|
||||
try {
|
||||
$json = $block.Groups["body"].Value | ConvertFrom-Json
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
|
||||
$propertyNames = @($json.PSObject.Properties.Name)
|
||||
$hasRequiredProperties = $true
|
||||
foreach ($property in $requiredJsonProperties) {
|
||||
if ($propertyNames -notcontains $property) {
|
||||
$hasRequiredProperties = $false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$hasRequiredProperties -and
|
||||
$json.contrarian_loopback -is [bool]
|
||||
) {
|
||||
$results.JsonSummary = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
$pass = @($results.Values | Where-Object { $_ -eq $false }).Count -eq 0
|
||||
$output = [pscustomobject]@{
|
||||
Pass = $pass
|
||||
File = $resolvedPath
|
||||
Checks = [pscustomobject]$results
|
||||
}
|
||||
|
||||
$output | ConvertTo-Json -Depth 5
|
||||
if (-not $pass) {
|
||||
exit 1
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
---
|
||||
name: windbg-kernel-bugcheck-triage
|
||||
description: 'Use when a kernel dump reports a Windows bugcheck; decode parameters and recover exception or trap context before investigating your driver. Not for user-mode process crashes or blaming a module from its name alone.'
|
||||
---
|
||||
|
||||
# Kernel Bugcheck Triage
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Scope
|
||||
|
||||
Use a kernel crash dump or authorized live kernel session. A process dump
|
||||
captured after a reboot does not contain the earlier kernel fault. Confirm
|
||||
the dump type with the debugger, not a filename or the user's visible symptom.
|
||||
This skill includes exception-context and trap-frame recovery.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Establish symbols and bugcheck evidence
|
||||
|
||||
```text
|
||||
.symfix
|
||||
.sympath+ <your-vendor-symbol-directory>
|
||||
.reload
|
||||
!analyze -v
|
||||
.bugcheck
|
||||
k
|
||||
```
|
||||
|
||||
Replace the placeholder with the approved symbol location for your own binaries.
|
||||
Record dump type, target architecture/build, bugcheck code and parameters,
|
||||
faulting instruction, and available memory. Public Windows symbols suffice
|
||||
for many investigations; do not require private Windows source or PDBs.
|
||||
|
||||
### 2. Decode parameters for the specific code
|
||||
|
||||
| Code | Parameter meaning / next step |
|
||||
|---|---|
|
||||
| `0x1E` | P1 exception code; P2 exception address; P3/P4 exception-specific information. These are not generically a CONTEXT pair. |
|
||||
| `0x7E` | P1 exception code; P2 exception address; P3 EXCEPTION_RECORD; P4 CONTEXT. |
|
||||
| `0x3B` | P1 exception code; P2 instruction address; P3 CONTEXT; P4 unused. |
|
||||
| `0x0A` / `0xD1` | Referenced address, IRQL, access information, instruction address. Decode the access field for that code; these parameters are not generally a trap-frame pointer. |
|
||||
| `0x50` | Invalid memory reference; parameter interpretation varies with target version. Consult the code reference. |
|
||||
| `0x9F` | P1 selects the power-failure subtype; use its specific parameter table and `windbg-kernel-irp-lifecycle-triage` where applicable. |
|
||||
| Verifier-class stop | Use `windbg-kernel-verifier-triage` and the exact code/subcode definition. |
|
||||
|
||||
Do not reuse a parameter layout across different bugchecks.
|
||||
|
||||
### 3. Recover the original faulting context
|
||||
|
||||
For `0x7E`:
|
||||
|
||||
```text
|
||||
.exr <P3>
|
||||
.cxr <P4>
|
||||
kb
|
||||
r
|
||||
```
|
||||
|
||||
For `0x3B`:
|
||||
|
||||
```text
|
||||
.cxr <P3>
|
||||
kb
|
||||
r
|
||||
```
|
||||
|
||||
For other exception-style bugchecks, locate a valid saved exception/context
|
||||
using the documented code procedure and available analysis output. Do not
|
||||
guess `.cxr` arguments from arbitrary P1..P4 values.
|
||||
|
||||
When `!analyze -v` or verified stack evidence identifies a `TRAP_FRAME`:
|
||||
|
||||
```text
|
||||
.trap <trap-frame-address>
|
||||
kb
|
||||
r
|
||||
```
|
||||
|
||||
Trap frames can be partial: some registers may be missing or reconstructed
|
||||
incorrectly. Note the debugger's warnings and do not treat unsaved registers as
|
||||
reliable evidence. If a frame is missing, malformed, or absent from the dump,
|
||||
report the limitation rather than scanning arbitrary pointers and claiming a
|
||||
recovered context.
|
||||
|
||||
### 4. Investigate the driver, not just the detector
|
||||
|
||||
```text
|
||||
!thread
|
||||
lmvm <driver-module>
|
||||
.frame /r <frame-number>
|
||||
```
|
||||
|
||||
Inspect the recovered instruction, register/object used, IRQL, ownership,
|
||||
and nearby driver frames. A crash in an operating-system routine may result
|
||||
from prior driver corruption. Conversely, a third-party name in
|
||||
`MODULE_NAME` does not establish that the named driver caused the failure.
|
||||
Verify vendor build identity against the matching binary/PDB.
|
||||
|
||||
For concurrency or blocked requests use `windbg-kernel-lock-deadlock-triage` or
|
||||
`windbg-kernel-irp-lifecycle-triage`. Kernel `~` commands select processors, not the
|
||||
application thread list; use documented thread/process inspection such as
|
||||
`!thread` and `!process 0 7`.
|
||||
|
||||
## Validation
|
||||
|
||||
Record the decoded parameters, recovered context and its limitations, and the
|
||||
evidence connecting the driver's operation to the violated invariant. Test
|
||||
competing lifetime, bounds, IRQL, and synchronization explanations. Recommend
|
||||
an instrumented test/repro only with approval; route Verifier evidence to
|
||||
`windbg-kernel-verifier-triage`. Do not call a guessed module assignment a proven cause.
|
||||
|
||||
## References
|
||||
|
||||
- [Bugcheck reference](https://learn.microsoft.com/windows-hardware/drivers/debugger/bug-check-code-reference2)
|
||||
- [0x3B SYSTEM_SERVICE_EXCEPTION](https://learn.microsoft.com/windows-hardware/drivers/debugger/bug-check-0x3b--system-service-exception)
|
||||
- [0x7E SYSTEM_THREAD_EXCEPTION_NOT_HANDLED](https://learn.microsoft.com/windows-hardware/drivers/debugger/bug-check-0x7e--system-thread-exception-not-handled)
|
||||
- [Context record](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-cxr--display-context-record-)
|
||||
- [Trap frame](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-trap--display-trap-frame-)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and submit only reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-kernel-bugcheck-triage` and the package version from `plugin.json`; no
|
||||
automatic kernel dump, private-symbol, or source upload.
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
name: windbg-kernel-irp-lifecycle-triage
|
||||
description: 'Use when kernel evidence shows stalled I/O, a power IRP, or completion/cancellation misuse; inspect request state and driver ownership. Not for interpreting an empty IRP search in a limited dump as proof of healthy I/O.'
|
||||
---
|
||||
|
||||
# IRP Lifecycle Triage
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Scope
|
||||
|
||||
Investigate I/O Request Packets in a kernel dump or authorized live kernel
|
||||
session. Examples include `0x9F` power failures and hangs where progress
|
||||
depends on a driver request. Apply the parameter table for the specific
|
||||
bugcheck subtype rather than assuming every `0x9F` identifies the same object.
|
||||
|
||||
For `0x9F` with P1 equal to `3`, P4 is the blocked IRP. Inspect that directly
|
||||
before running a system-wide search.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Decode the known request
|
||||
|
||||
```text
|
||||
!analyze -v
|
||||
!irp <irp-address>
|
||||
```
|
||||
|
||||
When no request address is known and the dump has the required pool data:
|
||||
|
||||
```text
|
||||
!irpfind
|
||||
```
|
||||
|
||||
`!irpfind` can be expensive in a live session and incomplete in a limited dump.
|
||||
Use supported filters where appropriate. No result does not prove there are
|
||||
no outstanding requests.
|
||||
|
||||
### 2. Follow the stack and ownership
|
||||
|
||||
Record the major/minor operation, current stack location, device/driver stack,
|
||||
completion routine, pending flags, cancellation state, and any relevant thread.
|
||||
Use the available device stack and driver source to establish which component
|
||||
is expected to advance or complete the request.
|
||||
|
||||
Do not identify an offending driver solely by the last name printed in the IRP
|
||||
stack. A completion routine, downstream dependency, or framework-owned request
|
||||
may change the responsible path.
|
||||
|
||||
### 3. Correlate dependencies
|
||||
|
||||
| Evidence | Next investigation |
|
||||
|---|---|
|
||||
| I/O verifier violation or available shadow history | `windbg-kernel-verifier-triage` |
|
||||
| Owner/waiter kernel lock chain | `windbg-kernel-lock-deadlock-triage` |
|
||||
| Exception or trap during request handling | `windbg-kernel-bugcheck-triage` |
|
||||
|
||||
Preserve evidence between skills; avoid repeatedly handing the same unchanged
|
||||
IRP back and forth.
|
||||
|
||||
### 4. Test the request protocol
|
||||
|
||||
- **Power request:** inspect the subtype's objects and power/PnP state,
|
||||
current stack location, and completion dependency.
|
||||
- **Cancellation race:** establish which routine owns completion, how
|
||||
cancellation synchronizes with normal completion, and whether the request
|
||||
can be completed twice or retained after cancellation.
|
||||
- **Double completion:** trace competing terminal paths; a single live IRP
|
||||
snapshot may not contain enough history.
|
||||
- **Pending request:** verify API/framework-specific pending and completion
|
||||
rules, remove/shutdown paths, and who promises eventual progress.
|
||||
|
||||
WDM and WDF have different ownership APIs. Do not transplant a raw WDM
|
||||
completion/cancel pattern into a framework-owned request without checking its
|
||||
contract. This skill establishes evidence; it is not a complete I/O protocol
|
||||
reference or a decoder for every power subtype.
|
||||
|
||||
## Validation
|
||||
|
||||
Name the operation, current owner/dependency, and supported protocol violation
|
||||
or stalled path. Test normal completion, concurrent cancellation, removal,
|
||||
power transitions, and shutdown where relevant. If history is missing, propose
|
||||
an approved instrumented test using the verifier skill rather than inventing
|
||||
which driver lost the completion.
|
||||
|
||||
## References
|
||||
|
||||
- [IRP inspection](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-irp)
|
||||
- [IRP search](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-irpfind)
|
||||
- [0x9F power-state failure](https://learn.microsoft.com/windows-hardware/drivers/debugger/bug-check-0x9f--driver-power-state-failure)
|
||||
- [Canceling IRPs](https://learn.microsoft.com/windows-hardware/drivers/kernel/canceling-irps)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and report only reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-kernel-irp-lifecycle-triage` and the package version from `plugin.json`; no
|
||||
automatic kernel dump or request-content upload.
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
name: windbg-kernel-lock-deadlock-triage
|
||||
description: 'Use when kernel threads block on driver synchronization or Verifier reports a lock-order violation; build an owner/waiter graph. Not for treating every watchdog stop as a deadlock or listing every lock type with !locks.'
|
||||
---
|
||||
|
||||
# Kernel Lock and Deadlock Triage
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Detection
|
||||
|
||||
Use kernel thread stacks, synchronization-object evidence, and Driver Verifier
|
||||
deadlock records. A watchdog bugcheck can indicate CPU/DPC progress failures,
|
||||
not necessarily a lock cycle. Establish the actual waits before choosing this
|
||||
workflow.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Gather owners and waiters
|
||||
|
||||
```text
|
||||
!locks
|
||||
!thread <ethread-address>
|
||||
!process 0 7
|
||||
```
|
||||
|
||||
`!locks` enumerates ERESOURCE information. It is not an inventory of all
|
||||
pushlocks, fast mutexes, and spinlocks. For other primitives use documented
|
||||
primitive-specific inspection when available, matching symbols for your
|
||||
driver, its source, and recorded acquisition evidence. State missing owners
|
||||
explicitly.
|
||||
|
||||
### 2. Inspect recorded lock-order evidence
|
||||
|
||||
If Driver Verifier deadlock detection was enabled and the dump contains its
|
||||
records:
|
||||
|
||||
```text
|
||||
!deadlock 1
|
||||
```
|
||||
|
||||
Inspect the reported resources, acquisition sequence, and threads. Verifier
|
||||
can detect an unsafe ordering before a persistent deadlock actually forms.
|
||||
An empty result without the required verification/history is not proof that
|
||||
the lock order is safe. For Verifier setup/safety use `windbg-kernel-verifier-triage`.
|
||||
|
||||
### 3. Build and test the graph
|
||||
|
||||
```text
|
||||
thread A holds resource X -> waits for Y owned by B
|
||||
thread B holds resource Y -> waits for X owned by A
|
||||
```
|
||||
|
||||
Show evidence for every edge. Check recursive acquisition, callbacks under
|
||||
locks, I/O completion dependencies, and destruction/rundown paths.
|
||||
|
||||
Distinguish:
|
||||
|
||||
- A demonstrated cycle or Verifier-reported order inversion.
|
||||
- Contention where a runnable owner can progress.
|
||||
- Starvation or an owner blocked on a separate request.
|
||||
- Spin/IRQL problems, which are not necessarily blocking-lock deadlocks.
|
||||
|
||||
If blocked on an IRP use `windbg-kernel-irp-lifecycle-triage`; if a chain crosses into a
|
||||
user-mode COM/RPC operation use `windbg-user-wait-chain-analysis`. Carry the proven graph
|
||||
edges into the next skill rather than starting the same investigation again.
|
||||
|
||||
### 4. Localize the driver path
|
||||
|
||||
Identify which call path held one resource while acquiring/waiting for another.
|
||||
Check the required IRQL, permitted waits, lock hierarchy, and object lifetime.
|
||||
Private Windows implementation layouts are not prerequisites; if public
|
||||
symbols and captured state cannot recover an edge, request appropriate
|
||||
authorized evidence and keep the conclusion provisional.
|
||||
|
||||
## Fix patterns
|
||||
|
||||
Use a consistent acquisition hierarchy, reduce lock scope, avoid unbounded
|
||||
waits/cross-component callbacks while holding resources, and move potentially
|
||||
blocking destruction outside locks where the ownership design permits.
|
||||
Do not replace a lock or add a timeout without preserving invariants and
|
||||
completion/cancellation semantics.
|
||||
|
||||
## Validation
|
||||
|
||||
Record the graph, supported cycle/inversion, and offending driver path.
|
||||
Test concurrency, callbacks, teardown, and the same applicable Verifier checks.
|
||||
Separate a demonstrated fix from an unproven contention hypothesis.
|
||||
|
||||
## References
|
||||
|
||||
- [ERESOURCE locks extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-locks)
|
||||
- [Deadlock extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-deadlock)
|
||||
- [Driver Verifier deadlock detection](https://learn.microsoft.com/windows-hardware/drivers/devtest/deadlock-detection)
|
||||
- [Thread inspection](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-thread)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and report reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-kernel-lock-deadlock-triage` and the package version from `plugin.json`; no
|
||||
automatic dump, lock-history transcript, or driver-source upload.
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
name: windbg-kernel-verifier-triage
|
||||
description: 'Use when a kernel dump contains Driver Verifier violations; inspect flags, bugcheck subcodes, and available I/O shadow state. Not for Application Verifier user-mode stops or inferring a violation from enabled flags alone.'
|
||||
---
|
||||
|
||||
# Driver Verifier Triage
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Scope
|
||||
|
||||
Driver Verifier checks kernel driver contracts. Application Verifier is a
|
||||
different user-mode facility; use `windbg-user-heap-corruption-investigation` for its heap
|
||||
stops. Enabled Driver Verifier flags alone do not prove a contract violation.
|
||||
|
||||
Use this skill when a verifier-class bugcheck or analysis identifies an actual
|
||||
violation. Examples include `0xC4`, `0xC9`, and `0xE6`; inspect the exact code
|
||||
and parameters rather than treating every stop as the same family.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Preserve code, subcode, and active configuration
|
||||
|
||||
```text
|
||||
!analyze -v
|
||||
.bugcheck
|
||||
!verifier
|
||||
k
|
||||
```
|
||||
|
||||
Record the bugcheck, subtype/subcode, offending operation and driver when
|
||||
reported, enabled checks, target build, and evidence availability. Decode each
|
||||
subcode against its documented contract. Existing output may be incomplete in
|
||||
a small dump; do not discard captured evidence merely because live
|
||||
configuration is now different.
|
||||
|
||||
### 2. Decode available I/O history
|
||||
|
||||
When the violation supplies an appropriate IRP address and I/O verification
|
||||
state is available:
|
||||
|
||||
```text
|
||||
!iovirp <irp-address>
|
||||
!irp <irp-address>
|
||||
```
|
||||
|
||||
Shadow state may preserve information lost from the live request. Correlate it
|
||||
with the decoded contract and use `windbg-kernel-irp-lifecycle-triage` for completion,
|
||||
cancellation, pending state, and ownership.
|
||||
|
||||
### 3. Recover context or follow dependencies
|
||||
|
||||
- Saved exception/trap context: `windbg-kernel-bugcheck-triage`.
|
||||
- Lock-order evidence: `windbg-kernel-lock-deadlock-triage`.
|
||||
- Outstanding or power request: `windbg-kernel-irp-lifecycle-triage`.
|
||||
|
||||
Avoid cyclic dispatch. Carry the evidence already collected to the next skill;
|
||||
re-enter only when a distinct evidence requirement exists.
|
||||
|
||||
### 4. Investigate uncovered violations
|
||||
|
||||
For a generic DDI violation, identify the exact precondition (IRQL, lifetime,
|
||||
parameters, or ownership) and the driver call that broke it. For a DMA violation,
|
||||
inspect supported adapter/map/unmap and buffer-lifetime evidence for that
|
||||
subcode. This package does not provide a specialized decoder for every DDI or
|
||||
DMA case; state the gap and continue from documentation and driver source.
|
||||
|
||||
## Controlled repro
|
||||
|
||||
Do not enable Driver Verifier without approval. It can deliberately crash the
|
||||
system and expose boot-critical defects. Use a recoverable test machine, save
|
||||
the current configuration, select relevant vendor drivers/checks, and agree on
|
||||
rollback before restarting. Do not verify every installed driver by default.
|
||||
|
||||
Read-only configuration inspection on a test machine:
|
||||
|
||||
```text
|
||||
verifier /querysettings
|
||||
```
|
||||
|
||||
`verifier /reset` clears settings and normally requires a restart to stop
|
||||
verification; it is a configuration change, not a harmless query. Restore
|
||||
previous intentional settings rather than unconditionally clearing them.
|
||||
|
||||
## Validation
|
||||
|
||||
Name the exact violated contract, link the recorded operation to driver source,
|
||||
and test that the remedy satisfies it under the same checks and workload.
|
||||
Record dump/verification limitations and unverified assumptions. Passing a
|
||||
single repro is not proof that every driver path is safe.
|
||||
|
||||
## References
|
||||
|
||||
- [Driver Verifier](https://learn.microsoft.com/windows-hardware/drivers/devtest/driver-verifier)
|
||||
- [Verifier extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-verifier)
|
||||
- [I/O verifier IRP extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-iovirp)
|
||||
- [0xC4 verifier violation](https://learn.microsoft.com/windows-hardware/drivers/debugger/bug-check-0xc4--driver-verifier-detected-violation)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and submit reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-kernel-verifier-triage` and the package version from `plugin.json`; do not
|
||||
automatically upload dumps or proprietary driver source.
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
name: windbg-user-exception-triage
|
||||
description: 'Use when a native C/C++ app, service, or user-mode driver host (including UMDF) crashes with a structured exception in a dump or WinDbg session, including native faults inside managed processes. Not for managed .NET exceptions, WinUI/XAML app errors, or kernel bugchecks.'
|
||||
---
|
||||
|
||||
# User-Mode Exception Triage
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## When to use
|
||||
|
||||
Start here for access violations, heap corruption, stack overflow, fail-fast,
|
||||
breakpoints, and other structured exceptions in a native application, service,
|
||||
or user-mode driver host process dump. This includes UMDF driver failures that
|
||||
occur in their user-mode host. Confirm
|
||||
the dump type from WinDbg; the filename extension alone does not distinguish
|
||||
user-mode from kernel-mode dumps.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Establish the exception context
|
||||
|
||||
```text
|
||||
.exr -1
|
||||
.ecxr
|
||||
k
|
||||
!analyze -v
|
||||
```
|
||||
|
||||
Record the exception code, address, parameters, access type, registers, module,
|
||||
and stack. `.ecxr` selects the saved exception context when available. If no
|
||||
exception context was captured, report that limitation rather than treating the
|
||||
currently selected thread as the faulting thread.
|
||||
|
||||
Use matching binaries and PDBs for your modules and public Windows symbols.
|
||||
Investigate mismatches or truncated stacks before naming a failing source line.
|
||||
|
||||
### 2. Classify and choose an available investigation
|
||||
|
||||
| Evidence | Next step |
|
||||
|---|---|
|
||||
| `0xC0000005` with allocation/free or overrun evidence | `windbg-user-heap-corruption-investigation` |
|
||||
| `0xC0000374` heap corruption | `windbg-user-heap-corruption-investigation` |
|
||||
| `0xC0000017`, `0x8007000E`, or an allocation-failure path | `windbg-user-virtual-memory-exhaustion` |
|
||||
| Lock/unlock failure following coroutine suspension | `windbg-user-mutex-held-across-co-await` |
|
||||
| A TTD recording is available and earlier mutation is in question | `windbg-user-ttd-reverse-debugging-triage` |
|
||||
| No crash exception and evidence of blocked work | `windbg-user-wait-chain-analysis` |
|
||||
| A kernel dump reports a bugcheck | `windbg-kernel-bugcheck-triage` |
|
||||
|
||||
Do not classify every address in a heap range as a lifetime bug. Check access
|
||||
type, faulting instruction, object layout, and valid allocation boundaries.
|
||||
|
||||
### 3. Investigate families without a dedicated skill
|
||||
|
||||
- **Access violation without a match:** identify the read/write/execute target,
|
||||
object/register used, and whether bounds, ownership, or synchronization was
|
||||
violated. Distinguish a null pointer from stale or corrupted state.
|
||||
- **`0xC0000409` / fail-fast:** inspect exception parameters and the documented
|
||||
fast-fail subcode, then the failing condition and call path. The historical
|
||||
status name alone does not prove a buffer overrun or rule one out. Not every
|
||||
fast-fail carries an HRESULT.
|
||||
- **`0xC00000FD` / stack overflow:** inspect stack bounds and frame sizes; test
|
||||
recursion, reentrancy, large frames, and inability to commit stack growth.
|
||||
Use the memory-exhaustion skill when commit evidence supports that branch.
|
||||
- **`0xE06D7363` / MSVC C++ exception:** establish whether it was handled,
|
||||
identify the throw/catch path with available symbols, and inspect the
|
||||
exception information supported by the runtime/version. A first-chance throw
|
||||
is not automatically a defect. This package does not decode thrown-object
|
||||
layouts or fully diagnose `noexcept`/termination behavior.
|
||||
- **Stowed/WinRT exceptions:** preserved error information can precede the
|
||||
final failure. Correlate its originating stack and nested errors with the
|
||||
application; this package does not include a XAML extension workflow.
|
||||
- **Illegal instruction or breakpoint:** distinguish CPU/architecture or
|
||||
code-corruption hypotheses from intentional assertions/debug breaks.
|
||||
|
||||
## Validation
|
||||
|
||||
- Exception context and code are established, or their absence is stated.
|
||||
- Faulting instruction and relevant object/register agree with the hypothesis.
|
||||
- Alternatives are tested against evidence, not just stack names.
|
||||
- Missing memory, symbols, and specialized exception coverage are explicit.
|
||||
- The proposed fix addresses a demonstrated invariant and has a repro/test plan.
|
||||
|
||||
## References
|
||||
|
||||
- [Exception context](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-ecxr--display-exception-context-record-)
|
||||
- [Exception record](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-exr--display-exception-record-)
|
||||
- [Controlling exceptions and events](https://learn.microsoft.com/windows-hardware/drivers/debugger/controlling-exceptions-and-events)
|
||||
|
||||
## Feedback
|
||||
|
||||
For this skill, follow the plugin's `FEEDBACK.md` and report a reviewed, sanitized
|
||||
issue to [WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-user-exception-triage` and the package version from `plugin.json`; do not
|
||||
upload dumps or private source automatically.
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
name: windbg-user-heap-corruption-investigation
|
||||
description: 'Use when an app, service, or user-mode driver host heap fails or Application Verifier detects corruption; inspect history and bounds. Not for kernel pool corruption or ordinary OOM.'
|
||||
---
|
||||
|
||||
# Heap Corruption Investigation
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Detection and limits
|
||||
|
||||
Look for `STATUS_HEAP_CORRUPTION` (`0xC0000374`), Application Verifier stops,
|
||||
or failures in heap allocate/free/reallocate paths in an application, service,
|
||||
or user-mode driver host such as an UMDF host process. A crash inside the allocator
|
||||
may be the first detection of an earlier bad write, not the faulty operation.
|
||||
Distinguish corruption from allocation failure; for the latter use
|
||||
`windbg-user-virtual-memory-exhaustion`.
|
||||
|
||||
Allocation/free history depends on how the process was instrumented and which
|
||||
pages were captured. A missing history is a limitation, not proof of a leak or
|
||||
use-after-free.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Decode the stop
|
||||
|
||||
```text
|
||||
.exr -1
|
||||
.ecxr
|
||||
!analyze -v
|
||||
k
|
||||
```
|
||||
|
||||
Record the stop reason, corrupted block, corruption address, and the operation
|
||||
that detected the damage. If a verifier stop frame has parameter/local symbols,
|
||||
select it with `.frame /r <frame>` and inspect `dv`; otherwise use the captured
|
||||
stop output and the documented stop definition. Do not assume one fixed
|
||||
parameter layout or a stop code shared by all verifier versions.
|
||||
|
||||
### 2. Recover available block history
|
||||
|
||||
```text
|
||||
!heap -p -a <address>
|
||||
!avrf -hp -a <address>
|
||||
```
|
||||
|
||||
The first command inspects a Page Heap allocation; the second searches available
|
||||
Application Verifier heap-operation history. Use `!heap -?` and `!avrf -?` to
|
||||
confirm support in the installed extension. On an uninstrumented dump these
|
||||
commands may not recover the history needed to identify the writer.
|
||||
|
||||
Capture allocation and free stacks when present. Check the address is inside
|
||||
the user allocation rather than a header or neighboring block.
|
||||
|
||||
### 3. Test competing explanations
|
||||
|
||||
| Hypothesis | Evidence to seek |
|
||||
|---|---|
|
||||
| Use-after-free | Confirmed free before a later access through a retained reference |
|
||||
| Double-free | Two ownership/completion paths freeing the same allocation |
|
||||
| Overrun/underrun | A write outside the allocated user bounds |
|
||||
| Wild write | Corrupted header or payload and a writer with an invalid target |
|
||||
| Allocation/free contract mismatch | Different allocator/deallocator or incorrect owning heap |
|
||||
|
||||
Inspect bytes with `db <address> L<size>` and disassembly around the access.
|
||||
Fill patterns and plausible pointers are clues, not causal proof. Correlate with
|
||||
source, history, or a repro and trace the ownership transition.
|
||||
|
||||
### 4. Obtain stronger evidence if necessary
|
||||
|
||||
With user approval, enable full Page Heap for a named test executable:
|
||||
|
||||
```text
|
||||
gflags /p /enable target.exe /full
|
||||
```
|
||||
|
||||
Restart that process and reproduce under the debugger. Application Verifier
|
||||
heap checks can also be configured for that test executable. Explain memory
|
||||
overhead, timing changes, and potential deliberate stops before doing this.
|
||||
Record the previous settings and restore them when finished; if Page Heap was
|
||||
newly enabled for this test, disable it with:
|
||||
|
||||
```text
|
||||
gflags /p /disable target.exe
|
||||
```
|
||||
|
||||
Do not change an existing application's verification policy without approval.
|
||||
If a user-mode TTD trace is available, use `windbg-user-ttd-reverse-debugging-triage` to
|
||||
find the relevant mutation or free.
|
||||
|
||||
## Fix patterns
|
||||
|
||||
- Enforce the actual lifetime contract with ownership types or explicit
|
||||
acquire/release rules. Shared ownership is appropriate only when the design
|
||||
genuinely has multiple owners.
|
||||
- Synchronize shared state separately: `shared_ptr` ownership does not make a
|
||||
concurrently modified cache or pointed-to object thread-safe.
|
||||
- Size buffers and check arithmetic, lengths, and terminators; use bounds-aware
|
||||
containers where appropriate.
|
||||
- Keep allocation and deallocation compatible across DLL/API boundaries.
|
||||
|
||||
## Validation
|
||||
|
||||
Establish the affected block and supported corruption class, name the path that
|
||||
violated bounds or ownership, and distinguish the detector from the writer.
|
||||
Exercise the fix with the same instrumentation and relevant concurrency/load.
|
||||
Report unresolved writer history rather than presenting a guessed fix as proven.
|
||||
|
||||
## References
|
||||
|
||||
- [Application Verifier stop definitions](https://learn.microsoft.com/windows-hardware/drivers/devtest/application-verifier-stop-codes-and-definitions)
|
||||
- [Heap extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-heap)
|
||||
- [Application Verifier extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-avrf)
|
||||
- [GFlags and Page Heap](https://learn.microsoft.com/windows-hardware/drivers/debugger/gflags-and-pageheap)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and report reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-user-heap-corruption-investigation` and the package version from
|
||||
`plugin.json`; no automatic dump, source, or transcript upload.
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
name: windbg-user-mutex-held-across-co-await
|
||||
description: 'Use when app, service, or user-mode driver C++ coroutine code holds a thread-affine lock across suspension and later hangs or fails. Not for all coroutine crashes or choosing lock performance.'
|
||||
---
|
||||
|
||||
# Mutex Held Across co_await
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Detection
|
||||
|
||||
This pattern can occur in native application, service, or user-mode driver
|
||||
code, including UMDF components that use C++ coroutines. Look for a lock
|
||||
acquired before `co_await` and released after resumption or
|
||||
coroutine destruction. Mutex ownership belongs to the acquiring thread, not
|
||||
the coroutine frame. A resumption on another thread can violate that contract.
|
||||
Even same-thread resumption can create reentrancy or progress problems when
|
||||
the awaited operation needs a lock the coroutine still holds.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Identify the exact lock primitive and acquisition/release scope in source.
|
||||
Audit every suspension point while the RAII guard or ownership is alive.
|
||||
2. Establish the acquire and resume threads using trace/source evidence.
|
||||
Standard mutexes and SRW locks do not provide a universally queryable owner
|
||||
field; do not fabricate an owning TID from undocumented layouts.
|
||||
3. Verify the awaiter's resumption contract. C++/WinRT can preserve apartment
|
||||
context for particular awaitables; `resume_background` intentionally switches.
|
||||
Do not assume every WinRT awaitable always resumes on a worker or always on
|
||||
the originating thread.
|
||||
4. Distinguish wrong-thread release, a dependency cycle, state changed during
|
||||
suspension, lifetime failure, and unrelated memory corruption.
|
||||
5. Move the thread-affine lock into synchronous scopes. Revalidate relevant
|
||||
state after the await rather than treating the pre-await snapshot as current.
|
||||
|
||||
If the symptom is general blocking use `windbg-user-wait-chain-analysis`. For damaged
|
||||
heap objects use `windbg-user-heap-corruption-investigation`. If a recording is available,
|
||||
`windbg-user-ttd-reverse-debugging-triage` can help establish the ownership timeline.
|
||||
|
||||
## Fix pattern
|
||||
|
||||
Conceptual sequence, not a promise about any particular scheduler:
|
||||
|
||||
```text
|
||||
under lock:
|
||||
take a snapshot and its generation
|
||||
release lock
|
||||
await work using that snapshot
|
||||
under lock on the resumed thread:
|
||||
revalidate generation, lifetime, and assumptions
|
||||
apply result or explicitly handle a stale/cancelled operation
|
||||
release lock
|
||||
```
|
||||
|
||||
Use RAII for each synchronous scope. If invariants cannot tolerate unlocking,
|
||||
redesign the operation or use a specifically designed asynchronous coordination
|
||||
primitive with cancellation/lifetime rules. Switching to a recursive mutex or
|
||||
`shared_mutex` does not make a thread-affine lock coroutine-safe.
|
||||
|
||||
Do not recommend a blanket mutex-type replacement. Shared locking is a separate
|
||||
design decision; changing the primitive does not repair suspension ownership.
|
||||
Keep the object and any captured interfaces alive across asynchronous work.
|
||||
|
||||
## Validation
|
||||
|
||||
- No thread-affine lock ownership survives a suspension in the corrected path.
|
||||
- Each awaiter's thread/apartment contract is understood.
|
||||
- State invariants are revalidated after suspension.
|
||||
- Cancellation, concurrent mutation, shutdown, and failed awaited work are tested.
|
||||
- The remedy removes the demonstrated cause, not just an observed exception.
|
||||
|
||||
## References
|
||||
|
||||
- [Holding a lock across coroutine suspension](https://devblogs.microsoft.com/oldnewthing/20210707-00/?p=105417)
|
||||
- [C++/WinRT concurrency and asynchronous operations](https://learn.microsoft.com/windows/uwp/cpp-and-winrt-apis/concurrency)
|
||||
- [Slim reader/writer locks](https://learn.microsoft.com/windows/win32/sync/slim-reader-writer--srw--locks)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and report reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-user-mutex-held-across-co-await` and the package version from `plugin.json`;
|
||||
no automatic source, dump, or transcript upload.
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
name: windbg-user-ttd-reverse-debugging-triage
|
||||
description: 'Use when an app, service, or user-mode driver host TTD recording is available and earlier calls, writes, or lifetimes matter. Not for kernel replay or history from a normal dump.'
|
||||
---
|
||||
|
||||
# TTD Reverse Debugging Triage
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Requirements and scope
|
||||
|
||||
Time Travel Debugging records a user-mode process for replay, including an
|
||||
authorized application, service, or user-mode driver host process. A dump alone
|
||||
contains no execution timeline. Confirm a valid recording and matching module
|
||||
symbols before attempting timeline queries. It does not record kernel execution
|
||||
or automatically include another process's server-side activity.
|
||||
|
||||
Recording can change timing, require substantial storage, and capture sensitive
|
||||
memory. Obtain authorization before capture. Check the installed recorder's help
|
||||
for supported target, architecture, and options. WinDbg's **Launch executable
|
||||
(advanced)** / **Record with Time Travel Debugging** flow can record a named
|
||||
test application without guessing a recorder command.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Open and index the recording
|
||||
|
||||
Open the recorded `.run` file in WinDbg and load public Windows symbols and
|
||||
matching PDBs for your own binaries.
|
||||
|
||||
```text
|
||||
!tt.index
|
||||
dx @$cursession.TTD
|
||||
```
|
||||
|
||||
Confirm the timeline range. Indexing and data-model availability depend on
|
||||
WinDbg/TTD versions; consult the installed help if the command is unavailable.
|
||||
|
||||
### 2. Ask a bounded history question
|
||||
|
||||
```text
|
||||
dx @$cursession.TTD.Calls("MyModule!MyFunction")
|
||||
dx @$cursession.TTD.Memory(<start-address>, <end-address>, "w")
|
||||
```
|
||||
|
||||
Query the known function or exact memory range, then inspect relevant results
|
||||
and their timeline positions. An empty result can mean unmatched symbols,
|
||||
uninstrumented execution, or an out-of-range query, not proof of absence.
|
||||
|
||||
Use the call query to find allocation/free or module lifetime transitions and
|
||||
the memory query to locate candidate writes. Account for allocator reuse: the
|
||||
same virtual address may represent different objects over the recording.
|
||||
|
||||
### 3. Seek and inspect state
|
||||
|
||||
```text
|
||||
!tt <position>
|
||||
k
|
||||
r
|
||||
g-
|
||||
```
|
||||
|
||||
Seek to an actual position returned by the query. `g-` continues backward;
|
||||
use the installed reverse-step controls to refine the search. Capture the
|
||||
last-good and first-bad states, writer/caller stack, and ownership transition.
|
||||
|
||||
Do not equate the last write with the bug until you establish the object's
|
||||
identity, valid lifetime, intended invariant, and relevant cross-thread order.
|
||||
|
||||
### 4. Continue with a shipped investigation
|
||||
|
||||
| Evidence | Skill |
|
||||
|---|---|
|
||||
| Bad free/write or allocation-boundary violation | `windbg-user-heap-corruption-investigation` |
|
||||
| Growing allocation/reservation usage | `windbg-user-virtual-memory-exhaustion` |
|
||||
| Lock survives coroutine suspension | `windbg-user-mutex-held-across-co-await` |
|
||||
| Blocker or cross-process dependency at the selected moment | `windbg-user-wait-chain-analysis` |
|
||||
|
||||
For other user-mode families continue reasoning from the timeline rather than
|
||||
dispatching to absent skills. For a kernel crash use `windbg-kernel-bugcheck-triage`;
|
||||
TTD is not a kernel-history substitute.
|
||||
|
||||
## Validation
|
||||
|
||||
Record the question, trace identity, timeline positions, relevant object
|
||||
lifetime, and source/stack evidence. Test alternatives and state recording
|
||||
boundaries. A reproducible timeline proves what occurred in that recording;
|
||||
it does not establish that instrumentation preserved all production timing.
|
||||
|
||||
## References
|
||||
|
||||
- [Time Travel Debugging overview](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/time-travel-debugging-overview)
|
||||
- [TTD data-model queries](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/time-travel-debugging-object-model)
|
||||
- [TTD extension commands](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/time-travel-debugging-extension-commands)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and report a reviewed summary to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-user-ttd-reverse-debugging-triage` and the package version from
|
||||
`plugin.json`; never automatically upload a recording or its memory/query
|
||||
contents.
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
name: windbg-user-virtual-memory-exhaustion
|
||||
description: 'Use when a native app, service, or user-mode driver host allocation fails; distinguish VA exhaustion, fragmentation, and commit pressure. Not for managed .NET heap growth, proving a leak from one snapshot, or corruption.'
|
||||
---
|
||||
|
||||
# Virtual Memory Exhaustion
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Detection
|
||||
|
||||
Investigate `E_OUTOFMEMORY` (`0x8007000E`), `STATUS_NO_MEMORY` (`0xC0000017`),
|
||||
`bad_alloc`, or failed heap/virtual allocations in an application, service, or
|
||||
user-mode driver host (including UMDF). Record the actual API, requested
|
||||
size/alignment, architecture, flags, and error. Free physical RAM does not rule
|
||||
out insufficient virtual address space, commit pressure, or applicable limits.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Examine the process VA map
|
||||
|
||||
```text
|
||||
!address -summary
|
||||
!address
|
||||
!heap -s
|
||||
```
|
||||
|
||||
Compare available regions with the attempted allocation's contiguous range and
|
||||
alignment requirements. Distinguish reserved, committed, free, image, mapped,
|
||||
stack, and heap ranges. A large reservation consumes VA without committing its
|
||||
entire range. Heap internals may require more than the user's requested bytes.
|
||||
|
||||
Report unavailable pages/map data rather than inferring completeness from a
|
||||
limited dump.
|
||||
|
||||
### 2. Separate pressure mechanisms
|
||||
|
||||
| Mechanism | Evidence needed |
|
||||
|---|---|
|
||||
| VA exhaustion | Process address range/architecture and little usable free VA |
|
||||
| Fragmentation | Free space exists, but no suitable contiguous/aligned region |
|
||||
| System commit pressure | Commit usage/limit near the failure, not just free RAM |
|
||||
| Process/job memory limit | Actual configured limit and relevant usage/accounting |
|
||||
| Allocation policy/API failure | API-specific constraints, flags, or allocator policy |
|
||||
|
||||
Use contemporaneous system memory counters or an appropriate live/kernel
|
||||
session for system commit data. A process PEB is not a documented
|
||||
`MaximumCommit` source. A process's committed bytes alone do not establish a
|
||||
system-wide or job limit.
|
||||
|
||||
For 32-bit targets inspect `/LARGEADDRESSAWARE` and the host architecture;
|
||||
2 GB versus up to 4 GB depends on those settings. Verify current documented
|
||||
limits for the target Windows version and architecture instead of applying
|
||||
one 64-bit limit to every system.
|
||||
|
||||
### 3. Identify dominant consumers
|
||||
|
||||
```text
|
||||
!address -f:Heap
|
||||
!address -f:Stack
|
||||
!heap -stat -h <heap-address>
|
||||
```
|
||||
|
||||
Use `!address -?` and `!heap -?` for allocator/version-specific support.
|
||||
Classify dominant heaps, stacks, mappings, images, and reserved arenas.
|
||||
Large or numerous allocations are not automatically leaks: map them to cache
|
||||
policy, owners, workload, and expected lifetimes.
|
||||
|
||||
### 4. Establish growth with history
|
||||
|
||||
Collect authorized time-series counters, repeated comparable snapshots, or
|
||||
allocation/free tracing across the workload. Compare warm-up with steady-state
|
||||
behavior and verify whether memory is reclaimed when work finishes.
|
||||
|
||||
One snapshot plus process uptime cannot prove a leak rate. For a suitable
|
||||
user-mode recording use `windbg-user-ttd-reverse-debugging-triage`; for damaged allocations
|
||||
use `windbg-user-heap-corruption-investigation` instead.
|
||||
|
||||
## Fix patterns
|
||||
|
||||
- Bound caches by an appropriate size/cost policy and verify eviction.
|
||||
Define the lifetime of any references returned before eviction.
|
||||
- Match `VirtualAlloc` reservations with the correct `VirtualFree` release
|
||||
contract; distinguish decommit from release.
|
||||
- Use RAII to release resources on all supported exit/error paths.
|
||||
- Reduce large contiguous allocation requirements where the design permits.
|
||||
- Do not blindly increase limits or stack reservations before finding the
|
||||
pressure source, and do not convert a failed allocation into a silent success.
|
||||
|
||||
## Validation
|
||||
|
||||
Name the failing allocation and pressure mechanism, identify the consumer with
|
||||
evidence, and exercise the remedy through warm-up, sustained load, and cleanup.
|
||||
Verify memory remains bounded or the intended allocation succeeds under the
|
||||
required constraints. Document configured system/job limits separately.
|
||||
|
||||
## References
|
||||
|
||||
- [Address extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-address)
|
||||
- [Heap extension](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-heap)
|
||||
- [Windows memory limits](https://learn.microsoft.com/windows/win32/memory/memory-limits-for-windows-releases)
|
||||
- [Large-address-aware linker option](https://learn.microsoft.com/cpp/build/reference/largeaddressaware-handle-large-addresses)
|
||||
- [VirtualFree](https://learn.microsoft.com/windows/win32/api/memoryapi/nf-memoryapi-virtualfree)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and submit reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-user-virtual-memory-exhaustion` and the package version from `plugin.json`;
|
||||
no automatic dump or memory-content upload.
|
||||
@@ -0,0 +1,116 @@
|
||||
---
|
||||
name: windbg-user-wait-chain-analysis
|
||||
description: 'Use when an app, service, or user-mode driver host is unresponsive on locks, COM/RPC, I/O, or another process; follow the blocker chain. Not for a crash solely from an exception stack.'
|
||||
---
|
||||
|
||||
# Cross-Process Wait Chain Analysis
|
||||
|
||||
**Load `windbg-diagnostic-method` first** if it is not already loaded in this
|
||||
conversation, and apply it throughout for evidence ranking, hypothesis testing,
|
||||
confidence calibration, independent review, and report validation. This skill
|
||||
adds the bug-family-specific commands and evidence requirements.
|
||||
|
||||
## Detection
|
||||
|
||||
Look for blocked work in an application, service, or user-mode driver host
|
||||
(including UMDF), and threads in wait, COM, RPC, or I/O paths.
|
||||
The process displaying the symptom may not own the underlying defect.
|
||||
Idle worker threads waiting normally are not evidence of a hang.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Identify the affected operation and its thread
|
||||
|
||||
```text
|
||||
.lastevent
|
||||
~*kb
|
||||
!runaway
|
||||
```
|
||||
|
||||
Confirm why the dump was collected. A dump is a snapshot; `.lastevent` does not
|
||||
by itself certify "hang" or "no crash." Identify the UI/serving thread from
|
||||
application evidence instead of assuming thread zero is always the UI thread.
|
||||
If work is spinning rather than blocked, collect appropriate CPU evidence.
|
||||
|
||||
### 2. Identify each wait and its owner
|
||||
|
||||
Inspect frames around `WaitForSingleObject`, `WaitForMultipleObjects`, COM
|
||||
send/receive, and RPC calls. Use matching symbols/source for your own proxy,
|
||||
interface, and server registration to determine what was requested.
|
||||
|
||||
For each edge record:
|
||||
|
||||
```text
|
||||
process / thread -> waited resource or request -> owner / serving thread
|
||||
```
|
||||
|
||||
Do not guess a server PID from undocumented private COM layouts. Use available
|
||||
Wait Chain Traversal, RPC/COM tracing, application correlation IDs, or
|
||||
registration/process information, and explicitly mark unresolved edges.
|
||||
|
||||
### 3. Gather corresponding server evidence
|
||||
|
||||
Obtain authorized dumps or live state of the relevant server processes close
|
||||
enough in time to represent the same operation. Inspect their serving threads.
|
||||
For kernel context use documented commands such as:
|
||||
|
||||
```text
|
||||
!process 0 7
|
||||
!thread <ethread>
|
||||
```
|
||||
|
||||
Available user pages and symbol/context support vary by dump type. If the chain
|
||||
ends in a kernel lock use `windbg-kernel-lock-deadlock-triage`; if blocked I/O is supported
|
||||
by IRP evidence use `windbg-kernel-irp-lifecycle-triage`. Do not promise process heaps or
|
||||
user stacks absent from the dump.
|
||||
|
||||
### 4. Distinguish a cycle from a slow or missing responder
|
||||
|
||||
- **Cycle:** show every required wait/owner edge back to the starting actor.
|
||||
- **Contention:** a runnable owner may eventually release the resource.
|
||||
- **Starvation:** queued work cannot obtain execution capacity.
|
||||
- **Lost completion:** the actor/event expected to unblock the waiter no
|
||||
longer exists or no path signals it.
|
||||
- **Slow server:** the endpoint is doing work, blocked on another dependency,
|
||||
or looping; gather its evidence before blaming the client.
|
||||
|
||||
Multiple snapshots or tracing may be needed to distinguish transient waits
|
||||
from persistent blocking.
|
||||
|
||||
## Fix patterns and COM boundaries
|
||||
|
||||
A synchronous COM call from an STA can pump messages and permit reentrancy.
|
||||
It is not automatically a deadlock. Investigate locks held across calls,
|
||||
callbacks, apartment access, and any non-pumping waits that form an actual
|
||||
dependency cycle.
|
||||
|
||||
Possible remedies include asynchronous APIs, shorter lock scopes, moving
|
||||
destruction/cross-process calls outside critical sections, and bounded
|
||||
wait/cancellation protocols where the API supports them. A timeout on the
|
||||
caller does not cancel server work by itself.
|
||||
|
||||
If work moves to another apartment, marshal apartment-bound interfaces, keep
|
||||
captured state alive, and dispatch UI updates to the correct thread. Merely
|
||||
capturing a COM pointer and `this` in a worker lambda is not a safe fix.
|
||||
|
||||
## Validation
|
||||
|
||||
Identify the affected thread, relevant resources and owners, and demonstrated
|
||||
cycle or deepest supported blocker. Test the proposed remedy under concurrency,
|
||||
reentrancy, shutdown, and timeout/cancellation. Do not stop at "waiting in RPC."
|
||||
If the server dump or an owner edge is missing, state the unresolved hypothesis.
|
||||
|
||||
## References
|
||||
|
||||
- [Wait Chain Traversal](https://learn.microsoft.com/windows/win32/debug/wait-chain-traversal)
|
||||
- [Processes, threads, and COM apartments](https://learn.microsoft.com/windows/win32/com/processes--threads--and-apartments)
|
||||
- [Process inspection](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-process)
|
||||
- [Thread inspection](https://learn.microsoft.com/windows-hardware/drivers/debuggercmds/-thread)
|
||||
|
||||
## Feedback
|
||||
|
||||
Follow `FEEDBACK.md` and submit only reviewed, sanitized feedback to
|
||||
[WinDbg-Feedback](https://github.com/microsoft/WinDbg-Feedback/issues).
|
||||
Include `windbg-user-wait-chain-analysis` and the package version from `plugin.json`; no
|
||||
automatic capture or public upload of process dumps or full diagnostic
|
||||
transcripts.
|
||||
Reference in New Issue
Block a user