Commands
.sympath srv*
.reload
x notepad!*
Loading symbols
Listing modules lm
shows that most modules don't yet have the symbols:
0:000> lm
00007ff9`232b0000 00007ff9`233b0000 ucrtbase (deferred)
00007ff9`233b0000 00007ff9`233d2000 win32u (deferred)
00007ff9`233e0000 00007ff9`2347d000 msvcp_win (deferred)
00007ff9`23770000 00007ff9`23a39000 KERNELBASE (deferred)
00007ff9`23ac0000 00007ff9`23bcb000 gdi32full (deferred)
00007ff9`23bd0000 00007ff9`23c8d000 KERNEL32 (deferred)
00007ff9`242b0000 00007ff9`24450000 USER32 (deferred)
00007ff9`25a40000 00007ff9`25a6a000 GDI32 (pdb symbols) C:\ProgramData\Dbg\sym\gdi32.pdb\26374D0C904F7078CBA564E8FCA58EE71\gdi32.pdb
00007ff9`25b70000 00007ff9`25d66000 ntdll (pdb symbols) C:\ProgramData\Dbg\sym\ntdll.pdb\432F2B8588C52E47219EE25E35F653491\ntdll.pdb
So, let's refresh at least USER32
and KERNEL32
:
0:000> ld USER32
Symbols loaded for USER32
0:000> ld KERNEL32
Symbols loaded for KERNEL32
Executing lm
again now shows that USER32
and KERNEL32
have their symbols updated:
O:OOO> lm
00007ff9`232b0000 00007ff9`233b0000 ucrtbase (deferred)
00007ff9`233b0000 00007ff9`233d2000 win32u (deferred)
00007ff9`233e0000 00007ff9`2347d000 msvcp_win (deferred)
00007ff9`23770000 00007ff9`23a39000 KERNELBASE (deferred)
00007ff9`23ac0000 00007ff9`23bcb000 gdi32full (deferred)
00007ff9`23bd0000 00007ff9`23c8d000 KERNEL32 (pdb symbols) C:\ProgramData\Dbg\sym\kernel32.pdb\789BD698F50E4D3F96DDF36A5D4BAD6E1\kernel32.pdb
00007ff9`242b0000 00007ff9`24450000 USER32 (pdb symbols) C:\ProgramData\Dbg\sym\user32.pdb\EF56DB6F9CC97AD4E21FDF7B2A0A0FEA1\user32.pdb
00007ff9`25a40000 00007ff9`25a6a000 GDI32 (pdb symbols) C:\ProgramData\Dbg\sym\gdi32.pdb\26374D0C904F7078CBA564E8FCA58EE71\gdi32.pdb
00007ff9`25b70000 00007ff9`25d66000 ntdll (pdb symbols) C:\ProgramData\Dbg\sym\ntdll.pdb\432F2B8588C52E47219EE25E35F653491\ntdll.pdb
Expressions
When a command expects a value, the value can be specified using an expression. The expression can contain names of registers and addressed in the module!function+byte
format:
bp EIP+1
u ntdll!CsrSetPriorityClass+0x41
dd ebp+4
Numerical expressions
By default, numerical are interpreted as hexadecimally formatted. In order to specify, the numbers can be prefixed with 0x
(explicitly hexadecimal), 0n
(base 10), 0t
(octal) 0y
(binary).
The default base can be changed with n
.
The .formats
command displays a number in various formats:
0:000> .formats 0n4096
Evaluate expression:
Hex: 00000000`00001000
Decimal: 4096
Octal: 0000000000000000010000
Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00010000 00000000
Chars: ........
Time: Thu Jan 1 02:08:16 1970
Float: low 5.73972e-042 high 0
Double: 2.02369e-320
«Mathematical» expressions are calculated using the question mark:
0:000> ? FF+1
Evaluate expression: 256 = 00000000`00000100
The double-questionmark (??
) allows to evaluate a C++ expression.
.expr
specifies the default expression evaluator:
.expr /s masm
.expr /s c++
.expr /q
displays the list of possible expression types.
?
The question mark evaluates a MASM expression.
An interesting feature are source line expressions: prog.c:42
.
??
When evaluating C++ expressions, register names need to be prefixed with an @
The default base for numerals is 10.
Display data
dv
displays local variables. dv /i
classifies them into categories, dv /V
shows addresses and offsets for the relevant base frame register, dv /t
shows type information.
dd rdx L1
, dd rdx L2
, …
poi
poi(addr)
dereferences an address (pointer).
For example, if the rdx
register stores a pointer to char*
(as for example for the argv
parameter in main
), the value of this string (argv[0]
) can be displayed with da poi(rdx)
.
In C++ expression evaluation, this expression would be equivalent to ?? *(char**) @rdx
.
The value of the argv[1]
is displayed with da poi(rdx+8)
, the value of argv[2]
with da poi(rdx+10)
etc.
Breakpoints
Breakpoints can be set with bu
, bp
and bm
.
bp
converts the given expression into an address and are not saved in the workspace.
bu
stays asssociated with the symbolic value.
A breakpoint can be set on the entry point for an executable with code bp $exentry
or bp @$exentry
(which at least for console applications seems to be something like conhost!wWinMainCRTStartup
)
Another interesting breakpoint seems to be conhost!wWinMain
Breakpoints that have been set are shown with bl
:
0:000> bu prog_64!main
0:000> bl
0 e Disable Clear 00007ff9`25c40670 0001 (0001) 0:**** ntdll!LdrpDoDebuggerBreak+0x30
1 e Disable Clear 00007ff6`34b47280 0001 (0001) 0:**** prog_64!main
The breakpoint at ntdll!LdrpDoDebuggerBreak+0x30
seems to be set by default.
A breakpoint can be disabled with bd
and cleared with bc
:
bd 1
bc 1
Scriptproviders
0:000> .scriptproviders
Available Script Providers:
NatVis (extension '.NatVis')
JavaScript (extension '.js')
NatVis
There are three default NatVis extensions:
dx @$cursession
dx @$curthread
dx @$cursession
dx @$curthread.Registers
dx @$curthread.Registers.User
Others
.exepath
sets or displays the executable file search path.
p
executes a single instruction or a source line», pt
goes to next ret
, gu
(go up) finished the current function
d…
displays memory, dd…
displays referenced memory
kv
displays stack backtrace.
dt nt!_KPROCESS
and dt nt!_EPROCESS
dt ntdll!*IMAGE_*
, dt ntdll!_IMAGE_NT_HEADERS64
etc
Simple debugging session
Show specific symbols in a module
Show symbols in the notepad module that contain main
:
0:000> x notepad!*main*
00007ff6`3d17ac68 notepad!__mainCRTStartup (void)
00007ff6`3d17b8e3 notepad!__mainCRTStartup$filt$0 (void)
00007ff6`3d17cf68 notepad!_imp___getmainargs = <no type information>
00007ff6`3d164238 notepad!WinMain (<no parameter info>)
00007ff6`3d17ac50 notepad!WinMainCRTStartup (<no parameter info>)
Put a breakpoint on WinMain
bu notepad!WinMain
Break into running applcation
Menu Debug -> Break or keyboard shortcut ctrl+break
.
Set another breakpoint
bu ntdll!ZwWriteFile
Wait for breakpoint
Go to notepad and save the document. The breakpoint will be hit.
Quit debugging and detach from application
qd
Symbol related
Set or append to the symbol file path
symset p:\ath\to\a\dir
symset+ p:\ath\to\another\dir
Set the symbol path to the Microsoft symbol store.
.symfix
The following command turns on symbol loading diagnostics to trouble shoot symbol file related issues
!sym noisy
Thread related
Show all threads in process
~
Look at stack trace of another thread
~0s
k
Attaching to a running process
In order to attach WinDbg to a running
process, it
process id (which uniquely identifies a process) must be known.
In an already running WinDbg application, the Keyboard shortcut <F6>
or the menu File -> Attach to a process can be used to attach to a process.
On the command line, a new WinDbg instance can be started like so
windbg -p <pid>
windbg -pn <pid>