windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/dbgext/heapfind.cxx

369 lines
7.3 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995-1997 Microsoft Corporation
Module Name:
heapfind.cxx
Abstract:
This module contains an NTSD debugger extension for dumping various
bits of heap information.
Author:
Keith Moore (keithmo) 01-Nov-1997
Revision History:
--*/
#include "inetdbgp.h"
typedef struct _ENUM_CONTEXT {
ULONG SizeToDump;
ULONG DumpCount;
PUCHAR BlockToSearchFor;
BOOLEAN ContinueEnum;
} ENUM_CONTEXT, *PENUM_CONTEXT;
/************************************************************
* Dump Heap Info
************************************************************/
BOOLEAN
CALLBACK
HfpEnumHeapSegmentEntriesProc(
IN PVOID Param,
IN PHEAP_ENTRY LocalHeapEntry,
IN PHEAP_ENTRY RemoteHeapEntry
)
/*++
Routine Description:
Callback invoked for each heap entry within a heap segment.
Arguments:
Param - An uninterpreted parameter passed to the enumerator.
LocalHeapEntry - Pointer to a local copy of the HEAP_ENTRY structure.
RemoteHeapEntry - The remote address of the HEAP_ENTRY structure
in the debugee.
Return Value:
BOOLEAN - TRUE if the enumeration should continue, FALSE if it
should be terminated.
--*/
{
PENUM_CONTEXT context = (PENUM_CONTEXT)Param;
PUCHAR entryStart;
ULONG entryLength;
BOOLEAN dumpBlock = FALSE;
//
// allow user to break out of lengthy enumeration
//
if( CheckControlC() ) {
context->ContinueEnum = FALSE;
return TRUE;
}
//
// Ignore free blocks.
//
if( !( LocalHeapEntry->Flags & HEAP_ENTRY_BUSY ) ) {
return TRUE;
}
//
// Calculate the start & length of the heap block.
//
entryStart = (PUCHAR)RemoteHeapEntry + sizeof(HEAP_ENTRY);
entryLength = ( (ULONG)LocalHeapEntry->Size << HEAP_GRANULARITY_SHIFT ) -
(ULONG)LocalHeapEntry->UnusedBytes;
//
// Decide how to handle this request.
//
if( context->BlockToSearchFor != NULL ) {
//
// The user is looking for the heap block that contains a
// specific address. If the current block is a match, then
// dump it and terminate the enumeration.
//
if( context->BlockToSearchFor >= entryStart &&
context->BlockToSearchFor < ( entryStart + entryLength ) ) {
dumpBlock = TRUE;
context->ContinueEnum = FALSE;
}
} else {
//
// The user is looking for blocks of a specific size. If the
// size matches, or the user is looking for "big" blocks and
// the current block is >= 64K, then dump it.
//
if( context->SizeToDump == entryLength ||
( context->SizeToDump == 0xFFFFFFFF && entryLength >= 65536 ) ) {
dumpBlock = TRUE;
}
}
if( dumpBlock ) {
context->DumpCount++;
dprintf(
"HeapEntry @ %08lp [%08lp], flags = %02x, length = %lx\n",
RemoteHeapEntry,
entryStart,
(ULONG)LocalHeapEntry->Flags,
entryLength
);
}
return context->ContinueEnum;
} // HfpEnumHeapSegmentEntriesProc
BOOLEAN
CALLBACK
HfpEnumHeapSegmentsProc(
IN PVOID Param,
IN PHEAP_SEGMENT LocalHeapSegment,
IN PHEAP_SEGMENT RemoteHeapSegment,
IN ULONG HeapSegmentIndex
)
/*++
Routine Description:
Callback invoked for each heap segment within a heap.
Arguments:
Param - An uninterpreted parameter passed to the enumerator.
LocalHeapSegment - Pointer to a local copy of the HEAP_SEGMENT
structure.
RemoteHeapSegment - The remote address of the HEAP_SEGMENT
structure in the debugee.
Return Value:
BOOLEAN - TRUE if the enumeration should continue, FALSE if it
should be terminated.
--*/
{
PENUM_CONTEXT context = (PENUM_CONTEXT)Param;
//
// Enumerate the entries for the specified segment.
//
if( !EnumHeapSegmentEntries(
LocalHeapSegment,
RemoteHeapSegment,
HfpEnumHeapSegmentEntriesProc,
(PVOID)context
) ) {
dprintf( "error retrieving heap segment entries\n" );
return FALSE;
}
return context->ContinueEnum;
} // HfpEnumHeapSegmentsProc
BOOLEAN
CALLBACK
HfpEnumHeapsProc(
IN PVOID Param,
IN PHEAP LocalHeap,
IN PHEAP RemoteHeap,
IN ULONG HeapIndex
)
/*++
Routine Description:
Callback invoked for each heap within a process.
Arguments:
Param - An uninterpreted parameter passed to the enumerator.
LocalHeap - Pointer to a local copy of the HEAP structure.
RemoteHeap - The remote address of the HEAP structure in the debugee.
Return Value:
BOOLEAN - TRUE if the enumeration should continue, FALSE if it
should be terminated.
--*/
{
PENUM_CONTEXT context = (PENUM_CONTEXT)Param;
//
// Enumerate the segments for the specified heap.
//
if( !EnumHeapSegments(
LocalHeap,
RemoteHeap,
HfpEnumHeapSegmentsProc,
(PVOID)context
) ) {
dprintf( "error retrieving heap segments\n" );
return FALSE;
}
return context->ContinueEnum;
} // HfpEnumHeapsProc
DECLARE_API( heapfind )
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
heap information.
Arguments:
hCurrentProcess - Supplies a handle to the current process (at the
time the extension was called).
hCurrentThread - Supplies a handle to the current thread (at the
time the extension was called).
CurrentPc - Supplies the current pc at the time the extension is
called.
lpExtensionApis - Supplies the address of the functions callable
by this extension.
lpArgumentString - Supplies the asciiz string that describes the
ansi string to be dumped.
Return Value:
None.
--*/
{
ENUM_CONTEXT context;
INIT_API();
//
// Setup.
//
RtlZeroMemory(
&context,
sizeof(context)
);
context.ContinueEnum = TRUE;
//
// Skip leading blanks.
//
while( *lpArgumentString == ' ' ||
*lpArgumentString == '\t' ) {
lpArgumentString++;
}
if( *lpArgumentString == '\0' || *lpArgumentString != '-' ) {
PrintUsage( "heapfind" );
return;
}
lpArgumentString++;
//
// Interpret the command-line switch.
//
switch( *lpArgumentString ) {
case 'a' :
case 'A' :
lpArgumentString++;
context.BlockToSearchFor = (PUCHAR)strtoul( lpArgumentString, NULL, 16 );
break;
case 's' :
case 'S' :
lpArgumentString++;
context.SizeToDump = (ULONG)strtoul( lpArgumentString, NULL, 16 );
break;
default :
PrintUsage( "heapfind" );
return;
}
//
// Enumerate the heaps, which will enumerate the segments, which
// will enumerate the entries, which will search for the specified
// address or specified size.
//
if( !EnumProcessHeaps(
HfpEnumHeapsProc,
(PVOID)&context
) ) {
dprintf( "error retrieving process heaps\n" );
} else {
if (context.DumpCount > 0) {
dprintf( "Total count: %08lx\n", context.DumpCount);
}
}
} // DECLARE_API( heapfind )