Commands

Common WinDbg Commands (Thematically Grouped)

By Robert Kuster

Collapse all examples

PDF

Collapse

Also check the "!lmi" command.

Collapse

exr -1

.exr 7c901230

!cppexr 7c901230

display most recent exception

display exception at address 7c901230

display c++ exception at address 7c901230

Collapse

Collapse

Collapse

Collapse

With bp, the breakpoint location is always converted to an address. In contrast, a bu or a bm breakpoint is always associated with the symbolic value.

Simple Examples

Breakpoitns with options

Breakpoints with commands: The command will be executed when the breakpoint is hit.

Howto set a brekpoint in your code programatically?

    • kernel32!DebugBreak

    • ntdll!DbgBreakPoint

    • __asm int 3 (x86 only)

Collapse

Collapse

To get more than 3 Function Arguments from the stack

dd ChildEBP+8 (Parameters start at ChildEBP+8)

dd ChildEBP+8 (frame X) == dd ESP (frame X-1)

Collapse

Collapse

Collapse

Determine stack usage for a thread

Stack Identifier Memory Identifier ^ --------------------------------------------------------- -------------- <- _TEB.StackBase SubRegionBase3 + SubRegionSize3 | | | MEM_COMMIT | | | |------------| <- _TEB.StackLimit SubRegionBase3 ^, SubRegionBase2 + SubRegionSize2 | PAGE_GUARD | |------------| SubRegionBase2 ^, SubRegionBase1 + SubRegionSize1 | | |MEM_RESERVED| | | |------------| <- _TEB.DeallocationStack AllocationBase or RegionBase, SubRegionBase1 ^ DeallocationStack: dt ntdll!_TEB TebAddr DeallocationStack

From MSDN CreateThread > dwStackSize > "Thread Stack Size":

"Each new thread receives its own stack space, consisting of both committed and reserved memory. By default, each thread uses 1 Mb of reserved memory, and one page of committed memory. The system will commit one page block from the reserved stack memory as needed."

Collapse

20) Memory: Heap

Cmd

!heap

!heap -b, -B

!heap -flt

!heap -stat

!heap -p

Variants / Params

!heap -?

!heap

!heap -h

!heap -h [HeapAddr | Idx | 0]

!heap -v [HeapAddr | Idx | 0]

!heap -s [HeapAddr | 0]

!heap -i [HeapAddr]

!heap -x [-v] Address

!heap -l

!heap Heap -b [alloc | realloc | free] [Tag]

!heap Heap -B [alloc | realloc | free]

!heap -flt s Size

!heap -flt r SizeMin SizeMax

!heap -stat

!heap -stat -h [HeapHandle | 0]

!heap -p -?

!heap -p

!heap -p -h HeapHandle

!heap -p -a UserAddr

!heap -p -all

Description

Brief help

List heaps with index and HeapAddr

List heaps with index and range (= startAddr(=HeapAddr), endAddr)

Detailed heap info [Idx = heap Idx, 0 = all heaps]

Validate heap [Idx = heap Idx, 0 = all heaps]

Summary info, i.e. reserved and committed memory [Idx = heap Idx, 0 = all heaps]

Detailed info for a block at given address

Search heap block containing the address (v = search the whole process virtual space)

Search for potentially leaked heap blocks

Set conditional breakpoint in the heap manager [Heap = HeapAddr | Idx | 0]

Remove a conditional breakpoint

Dump info for allocations matching the specified size

Filter by range

Dump heap handle list

Dump usage statistic for every AllocSize [HeapHandle = given heap | 0 = all heaps].

The statistic includes AllocSize, #blocks, TotalMem for each AllocSize.

Extended page heap help

Summary for NtGlobalFlag, HeapHandle + NormalHeap list **

Detailed info about a page heap with Handle

Details of heap allocation containing UserAddr. Prints backtraces when available.

Details of all allocations in all heaps in the process.

The output includes UserAddr and AllocSize for every HeapAlloc call.

It seems that the following applies for windows XP SP2:

a) Normal heap

    1. CreateHeap -> creates a _HEAP

    2. AllocHeap -> creates a _HEAP_ENTRY

b) Page heap enabled (gflags.exe /i +hpa)

    1. CreateHeap -> creates a _DPH_HEAP_ROOT (+ _HEAP + 2x _HEAP_ENTRY)**

    2. AllocHeap -> creates a _DPH_HEAP_BLOCK

** With page heap enabled there will still be a _HEAP with two constant _HEAP_ENTRY's for every CreateHeap call.

Collapse

Who allocated memory - who called HeapAlloc?

    1. Select "Create user mode stack trace database" for your image in GFlags (gflags.exe /i +ust)

    2. From WinDbg's command line do a !heap -p -a , where is the address of your allocation ***.

    3. While !heap -p -a will dump a call-stack, no source information will be included.

    4. To get source information you must additionally enable page heap in step 1 (gflags.exe /i +ust +hpa)

    5. Do a dt ntdll!_DPH_HEAP_BLOCK StackTrace , where is the DPH_HEAP_BLOCK address retrieved in step 3.

    6. Do a dds ", where is the value retrieved in step 5.

    7. Note that dds will dump the stack with source information included.

Who created a heap - who called HeapCreate?

    1. Select "Create user mode stack trace database" and "Enable page heap" for your image in GFlags (gflags.exe /i +ust +hpa)

    2. a) From WinDbg's command line do a !heap -p -h , where is the value returned by HeapCreate. You can do a !heap -stat or !heap -p to get all heap handles of your process.

    3. b) Alternatively you can use !heap -p -all to get addresses of all _DPH_HEAP_ROOT's of your process directly.

    4. Do a dt ntdll!_DPH_HEAP_ROOT CreateStackTrace , where is the address of a _DPH_HEAP_ROOT retrieved in step 2

    5. Do a dds , where is the value retrieved in step 3.

Finding memory leaks

    • From WinDbg's command line do a !address –summary.

    • If RegionUsageHeap or RegionUsagePageHeap are growing, then you might have a memory leak on the heap. Proceed with the following steps.

    1. Enable "Create user mode stack trace database" for your image in GFlags (gflags.exe /i +ust)

    2. From WinDbg's command line do a !heap -stat, to get all active heap blocks and their handles.

    3. Do a !heap -stat -h 0. This will list down handle specific allocation statistics for every AllocSize.

    4. For every AllocSize the following is listed: AllocSize, #blocks, and TotalMem. Take the AllocSize with maximum TotalMem.

    5. Do a !heap -flt s . =AllocSize that we determined in the previous step. This command will list down all blocks with that particular size.

    6. Do a !heap -p -a to get the stack trace from where you have allocated that much bytes. Use the that you got in step 4.

    7. To get source information you must additionally enable page heap in step 1 (gflags.exe /i +ust +hpa)

    8. Do a dt ntdll!_DPH_HEAP_BLOCK StackTrace , where is the DPH_HEAP_BLOCK address retrieved in step 5.

    9. Do a dds ", where is the value retrieved in step 7.

    10. Note that dds will dump the stack with source information included.

*** What is a ?

    1. is usually the address returned by HeapAlloc:

      1. int AllocSyze = 0x100000; // == 1 MB BYTE* pUserAddr = (BYTE*) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, AllocSyze);

    2. Often any address in the range [UserAddr....UserAddr+AlloSize] is also a valid parameter:

      1. !heap -p -a [UserAddr....UserAddr+AlloSize]

Collapse

Enable 19-ProcessesAndThreads and 22-StringManipulation logging: