On Windows, the LFH (Low
Fragmentation Heap) is commonly used to dynamically allocate small chunks of
memory (<16KB in size). Many programs use the LFH as it is intended for high
performance allocation/free of small objects, even in a multithreaded
environment. Debugging memory corruptions on the heap can often be complex, but
the following Windbg tricks may help:
1) The memory address is inside a current allocation- Windbg displays the call stack that led to the allocation.
- !heap -p -a MEMORY_ADDRESS
1) The memory address is inside a current allocation- Windbg displays the call stack that led to the allocation.
2) The memory address is inside an allocation that was freed- Windbg displays the call stack that led to the free.
Using this command requires the
page heap to be enabled. Page heap can be enabled per application using the
gflags.exe utility that is distributed in the Windbg package.
- Caller Based Conditional Breakpoint
This
Caller Based Conditional Breakpoint is very useful when one is interested in
the place where the object gets allocated/freed, especially when the allocation/free
codepath is very “hot” (meaning it is executed very often). The idea behind this breakpoint is to only break when there is a certain function (MemberFunction in the example below) on the call stack (ie only break if a certain function called this function directly or indirectly). If a breakpoint is
placed on the constructor/destructor of the object’s class, and the object is
allocated/freed very often, this could result in the breakpoint getting hit
many more times that a human can reasonably look at. For this reason, placing a
Caller Based Conditional Breakpoint in the constructor/destructor usually greatly
reduces the number of times the breakpoint is hit, allowing a human to
reasonably be able to investigate each time the breakpoint is hit. The Caller
Based Conditional Breakpoint is of the following format:
bp Module!MyFunctionWithConditionalBreakpoint "r $t0
= 0;.foreach (v { k }) { .if ($spat(\"v\", \"*Module!ClassA:MemberFunction*\"))
{ r $t0 = 1;.break } }; .if($t0 = 0) { gc }"
- Register Watching Breakpoint
The
Register Watching Breakpoint is a slight variation on the Caller Based
Conditional Breakpoint. In the Register Watching Breakpoint, instead of
actually breaking when the appropriate caller is on the call stack, the command
in Caller Based Conditional Breakpoint is modified to just print the CPU registers
(using the ‘r’ command). Very often, in destructors, the address of the object
that is being destroyed is in one of the CPU registers. The end result would be
that each time the Register Watching Breakpoint is hit, the CPU registers will
be printed rather than breaking execution. Since computers are very
deterministic machines, if there is no entropy introduced in the program’s
execution, one can count the number of times the breakpoint was hit before the
object of interest was freed, and predict it the next time the program is run,
and eventually get a live debugging session which is watching the object as it is
being freed. The Register Watching Breakpoint is of the following format:
bp Module!MyFunctionWithConditionalBreakpoint "r $t0
= 0;.foreach (v { k }) { .if ($spat(\"v\", \"* Module!ClassA:MemberFunction
*\")) { r; r $t0 = 1; gc; } }; .if($t0 = 0) { gc }"
References: