[NTOSKRNL] Add support for verbose output in the !poolused command

This commit is contained in:
Pierre Schweitzer 2017-12-29 20:28:54 +01:00
parent cbc4cfeed6
commit ca3143b9ab
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
2 changed files with 117 additions and 34 deletions

View file

@ -185,7 +185,7 @@ static const struct
{ "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg }, { "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg },
{ "help", "help", "Display help screen.", KdbpCmdHelp }, { "help", "help", "Display help screen.", KdbpCmdHelp },
{ "!pool", "!pool [Address [Flags]]", "Display information about pool allocations.", ExpKdbgExtPool }, { "!pool", "!pool [Address [Flags]]", "Display information about pool allocations.", ExpKdbgExtPool },
{ "!poolused", "!poolused [Tag]", "Display pool usage.", ExpKdbgExtPoolUsed }, { "!poolused", "!poolused [Flags [Tag]]", "Display pool usage.", ExpKdbgExtPoolUsed },
}; };
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/

View file

@ -485,9 +485,10 @@ ExpTagAllowPrint(CHAR Tag)
#endif #endif
VOID VOID
MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask) MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask, ULONG Flags)
{ {
SIZE_T i; SIZE_T i;
BOOLEAN Verbose;
// //
// Only print header if called from OOM situation // Only print header if called from OOM situation
@ -504,11 +505,25 @@ MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask)
} }
#endif #endif
//
// Remember whether we'll have to be verbose
// This is the only supported flag!
//
Verbose = BooleanFlagOn(Flags, 1);
// //
// Print table header // Print table header
// //
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, "\t\tNonPaged\t\t\tPaged\n");
MiDumperPrint(CalledFromDbg, "Tag\t\tAllocs\t\tUsed\t\tAllocs\t\tUsed\n"); MiDumperPrint(CalledFromDbg, "Tag\t\tAllocs\t\tUsed\t\tAllocs\t\tUsed\n");
}
// //
// We'll extract allocations for all the tracked pools // We'll extract allocations for all the tracked pools
@ -549,10 +564,31 @@ MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask)
// //
// Print in reversed order to match what is in source code // Print in reversed order to match what is in source code
// //
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[3], Tag[2], Tag[1], Tag[0],
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[3], Tag[2], Tag[1], Tag[0], 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->NonPagedAllocs, TableEntry->NonPagedBytes,
TableEntry->PagedAllocs, TableEntry->PagedBytes); TableEntry->PagedAllocs, TableEntry->PagedBytes);
} }
}
else
{
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 else
{ {
MiDumperPrint(CalledFromDbg, "%x\t%ld\t\t%ld\t\t%ld\t\t%ld\n", TableEntry->Key, MiDumperPrint(CalledFromDbg, "%x\t%ld\t\t%ld\t\t%ld\t\t%ld\n", TableEntry->Key,
@ -560,7 +596,18 @@ MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask)
TableEntry->PagedAllocs, TableEntry->PagedBytes); TableEntry->PagedAllocs, TableEntry->PagedBytes);
} }
} }
}
else if (Tag == 0 || (Tag & Mask) == (TAG_NONE & Mask)) else if (Tag == 0 || (Tag & Mask) == (TAG_NONE & Mask))
{
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", MiDumperPrint(CalledFromDbg, "Anon\t\t%ld\t\t%ld\t\t%ld\t\t%ld\n",
TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes, TableEntry->NonPagedAllocs, TableEntry->NonPagedBytes,
@ -568,6 +615,7 @@ MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask)
} }
} }
} }
}
if (!CalledFromDbg) if (!CalledFromDbg)
{ {
@ -1761,7 +1809,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
// //
// Out of memory, display current consumption // Out of memory, display current consumption
// //
MiDumpPoolConsumers(FALSE, 0, 0); MiDumpPoolConsumers(FALSE, 0, 0, 0);
#endif #endif
// //
@ -2094,7 +2142,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
// //
// Out of memory, display current consumption // Out of memory, display current consumption
// //
MiDumpPoolConsumers(FALSE, 0, 0); MiDumpPoolConsumers(FALSE, 0, 0, 0);
#endif #endif
// //
@ -2949,6 +2997,35 @@ ExpKdbgExtPool(
return TRUE; return TRUE;
} }
static
VOID
ExpKdbgExtPoolUsedGetTag(PCHAR Arg, PULONG Tag, PULONG Mask)
{
CHAR Tmp[4];
ULONG Len;
USHORT i;
/* Get the tag */
Len = strlen(Arg);
if (Len > 4)
{
Len = 4;
}
/* Generate the mask to have wildcards support */
for (i = 0; i < Len; ++i)
{
Tmp[i] = Arg[i];
if (Tmp[i] != '?')
{
*Mask |= (0xFF << i * 8);
}
}
/* Get the tag in the ulong form */
*Tag = *((PULONG)Tmp);
}
BOOLEAN BOOLEAN
ExpKdbgExtPoolUsed( ExpKdbgExtPoolUsed(
ULONG Argc, ULONG Argc,
@ -2956,35 +3033,41 @@ ExpKdbgExtPoolUsed(
{ {
ULONG Tag = 0; ULONG Tag = 0;
ULONG Mask = 0; ULONG Mask = 0;
ULONG Flags = 0;
if (Argc > 1) if (Argc > 1)
{ {
CHAR Tmp[4]; /* If we have 2+ args, easy: flags then tag */
ULONG Len; if (Argc > 2)
USHORT i;
/* Get the tag */
Len = strlen(Argv[1]);
if (Len > 4)
{ {
Len = 4; ExpKdbgExtPoolUsedGetTag(Argv[2], &Tag, &Mask);
} if (!KdbpGetHexNumber(Argv[1], &Flags))
/* Generate the mask to have wildcards support */
for (i = 0; i < Len; ++i)
{ {
Tmp[i] = Argv[1][i]; KdbpPrint("Invalid parameter: %s\n", Argv[0]);
if (Tmp[i] != '?') }
{ }
Mask |= (0xFF << i * 8); else
{
/* Otherwise, try to find out whether that's flags */
if (strlen(Argv[1]) == 1 ||
(strlen(Argv[1]) == 3 && Argv[1][0] == '0' && Argv[1][1] == 'x'))
{
/* Fallback: if reading flags failed, assume it's a tag */
if (!KdbpGetHexNumber(Argv[1], &Flags))
{
ExpKdbgExtPoolUsedGetTag(Argv[1], &Tag, &Mask);
}
}
/* Or tag */
else
{
ExpKdbgExtPoolUsedGetTag(Argv[1], &Tag, &Mask);
} }
} }
/* Get the tag in the ulong form */
Tag = *((PULONG)Tmp);
} }
/* Call the dumper */ /* Call the dumper */
MiDumpPoolConsumers(TRUE, Tag, Mask); MiDumpPoolConsumers(TRUE, Tag, Mask, Flags);
return TRUE; return TRUE;
} }