summaryrefslogtreecommitdiffstats
path: root/private/mvdm/vdmexts/heap.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/vdmexts/heap.c')
-rw-r--r--private/mvdm/vdmexts/heap.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/private/mvdm/vdmexts/heap.c b/private/mvdm/vdmexts/heap.c
new file mode 100644
index 000000000..298be7479
--- /dev/null
+++ b/private/mvdm/vdmexts/heap.c
@@ -0,0 +1,449 @@
+/*++
+
+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;
+
+ //BUGBUG SLIMY SLIMY! Look around for a selector that appears to be
+ // the kernel heap
+
+ for (selector=0x1bf; selector<0x1ff; selector+=8) {
+
+ GetInfoFromSelector(selector, PROT_MODE, &si);
+ if ((!si.bSystem) && (!si.bCode) && (si.Limit>0xffff)) {
+ break;
+ }
+ si.Base = 0;
+ }
+
+ 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;
+
+ 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(" %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);
+ }
+ PRINTF("\n");
+
+ }
+
+}
+
+VOID
+UpdateLockCount(
+ int count
+ )
+{
+ HEAPENTRY he = {0};
+ SELECTORINFO si;
+ 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);
+}