Skip to content

Repository files navigation

CrashDrive

Mount Windows post-mortem artifacts as PSDrives — ls, cd, cat your way through crash dumps, Time-Travel Debugging recordings, and execution traces.

The Idea

A crash dump is a tree of information. A filesystem is the universal tree interface. CrashDrive surfaces post-mortem data as paths:

Import-Module CrashDrive
New-CrashDrive dmp .\crash.dmp
cd dmp:\threads\12\frames
Get-ChildItem|Format-Table Index, Method, SourceFile, Line

The same idioms humans already use (Get-ChildItem, Get-Content, cd) work identically when an AI agent browses the same drive.

Providers

ProviderOpensBackend
TracePython sys.monitoring JSONL or .NET Harmony tracedirect JSON
DumpWindows minidumps, .NET dumpsClrMD + dbgeng
TtdTime-Travel Debugging .rundbgeng + TTDAnalyze

Provider is picked automatically from the file.

Two Modes of Creating a Drive

New-CrashDrive has two parameter sets:

Mount — open an existing artifact:

New-CrashDrive foo .\crash.dmp # positional: Name, PathNew-CrashDrive tt .\recording.run
New-CrashDrive tr .\python-trace.jsonl

Capture — launch a program under a tracer, then mount the result:

New-CrashDrive app -ExecutablePath .\script.py # Python tracerNew-CrashDrive app -ExecutablePath .\MyApp.exe# .NET tracerNew-CrashDrive app -ExecutablePath .\MyApp.exe`-Include 'MyApp*'`-ExecutableArgs @('--flag','value')

-ExecutablePath is deliberately non-positional so "read an artifact" vs "execute a program" is unambiguous at the call site — one is safe reading, the other spawns a process.

-Language is auto-detected from the extension (.py/.pyw → python, .exe/.dll → dotnet) and overridable.

Path Tour

Dump drive

dmp:\
├── summary.json metadata (arch, CLR flavor, counts)
├── analyze.txt !analyze -v output (cached; skipped on non-crash snapshots)
├── threads\<id>\
│ ├── info.json
│ ├── registers.txt
│ └── frames\<n> stack frames with SourceFile + Line
├── modules\ every loaded module (native + managed)
└── heap\ GC heap types with InstanceCount + TotalBytes

TTD drive

ttd:\
├── triage.md answer-first overview
├── summary.json
├── timeline\
│ ├── events\ all events ordered by position
│ ├── exceptions\ Type matching Exception*
│ └── significant\ Module*/Thread* events
├── positions\
│ ├── start\ lifetime start
│ ├── end\ lifetime end
│ └── <major>_<minor>\ arbitrary time positions
│ └── threads\<id>\frames\<n>
├── ttd-events\ notable events during the recording
├── calls\<module>\<fn>\ every invocation of a named function
└── memory\<start>_<end>\
├── reads\ read accesses
├── writes\ write accesses
├── first-write.json first write in the range
└── last-write-before\<pos>\

Trace drive

tr:\
├── summary.json total events, types, unique functions
├── events\<n> every event in sequence order
├── by-type\<type>\ events grouped by type (call/return/exception)
├── by-function\<fn>\ events grouped by function
└── exceptions\ exception occurrences with context

Cmdlets

CmdletPurpose
New-CrashDriveMount a trace/dump/TTD, or capture a new trace + mount
Enable-CrashEditorFollowcd into a frame/event → editor jumps to the line
Disable-CrashEditorFollowTurn it off
Read-CrashMemoryRaw memory read through the shared dbgeng session
Get-CrashObjectManaged heap object inspection via ClrMD
Get-CrashLocalVariableInspect locals at a frame (dbgeng dv)

Source Resolution

  • Native frames resolve via dbgeng ln. Works when the module has private or source-indexed PDBs. Public Microsoft PDBs lack source info and return null.
  • Managed frames resolve via ClrMD + portable PDB sequence points. Requires DumpType.Full for arbitrary JIT IPs; WithHeap may resolve stack-frame IPs but is not guaranteed. Only portable PDBs are supported (matches modern .NET defaults).

With Enable-CrashEditorFollow, cd into a frame or event jumps VS Code straight to SourceFile:Line.

.NET Tracer Notes

The -Language dotnet path runs the target under a DOTNET_STARTUP_HOOKS loaded assembly that uses Harmony to patch every concrete method in the user assemblies — no changes required to the target program.

Two caveats worth knowing:

  • Requires .NET 6+ targets (the DOTNET_STARTUP_HOOKS env var is supported from .NET Core 3.1 but the tracer is built against net6.0 for ease).
  • JIT inlining. Harmony patches a method's stub; if the JIT has inlined the method into its caller, calls through that inlined copy won't be intercepted. For trivial one-liner methods (like int Add(int a, int b) => a + b), the JIT will usually inline them and Harmony can't see the calls. In real-world code where methods are non-trivial, inlining is much less aggressive and the tracer sees most calls. If you hit this for a specific method, annotate it with [MethodImpl(MethodImplOptions.NoInlining)].

Use -Include 'MyApp*' to restrict patching to specific assemblies (by name glob); otherwise the default filter patches user-authored assemblies and skips BCL / runtime / CrashDrive itself.

Requirements

  • Windows
  • PowerShell 7.4+
  • .NET 8 SDK (build only)
  • WinDbg Preview from the Microsoft Store — required for the Ttd provider (System32 dbgeng cannot open .run files)
  • Python 3.12+ — only for capturing Python traces
  • .NET 6+ target — only for capturing .NET traces

Install

From source:

.\deploy.ps1
Import-Module CrashDrive

PSGallery install will land at 1.0.

Status

Pre-1.0 (0.9.x). Core providers are operational and used regularly for real investigations; the API surface may still change before the 1.0 cut.

Related

  • DebuggerDrive — live DAP debugger as a PSDrive. CrashDrive's post-mortem sibling.

License

MIT.

About

Mount Windows post-mortem artifacts (crash dumps, TTD recordings, execution traces) as PSDrives

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages