Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

454 lines
9.7 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
heap.c
Abstract:
This function contains the default ntsd debugger extensions
Author:
Bob Day (bobday) 29-Feb-1992 Grabbed standard header
Revision History:
Neil Sandlin (NeilSa) 15-Jan-1996 Merged with vdmexts
--*/
#include <precomp.h>
#pragma hdrstop
BOOL bWalkOnly = FALSE;
ULONG
GetHeapBase(
VOID
)
{
WORD selector;
SELECTORINFO si;
if (!ReadMemExpression("ntvdmd!DbgWowhGlobalHeap", &selector, sizeof(selector))) {
return 0;
}
GetInfoFromSelector(selector, PROT_MODE, &si);
return(si.Base + GetIntelBase());
}
void
GetFileNameFromOwner(
LPSTR filename,
LPSTR OwnerName
)
{
}
VOID
GetHeapOwnerInfo(
HEAPENTRY *he
)
{
BOOL b;
NEHEADER owner;
ULONG base;
UCHAR len;
int i;
ULONG offset;
WORD wTemp;
he->SegmentNumber = -1;
he->OwnerName[0] = 0;
if (he->gnode.pga_owner == 0) {
strcpy(he->OwnerName, "free");
return;
} else if (he->gnode.pga_owner>=0xFFF8) {
strcpy(he->OwnerName, "sentinel");
return;
}
base = GetInfoFromSelector(he->gnode.pga_owner, PROT_MODE, NULL)
+ GetIntelBase();
b = READMEM((LPVOID)base, &owner, sizeof(owner));
if (b) {
if (owner.ne_magic == 0x454e) {
len = ReadByteSafe(base+owner.ne_restab);
if (len>8) {
len=8;
}
READMEM((LPVOID)(base+owner.ne_restab+1), he->OwnerName, 8);
he->OwnerName[len] = 0;
if (!_stricmp(he->OwnerName, "kernel")) {
strcpy(he->FileName, "krnl386");
} else {
strcpy(he->FileName, he->OwnerName);
}
offset = owner.ne_segtab;
for (i=0; i<owner.ne_cseg; i++) {
wTemp = ReadWordSafe(base+offset+8); //get handle
if (wTemp == he->gnode.pga_handle) {
he->SegmentNumber = i;
break;
}
offset += 10;
}
}
}
}
BOOL
CheckGlobalHeap(
BOOL bVerbose
)
{
PGHI32 pghi;
DWORD offset, prevoffset;
DWORD count, heapcount;
DWORD p;
GNODE32 gnode;
PBYTE pFault = NULL;
BOOL bError = FALSE;
pghi = (PGHI32)GetHeapBase();
prevoffset = offset = (DWORD) ReadWord(&pghi->hi_first);
heapcount = count = ReadWord(&pghi->hi_count);
if (bVerbose) {
PRINTF("Global Heap is at %08X\n", pghi);
}
while ((offset != 0) && (count)) {
if (offset&0x1f) {
PRINTF("Error! Kernel heap entry(%08X) contains invalid forward link (%08X)\n", prevoffset, offset);
return FALSE;
}
p = (DWORD)pghi + offset;
if (!ReadGNode32Safe(p, &gnode)) {
PRINTF("Error! Kernel heap entry(%08X) contains invalid forward link (%08X)\n", prevoffset, offset);
return FALSE;
}
if (count == heapcount) {
// first entry
if (offset != gnode.pga_prev) {
PRINTF("Error! Kernel heap entry (%08X) contains invalid back link (%08X)\n", offset, gnode.pga_prev);
PRINTF(" expecting (%08X)\n", offset);
return FALSE;
}
} else {
if (prevoffset != gnode.pga_prev) {
PRINTF("Error! Kernel heap entry (%08X) contains invalid back link (%08X)\n", offset, gnode.pga_prev);
PRINTF(" expecting (%08X)\n", prevoffset);
return FALSE;
}
}
prevoffset = offset;
count--;
if (offset == gnode.pga_next) {
if (!count) {
if (bVerbose) {
PRINTF("%d entries scanned\n", heapcount);
}
return TRUE;
} else {
PRINTF("Error! Kernel heap count (%d) larger then forward chain (%d)\n", heapcount, heapcount-count);
}
}
offset = gnode.pga_next;
}
PRINTF("Error! Kernel heap count (%d) smaller then forward chain\n", heapcount);
return FALSE;
}
BOOL
FindHeapEntry(
HEAPENTRY *he,
UINT FindMethod,
BOOL bVerbose
)
{
PGHI32 pghi;
DWORD offset;
DWORD MaxEntries, count;
DWORD p;
PBYTE pFault = NULL;
BOOL bError = FALSE;
pghi = (PGHI32)GetHeapBase();
//
// Verify that we are looking at a heap
//
offset = (DWORD) ReadWordSafe(&pghi->hi_first);
p = (DWORD)pghi + offset;
if (!ReadGNode32Safe(p, &he->gnode)) {
if (bVerbose) {
PRINTF("Heap not available\n");
}
return FALSE;
}
if (offset != he->gnode.pga_prev) {
if (bVerbose) {
PRINTF("Heap not valid\n");
}
return FALSE;
}
//
// The caller has requested that we return the next heap
// entry since the last invocation, or the first entry.
//
if (he->CurrentEntry == 0) {
// get first entry
offset = (DWORD) ReadWord(&pghi->hi_first);
} else {
if (he->CurrentEntry == he->NextEntry) {
return FALSE;
}
// get next entry
offset = he->NextEntry;
}
he->CurrentEntry = offset;
if ((he->Selector == 0) && (FindMethod != FHE_FIND_MOD_ONLY)) {
p = (DWORD)pghi + offset;
if (!ReadGNode32(p, &he->gnode)) {
return FALSE;
}
he->NextEntry = he->gnode.pga_next;
GetHeapOwnerInfo(he);
return TRUE;
}
//
// If we get here, the caller wants us to scan the heap
//
MaxEntries = ReadWord(&pghi->hi_count);
count = 0;
while ((offset != 0) && (count <= MaxEntries)) {
p = (DWORD)pghi + offset;
if (!ReadGNode32(p, &he->gnode)) {
return FALSE;
} else {
if (FindMethod == FHE_FIND_ANY) {
WORD sel = he->Selector;
if (((sel|1)==((WORD)he->gnode.pga_handle|1)) ||
((sel|1)==((WORD)he->gnode.pga_owner|1)) ||
(sel==offset))
{
he->NextEntry = he->gnode.pga_next;
GetHeapOwnerInfo(he);
return TRUE;
}
} else if (FindMethod == FHE_FIND_MOD_ONLY) {
GetHeapOwnerInfo(he);
if (!_stricmp(he->OwnerName, he->ModuleArg)) {
he->NextEntry = he->gnode.pga_next;
return TRUE;
}
} else {
if ((he->Selector|1)==((WORD)he->gnode.pga_handle|1)) {
he->NextEntry = he->gnode.pga_next;
GetHeapOwnerInfo(he);
return TRUE;
}
}
}
count++;
if (offset == he->gnode.pga_next) {
break;
}
offset = he->gnode.pga_next;
he->CurrentEntry = offset;
}
return FALSE;
}
VOID
chkheap(
CMD_ARGLIST
)
{
CMD_INIT();
if (CheckGlobalHeap(TRUE)) {
PRINTF("Heap checks OK\n");
}
}
//*************************************************************
// dumpgheap xxx
// where xxx is the 16-bit protect mode selector of the
// Kernel global heap info.
//
//*************************************************************
VOID
dgh(
CMD_ARGLIST
)
{
HEAPENTRY he = {0};
SELECTORINFO si;
ULONG TotalAllocated = 0;
ULONG TotalFree = 0;
ULONG CountPrinted = 0;
CMD_INIT();
if (GetNextToken()) {
he.Selector = (WORD) EXPRESSION( lpArgumentString );
}
PRINTF("Arena Base Limit Hnd Own Fl Lk Module Type Resid");
PRINTF("\n");
PRINTF("===== ======== ======== ==== ==== == == ======== ==== =====");
PRINTF("\n");
while (FindHeapEntry(&he, FHE_FIND_ANY, FHE_FIND_VERBOSE)) {
PRINTF("%.5x", he.CurrentEntry);
PRINTF(" %.8x", he.gnode.pga_address);
PRINTF(" %.8X", he.gnode.pga_size);
PRINTF(" %.4X", he.gnode.pga_handle);
PRINTF(" %.4X", he.gnode.pga_owner);
PRINTF(" %.2X", he.gnode.pga_flags);
PRINTF(" %.2X", he.gnode.pga_count);
PRINTF(" %-8.8s", he.OwnerName);
GetInfoFromSelector((WORD)(he.gnode.pga_handle | 1), PROT_MODE, &si);
PRINTF(" %s", si.bCode ? "Code" : "Data");
if (he.SegmentNumber != -1) {
PRINTF(" %d", he.SegmentNumber+1);
}
PRINTF("\n");
if (!he.gnode.pga_owner) {
TotalFree += he.gnode.pga_size;
} else {
TotalAllocated += he.gnode.pga_size;
}
CountPrinted++;
}
if (CountPrinted > 1) {
PRINTF("\n Allocated = %dK, Free = %dK\n", TotalAllocated/1024, TotalFree/1024);
}
}
VOID
UpdateLockCount(
int count
)
{
HEAPENTRY he = {0};
BYTE LockCount;
if (GetNextToken()) {
he.Selector = (WORD) EXPRESSION( lpArgumentString );
} else {
PRINTF("Please enter a selector or handle\n");
return;
}
if (FindHeapEntry(&he, FHE_FIND_SEL_ONLY, FHE_FIND_VERBOSE)) {
if (READMEM((LPVOID)(GetHeapBase()+he.CurrentEntry+0x14), &LockCount, 1)) {
LockCount = (BYTE)((int) LockCount + count);
WRITEMEM((LPVOID)(GetHeapBase()+he.CurrentEntry+0x14), &LockCount, 1);
PRINTF("Lock count for %.4X is now %d\n", he.Selector, LockCount);
} else {
PRINTF("<can't read memory at that location>\n");
}
} else {
PRINTF("Can't find selector %4X in WOW heap\n", he.Selector);
}
}
VOID
glock(
CMD_ARGLIST
)
{
CMD_INIT();
UpdateLockCount(1);
}
VOID
gunlock(
CMD_ARGLIST
)
{
CMD_INIT();
UpdateLockCount(-1);
}