{
if ((Tag >= 'a' && Tag <= 'z') ||
(Tag >= 'A' && Tag <= 'Z') ||
- Tag == ' ')
+ (Tag >= '0' && Tag <= '9') ||
+ Tag == ' ' || Tag == '=' ||
+ Tag == '?' || Tag == '@')
{
return TRUE;
}
return FALSE;
}
+#ifdef KDBG
#define MiDumperPrint(dbg, fmt, ...) \
if (dbg) KdbpPrint(fmt, ##__VA_ARGS__); \
else DPRINT1(fmt, ##__VA_ARGS__)
+#else
+#define MiDumperPrint(dbg, fmt, ...) \
+ DPRINT1(fmt, ##__VA_ARGS__)
+#endif
VOID
-MiDumpNonPagedPoolConsumers(BOOLEAN CalledFromDbg)
+MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask, ULONG Flags)
{
SIZE_T i;
+ BOOLEAN Verbose;
//
// Only print header if called from OOM situation
DPRINT1("---------------------\n");
DPRINT1("Out of memory dumper!\n");
}
+#ifdef KDBG
else
{
KdbpPrint("Pool Used:\n");
}
+#endif
+
+ //
+ // Remember whether we'll have to be verbose
+ // This is the only supported flag!
+ //
+ Verbose = BooleanFlagOn(Flags, 1);
//
// Print table header
//
- MiDumperPrint(CalledFromDbg, "\t\tNonPaged\t\t\tPaged\n");
- MiDumperPrint(CalledFromDbg, "Tag\t\tAllocs\t\tUsed\t\tAllocs\t\tUsed\n");
+ if (Verbose)
+ {
+ MiDumperPrint(CalledFromDbg, "\t\t\t\tNonPaged\t\t\t\t\t\t\tPaged\n");
+ MiDumperPrint(CalledFromDbg, "Tag\t\tAllocs\t\tFrees\t\tDiff\t\tUsed\t\tAllocs\t\tFrees\t\tDiff\t\tUsed\n");
+ }
+ else
+ {
+ MiDumperPrint(CalledFromDbg, "\t\tNonPaged\t\t\tPaged\n");
+ MiDumperPrint(CalledFromDbg, "Tag\t\tAllocs\t\tUsed\t\tAllocs\t\tUsed\n");
+ }
//
// We'll extract allocations for all the tracked pools
{
//
// If there's a tag, attempt to do a pretty print
+ // only if it matches the caller's tag, or if
+ // any tag is allowed
+ // For checking whether it matches caller's tag,
+ // use the mask to make sure not to mess with the wildcards
//
- if (TableEntry->Key != 0 && TableEntry->Key != TAG_NONE)
+ if (TableEntry->Key != 0 && TableEntry->Key != TAG_NONE &&
+ (Tag == 0 || (TableEntry->Key & Mask) == (Tag & Mask)))
{
CHAR Tag[4];
if (ExpTagAllowPrint(Tag[0]) && ExpTagAllowPrint(Tag[1]) && ExpTagAllowPrint(Tag[2]) && ExpTagAllowPrint(Tag[3]))
{
//
- // Print in reversed order to match what is in source code
+ // Print in direct order to make !poolused TAG usage easier
//
- MiDumperPrint(CalledFromDbg, "'%c%c%c%c'\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n", Tag[3], Tag[2], Tag[1], Tag[0],
- TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes,
- TableEntry->PagedAllocs, TableEntry->PagedBytes);
+ if (Verbose)
+ {
+ MiDumperPrint(CalledFromDbg, "'%c%c%c%c'\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n", Tag[0], Tag[1], Tag[2], Tag[3],
+ TableEntry->NonPagedAllocs, TableEntry->NonPagedFrees,
+ (TableEntry->NonPagedAllocs - TableEntry->NonPagedFrees), TableEntry->NonPagedBytes,
+ TableEntry->PagedAllocs, TableEntry->PagedFrees,
+ (TableEntry->PagedAllocs - TableEntry->PagedFrees), TableEntry->PagedBytes);
+ }
+ else
+ {
+ MiDumperPrint(CalledFromDbg, "'%c%c%c%c'\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n", Tag[0], Tag[1], Tag[2], Tag[3],
+ TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes,
+ TableEntry->PagedAllocs, TableEntry->PagedBytes);
+ }
}
else
{
- MiDumperPrint(CalledFromDbg, "%x\t%ld\t\t%ld\t\t%ld\t\t%ld\n", TableEntry->Key,
- TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes,
- TableEntry->PagedAllocs, TableEntry->PagedBytes);
+ if (Verbose)
+ {
+ MiDumperPrint(CalledFromDbg, "%x\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n", TableEntry->Key,
+ TableEntry->NonPagedAllocs, TableEntry->NonPagedFrees,
+ (TableEntry->NonPagedAllocs - TableEntry->NonPagedFrees), TableEntry->NonPagedBytes,
+ TableEntry->PagedAllocs, TableEntry->PagedFrees,
+ (TableEntry->PagedAllocs - TableEntry->PagedFrees), TableEntry->PagedBytes);
+ }
+ else
+ {
+ MiDumperPrint(CalledFromDbg, "%x\t%ld\t\t%ld\t\t%ld\t\t%ld\n", TableEntry->Key,
+ TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes,
+ TableEntry->PagedAllocs, TableEntry->PagedBytes);
+ }
}
}
- else
+ else if (Tag == 0 || (Tag & Mask) == (TAG_NONE & Mask))
{
- MiDumperPrint(CalledFromDbg, "Anon\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n",
- TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes,
- TableEntry->PagedAllocs, TableEntry->PagedBytes);
+ if (Verbose)
+ {
+ MiDumperPrint(CalledFromDbg, "Anon\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n",
+ TableEntry->NonPagedAllocs, TableEntry->NonPagedFrees,
+ (TableEntry->NonPagedAllocs - TableEntry->NonPagedFrees), TableEntry->NonPagedBytes,
+ TableEntry->PagedAllocs, TableEntry->PagedFrees,
+ (TableEntry->PagedAllocs - TableEntry->PagedFrees), TableEntry->PagedBytes);
+ }
+ else
+ {
+ MiDumperPrint(CalledFromDbg, "Anon\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n",
+ TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes,
+ TableEntry->PagedAllocs, TableEntry->PagedBytes);
+ }
}
}
}
/* PRIVATE FUNCTIONS **********************************************************/
+INIT_FUNCTION
VOID
NTAPI
-INIT_SECTION
ExpSeedHotTags(VOID)
{
ULONG i, Key, Hash, Index;
DPRINT1("Out of pool tag space, ignoring...\n");
}
+INIT_FUNCTION
VOID
NTAPI
-INIT_SECTION
ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor,
IN POOL_TYPE PoolType,
IN ULONG PoolIndex,
ASSERT(PoolType != PagedPoolSession);
}
+INIT_FUNCTION
VOID
NTAPI
-INIT_SECTION
InitializePool(IN POOL_TYPE PoolType,
IN ULONG Threshold)
{
#endif
//
- // FIXME: Not yet supported
+ // Get the amount of hits in the system lookaside lists
//
- *NonPagedPoolLookasideHits += 0;
- *PagedPoolLookasideHits += 0;
+ if (!IsListEmpty(&ExPoolLookasideListHead))
+ {
+ PLIST_ENTRY ListEntry;
+
+ for (ListEntry = ExPoolLookasideListHead.Flink;
+ ListEntry != &ExPoolLookasideListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ PGENERAL_LOOKASIDE Lookaside;
+
+ Lookaside = CONTAINING_RECORD(ListEntry, GENERAL_LOOKASIDE, ListEntry);
+
+ if (Lookaside->Type == NonPagedPool)
+ {
+ *NonPagedPoolLookasideHits += Lookaside->AllocateHits;
+ }
+ else
+ {
+ *PagedPoolLookasideHits += Lookaside->AllocateHits;
+ }
+ }
+ }
}
VOID
{
#if DBG
//
- // If non paged backed, display current consumption
+ // Out of memory, display current consumption
+ // Let's consider that if the caller wanted more
+ // than a hundred pages, that's a bogus caller
+ // and we are not out of memory
//
- if ((OriginalType & BASE_POOL_TYPE_MASK) == NonPagedPool)
+ if (NumberOfBytes < 100 * PAGE_SIZE)
{
- MiDumpNonPagedPoolConsumers(FALSE);
+ MiDumpPoolConsumers(FALSE, 0, 0, 0);
}
#endif
{
#if DBG
//
- // If non paged backed, display current consumption
+ // Out of memory, display current consumption
+ // Let's consider that if the caller wanted more
+ // than a hundred pages, that's a bogus caller
+ // and we are not out of memory
//
- if ((OriginalType & BASE_POOL_TYPE_MASK) == NonPagedPool)
+ if (NumberOfBytes < 100 * PAGE_SIZE)
{
- MiDumpNonPagedPoolConsumers(FALSE);
+ MiDumpPoolConsumers(FALSE, 0, 0, 0);
}
#endif
return Buffer;
}
-#if DBG && defined(KDBG)
-
-BOOLEAN
-ExpKdbgExtPool(
- ULONG Argc,
- PCHAR Argv[])
-{
- ULONG_PTR Address = 0, Flags = 0;
- PVOID PoolPage;
- PPOOL_HEADER Entry;
- BOOLEAN ThisOne;
- PULONG Data;
-
- if (Argc > 1)
- {
- /* Get address */
- if (!KdbpGetHexNumber(Argv[1], &Address))
- {
- KdbpPrint("Invalid parameter: %s\n", Argv[0]);
- return TRUE;
- }
- }
-
- if (Argc > 2)
- {
- /* Get address */
- if (!KdbpGetHexNumber(Argv[1], &Flags))
- {
- KdbpPrint("Invalid parameter: %s\n", Argv[0]);
- return TRUE;
- }
- }
-
- /* Check if we got an address */
- if (Address != 0)
- {
- /* Get the base page */
- PoolPage = PAGE_ALIGN(Address);
- }
- else
- {
- KdbpPrint("Heap is unimplemented\n");
- return TRUE;
- }
-
- /* No paging support! */
- if (!MmIsAddressValid(PoolPage))
- {
- KdbpPrint("Address not accessible!\n");
- return TRUE;
- }
-
- /* Get pool type */
- if ((Address >= (ULONG_PTR)MmPagedPoolStart) && (Address <= (ULONG_PTR)MmPagedPoolEnd))
- KdbpPrint("Allocation is from PagedPool region\n");
- else if ((Address >= (ULONG_PTR)MmNonPagedPoolStart) && (Address <= (ULONG_PTR)MmNonPagedPoolEnd))
- KdbpPrint("Allocation is from NonPagedPool region\n");
- else
- {
- KdbpPrint("Address 0x%p is not within any pool!\n", (PVOID)Address);
- return TRUE;
- }
-
- /* Loop all entries of that page */
- Entry = PoolPage;
- do
- {
- /* Check if the address is within that entry */
- ThisOne = ((Address >= (ULONG_PTR)Entry) &&
- (Address < (ULONG_PTR)(Entry + Entry->BlockSize)));
-
- if (!(Flags & 1) || ThisOne)
- {
- /* Print the line */
- KdbpPrint("%c%p size: %4d previous size: %4d %s %.4s\n",
- ThisOne ? '*' : ' ', Entry, Entry->BlockSize, Entry->PreviousSize,
- (Flags & 0x80000000) ? "" : (Entry->PoolType ? "(Allocated)" : "(Free) "),
- (Flags & 0x80000000) ? "" : (PCHAR)&Entry->PoolTag);
- }
-
- if (Flags & 1)
- {
- Data = (PULONG)(Entry + 1);
- KdbpPrint(" %p %08lx %08lx %08lx %08lx\n"
- " %p %08lx %08lx %08lx %08lx\n",
- &Data[0], Data[0], Data[1], Data[2], Data[3],
- &Data[4], Data[4], Data[5], Data[6], Data[7]);
- }
-
- /* Go to next entry */
- Entry = POOL_BLOCK(Entry, Entry->BlockSize);
- }
- while ((Entry->BlockSize != 0) && ((ULONG_PTR)Entry < (ULONG_PTR)PoolPage + PAGE_SIZE));
-
- return TRUE;
-}
-
-BOOLEAN
-ExpKdbgExtPoolUsed(
- ULONG Argc,
- PCHAR Argv[])
-{
- MiDumpNonPagedPoolConsumers(TRUE);
-
- return TRUE;
-}
-
-#endif // DBG && KDBG
-
/* EOF */