mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[NTOSKRNL] Move KDBG MM functions implementation to their own file
This commit is contained in:
parent
0bfa6722ba
commit
36f90e7e46
3 changed files with 574 additions and 540 deletions
|
@ -2934,544 +2934,4 @@ ExAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType,
|
|||
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;
|
||||
}
|
||||
|
||||
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
|
||||
ExpKdbgExtPoolUsed(
|
||||
ULONG Argc,
|
||||
PCHAR Argv[])
|
||||
{
|
||||
ULONG Tag = 0;
|
||||
ULONG Mask = 0;
|
||||
ULONG Flags = 0;
|
||||
|
||||
if (Argc > 1)
|
||||
{
|
||||
/* If we have 2+ args, easy: flags then tag */
|
||||
if (Argc > 2)
|
||||
{
|
||||
ExpKdbgExtPoolUsedGetTag(Argv[2], &Tag, &Mask);
|
||||
if (!KdbpGetHexNumber(Argv[1], &Flags))
|
||||
{
|
||||
KdbpPrint("Invalid parameter: %s\n", Argv[0]);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the dumper */
|
||||
MiDumpPoolConsumers(TRUE, Tag, Mask, Flags);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
ExpKdbgExtValidatePoolHeader(
|
||||
PVOID BaseVa,
|
||||
PPOOL_HEADER Entry,
|
||||
POOL_TYPE BasePoolTye)
|
||||
{
|
||||
/* Block size cannot be NULL or negative and it must cover the page */
|
||||
if (Entry->BlockSize <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (Entry->BlockSize * 8 + (ULONG_PTR)Entry - (ULONG_PTR)BaseVa > PAGE_SIZE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* PreviousSize cannot be 0 unless on page begin
|
||||
* And it cannot be bigger that our current
|
||||
* position in page
|
||||
*/
|
||||
if (Entry->PreviousSize == 0 && BaseVa != Entry)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (Entry->PreviousSize * 8 > (ULONG_PTR)Entry - (ULONG_PTR)BaseVa)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Must be paged pool */
|
||||
if (((Entry->PoolType - 1) & BASE_POOL_TYPE_MASK) != BasePoolTye)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Match tag mask */
|
||||
if ((Entry->PoolTag & 0x00808080) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
ExpKdbgExtPoolFindPagedPool(
|
||||
ULONG Tag,
|
||||
ULONG Mask,
|
||||
VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
|
||||
PVOID CallbackContext)
|
||||
{
|
||||
ULONG i = 0;
|
||||
PPOOL_HEADER Entry;
|
||||
PVOID BaseVa;
|
||||
PMMPDE PointerPde;
|
||||
|
||||
KdbpPrint("Searching Paged pool (%p : %p) for Tag: %.4s\n", MmPagedPoolStart, MmPagedPoolEnd, (PCHAR)&Tag);
|
||||
|
||||
/*
|
||||
* To speed up paged pool search, we will use the allocation bipmap.
|
||||
* This is possible because we live directly in the kernel :-)
|
||||
*/
|
||||
i = RtlFindSetBits(MmPagedPoolInfo.PagedPoolAllocationMap, 1, 0);
|
||||
while (i != 0xFFFFFFFF)
|
||||
{
|
||||
BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
|
||||
Entry = BaseVa;
|
||||
|
||||
/* Validate our address */
|
||||
if ((ULONG_PTR)BaseVa > (ULONG_PTR)MmPagedPoolEnd || (ULONG_PTR)BaseVa + PAGE_SIZE > (ULONG_PTR)MmPagedPoolEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check whether we are beyond expansion */
|
||||
PointerPde = MiAddressToPde(BaseVa);
|
||||
if (PointerPde >= MmPagedPoolInfo.NextPdeForPagedPoolExpansion)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if allocation is valid */
|
||||
if (MmIsAddressValid(BaseVa))
|
||||
{
|
||||
for (Entry = BaseVa;
|
||||
(ULONG_PTR)Entry + sizeof(POOL_HEADER) < (ULONG_PTR)BaseVa + PAGE_SIZE;
|
||||
Entry = (PVOID)((ULONG_PTR)Entry + 8))
|
||||
{
|
||||
/* Try to find whether we have a pool entry */
|
||||
if (!ExpKdbgExtValidatePoolHeader(BaseVa, Entry, PagedPool))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->PoolTag & Mask) == (Tag & Mask))
|
||||
{
|
||||
if (FoundCallback != NULL)
|
||||
{
|
||||
FoundCallback(Entry, CallbackContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Print the line */
|
||||
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
|
||||
Entry, Entry->BlockSize, Entry->PreviousSize,
|
||||
Entry->PoolType ? "(Allocated)" : "(Free) ",
|
||||
(PCHAR)&Entry->PoolTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = RtlFindSetBits(MmPagedPoolInfo.PagedPoolAllocationMap, 1, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
extern PVOID MmNonPagedPoolEnd0;
|
||||
static
|
||||
VOID
|
||||
ExpKdbgExtPoolFindNonPagedPool(
|
||||
ULONG Tag,
|
||||
ULONG Mask,
|
||||
VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
|
||||
PVOID CallbackContext)
|
||||
{
|
||||
PPOOL_HEADER Entry;
|
||||
PVOID BaseVa;
|
||||
|
||||
KdbpPrint("Searching NonPaged pool (%p : %p) for Tag: %.4s\n", MmNonPagedPoolStart, MmNonPagedPoolEnd0, (PCHAR)&Tag);
|
||||
|
||||
/* Brute force search: start browsing the whole non paged pool */
|
||||
for (BaseVa = MmNonPagedPoolStart;
|
||||
(ULONG_PTR)BaseVa + PAGE_SIZE <= (ULONG_PTR)MmNonPagedPoolEnd0;
|
||||
BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE))
|
||||
{
|
||||
Entry = BaseVa;
|
||||
|
||||
/* Check whether we are beyond expansion */
|
||||
if (BaseVa >= MmNonPagedPoolExpansionStart)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if allocation is valid */
|
||||
if (!MmIsAddressValid(BaseVa))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Entry = BaseVa;
|
||||
(ULONG_PTR)Entry + sizeof(POOL_HEADER) < (ULONG_PTR)BaseVa + PAGE_SIZE;
|
||||
Entry = (PVOID)((ULONG_PTR)Entry + 8))
|
||||
{
|
||||
/* Try to find whether we have a pool entry */
|
||||
if (!ExpKdbgExtValidatePoolHeader(BaseVa, Entry, NonPagedPool))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->PoolTag & Mask) == (Tag & Mask))
|
||||
{
|
||||
if (FoundCallback != NULL)
|
||||
{
|
||||
FoundCallback(Entry, CallbackContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Print the line */
|
||||
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
|
||||
Entry, Entry->BlockSize, Entry->PreviousSize,
|
||||
Entry->PoolType ? "(Allocated)" : "(Free) ",
|
||||
(PCHAR)&Entry->PoolTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ExpKdbgExtPoolFind(
|
||||
ULONG Argc,
|
||||
PCHAR Argv[])
|
||||
{
|
||||
ULONG Tag = 0;
|
||||
ULONG Mask = 0;
|
||||
ULONG PoolType = NonPagedPool;
|
||||
|
||||
if (Argc == 1)
|
||||
{
|
||||
KdbpPrint("Specify a tag string\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* First arg is tag */
|
||||
if (strlen(Argv[1]) != 1 || Argv[1][0] != '*')
|
||||
{
|
||||
ExpKdbgExtPoolUsedGetTag(Argv[1], &Tag, &Mask);
|
||||
}
|
||||
|
||||
/* Second arg might be pool to search */
|
||||
if (Argc > 2)
|
||||
{
|
||||
PoolType = strtoul(Argv[2], NULL, 0);
|
||||
|
||||
if (PoolType > 1)
|
||||
{
|
||||
KdbpPrint("Only (non) paged pool are supported\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: What about large pool? */
|
||||
|
||||
if (PoolType == NonPagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindNonPagedPool(Tag, Mask, NULL, NULL);
|
||||
}
|
||||
else if (PoolType == PagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindPagedPool(Tag, Mask, NULL, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct _IRP_FIND_CTXT
|
||||
{
|
||||
ULONG_PTR RestartAddress;
|
||||
ULONG_PTR SData;
|
||||
ULONG Criteria;
|
||||
} IRP_FIND_CTXT, *PIRP_FIND_CTXT;
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExpKdbgExtIrpFindPrint(
|
||||
PPOOL_HEADER Entry,
|
||||
PVOID Context)
|
||||
{
|
||||
PIRP Irp;
|
||||
PIRP_FIND_CTXT FindCtxt = Context;
|
||||
PIO_STACK_LOCATION IoStack = NULL;
|
||||
PUNICODE_STRING DriverName;
|
||||
ULONG_PTR SData = FindCtxt->SData;
|
||||
ULONG Criteria = FindCtxt->Criteria;
|
||||
|
||||
/* Free entry, ignore */
|
||||
if (Entry->PoolType == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the IRP */
|
||||
Irp = (PIRP)POOL_FREE_BLOCK(Entry);
|
||||
|
||||
/* Bail out if not matching restart address */
|
||||
if ((ULONG_PTR)Irp < FindCtxt->RestartAddress)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Avoid bogus IRP stack locations */
|
||||
if (Irp->CurrentLocation <= Irp->StackCount + 1)
|
||||
{
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* Get associated driver */
|
||||
if (IoStack->DeviceObject && IoStack->DeviceObject->DriverObject)
|
||||
DriverName = &IoStack->DeviceObject->DriverObject->DriverName;
|
||||
else
|
||||
DriverName = NULL;
|
||||
}
|
||||
|
||||
/* Display if: no data, no criteria or if criteria matches data */
|
||||
if (SData == 0 || Criteria == 0 ||
|
||||
(Criteria & 0x1 && IoStack && SData == (ULONG_PTR)IoStack->DeviceObject) ||
|
||||
(Criteria & 0x2 && SData == (ULONG_PTR)Irp->Tail.Overlay.OriginalFileObject) ||
|
||||
(Criteria & 0x4 && Irp->MdlAddress && SData == (ULONG_PTR)Irp->MdlAddress->Process) ||
|
||||
(Criteria & 0x8 && SData == (ULONG_PTR)Irp->Tail.Overlay.Thread) ||
|
||||
(Criteria & 0x10 && SData == (ULONG_PTR)Irp->UserEvent))
|
||||
{
|
||||
KdbpPrint("%p Thread %p current stack belongs to %wZ\n", Irp, Irp->Tail.Overlay.Thread, DriverName);
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ExpKdbgExtIrpFind(
|
||||
ULONG Argc,
|
||||
PCHAR Argv[])
|
||||
{
|
||||
ULONG PoolType = NonPagedPool;
|
||||
IRP_FIND_CTXT FindCtxt;
|
||||
|
||||
/* Pool type */
|
||||
if (Argc > 1)
|
||||
{
|
||||
PoolType = strtoul(Argv[1], NULL, 0);
|
||||
|
||||
if (PoolType > 1)
|
||||
{
|
||||
KdbpPrint("Only (non) paged pool are supported\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
RtlZeroMemory(&FindCtxt, sizeof(IRP_FIND_CTXT));
|
||||
|
||||
/* Restart address */
|
||||
if (Argc > 2)
|
||||
{
|
||||
if (!KdbpGetHexNumber(Argv[2], &FindCtxt.RestartAddress))
|
||||
{
|
||||
KdbpPrint("Invalid parameter: %s\n", Argv[0]);
|
||||
FindCtxt.RestartAddress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (Argc > 4)
|
||||
{
|
||||
if (!KdbpGetHexNumber(Argv[4], &FindCtxt.SData))
|
||||
{
|
||||
FindCtxt.SData = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(Argv[3], "device") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x1;
|
||||
}
|
||||
else if (strcmp(Argv[3], "fileobject") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x2;
|
||||
}
|
||||
else if (strcmp(Argv[3], "mdlprocess") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x4;
|
||||
}
|
||||
else if (strcmp(Argv[3], "thread") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x8;
|
||||
}
|
||||
else if (strcmp(Argv[3], "userevent") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x10;
|
||||
}
|
||||
else if (strcmp(Argv[3], "arg") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PoolType == NonPagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindNonPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint, &FindCtxt);
|
||||
}
|
||||
else if (PoolType == PagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint, &FindCtxt);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // DBG && KDBG
|
||||
|
||||
/* EOF */
|
||||
|
|
573
ntoskrnl/mm/ARM3/kdbg.c
Normal file
573
ntoskrnl/mm/ARM3/kdbg.c
Normal file
|
@ -0,0 +1,573 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: ntoskrnl/mm/ARM3/kdbg.c
|
||||
* PURPOSE: ARM Memory Manager Kernel Debugger routines
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* Pierre Schweitzer
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define MODULE_INVOLVED_IN_ARM3
|
||||
#include <mm/ARM3/miarm.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
typedef struct _IRP_FIND_CTXT
|
||||
{
|
||||
ULONG_PTR RestartAddress;
|
||||
ULONG_PTR SData;
|
||||
ULONG Criteria;
|
||||
} IRP_FIND_CTXT, *PIRP_FIND_CTXT;
|
||||
|
||||
extern PVOID MmNonPagedPoolEnd0;
|
||||
|
||||
/* Pool block/header/list access macros */
|
||||
#define POOL_ENTRY(x) (PPOOL_HEADER)((ULONG_PTR)(x) - sizeof(POOL_HEADER))
|
||||
#define POOL_FREE_BLOCK(x) (PLIST_ENTRY)((ULONG_PTR)(x) + sizeof(POOL_HEADER))
|
||||
#define POOL_BLOCK(x, i) (PPOOL_HEADER)((ULONG_PTR)(x) + ((i) * POOL_BLOCK_SIZE))
|
||||
#define POOL_NEXT_BLOCK(x) POOL_BLOCK((x), (x)->BlockSize)
|
||||
#define POOL_PREV_BLOCK(x) POOL_BLOCK((x), -((x)->PreviousSize))
|
||||
|
||||
VOID MiDumpPoolConsumers(BOOLEAN CalledFromDbg, ULONG Tag, ULONG Mask, ULONG Flags);
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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
|
||||
ExpKdbgExtPoolUsed(
|
||||
ULONG Argc,
|
||||
PCHAR Argv[])
|
||||
{
|
||||
ULONG Tag = 0;
|
||||
ULONG Mask = 0;
|
||||
ULONG Flags = 0;
|
||||
|
||||
if (Argc > 1)
|
||||
{
|
||||
/* If we have 2+ args, easy: flags then tag */
|
||||
if (Argc > 2)
|
||||
{
|
||||
ExpKdbgExtPoolUsedGetTag(Argv[2], &Tag, &Mask);
|
||||
if (!KdbpGetHexNumber(Argv[1], &Flags))
|
||||
{
|
||||
KdbpPrint("Invalid parameter: %s\n", Argv[0]);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the dumper */
|
||||
MiDumpPoolConsumers(TRUE, Tag, Mask, Flags);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
ExpKdbgExtValidatePoolHeader(
|
||||
PVOID BaseVa,
|
||||
PPOOL_HEADER Entry,
|
||||
POOL_TYPE BasePoolTye)
|
||||
{
|
||||
/* Block size cannot be NULL or negative and it must cover the page */
|
||||
if (Entry->BlockSize <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (Entry->BlockSize * 8 + (ULONG_PTR)Entry - (ULONG_PTR)BaseVa > PAGE_SIZE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* PreviousSize cannot be 0 unless on page begin
|
||||
* And it cannot be bigger that our current
|
||||
* position in page
|
||||
*/
|
||||
if (Entry->PreviousSize == 0 && BaseVa != Entry)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (Entry->PreviousSize * 8 > (ULONG_PTR)Entry - (ULONG_PTR)BaseVa)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Must be paged pool */
|
||||
if (((Entry->PoolType - 1) & BASE_POOL_TYPE_MASK) != BasePoolTye)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Match tag mask */
|
||||
if ((Entry->PoolTag & 0x00808080) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
ExpKdbgExtPoolFindPagedPool(
|
||||
ULONG Tag,
|
||||
ULONG Mask,
|
||||
VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
|
||||
PVOID CallbackContext)
|
||||
{
|
||||
ULONG i = 0;
|
||||
PPOOL_HEADER Entry;
|
||||
PVOID BaseVa;
|
||||
PMMPDE PointerPde;
|
||||
|
||||
KdbpPrint("Searching Paged pool (%p : %p) for Tag: %.4s\n", MmPagedPoolStart, MmPagedPoolEnd, (PCHAR)&Tag);
|
||||
|
||||
/*
|
||||
* To speed up paged pool search, we will use the allocation bipmap.
|
||||
* This is possible because we live directly in the kernel :-)
|
||||
*/
|
||||
i = RtlFindSetBits(MmPagedPoolInfo.PagedPoolAllocationMap, 1, 0);
|
||||
while (i != 0xFFFFFFFF)
|
||||
{
|
||||
BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
|
||||
Entry = BaseVa;
|
||||
|
||||
/* Validate our address */
|
||||
if ((ULONG_PTR)BaseVa > (ULONG_PTR)MmPagedPoolEnd || (ULONG_PTR)BaseVa + PAGE_SIZE > (ULONG_PTR)MmPagedPoolEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check whether we are beyond expansion */
|
||||
PointerPde = MiAddressToPde(BaseVa);
|
||||
if (PointerPde >= MmPagedPoolInfo.NextPdeForPagedPoolExpansion)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if allocation is valid */
|
||||
if (MmIsAddressValid(BaseVa))
|
||||
{
|
||||
for (Entry = BaseVa;
|
||||
(ULONG_PTR)Entry + sizeof(POOL_HEADER) < (ULONG_PTR)BaseVa + PAGE_SIZE;
|
||||
Entry = (PVOID)((ULONG_PTR)Entry + 8))
|
||||
{
|
||||
/* Try to find whether we have a pool entry */
|
||||
if (!ExpKdbgExtValidatePoolHeader(BaseVa, Entry, PagedPool))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->PoolTag & Mask) == (Tag & Mask))
|
||||
{
|
||||
if (FoundCallback != NULL)
|
||||
{
|
||||
FoundCallback(Entry, CallbackContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Print the line */
|
||||
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
|
||||
Entry, Entry->BlockSize, Entry->PreviousSize,
|
||||
Entry->PoolType ? "(Allocated)" : "(Free) ",
|
||||
(PCHAR)&Entry->PoolTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = RtlFindSetBits(MmPagedPoolInfo.PagedPoolAllocationMap, 1, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
ExpKdbgExtPoolFindNonPagedPool(
|
||||
ULONG Tag,
|
||||
ULONG Mask,
|
||||
VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
|
||||
PVOID CallbackContext)
|
||||
{
|
||||
PPOOL_HEADER Entry;
|
||||
PVOID BaseVa;
|
||||
|
||||
KdbpPrint("Searching NonPaged pool (%p : %p) for Tag: %.4s\n", MmNonPagedPoolStart, MmNonPagedPoolEnd0, (PCHAR)&Tag);
|
||||
|
||||
/* Brute force search: start browsing the whole non paged pool */
|
||||
for (BaseVa = MmNonPagedPoolStart;
|
||||
(ULONG_PTR)BaseVa + PAGE_SIZE <= (ULONG_PTR)MmNonPagedPoolEnd0;
|
||||
BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE))
|
||||
{
|
||||
Entry = BaseVa;
|
||||
|
||||
/* Check whether we are beyond expansion */
|
||||
if (BaseVa >= MmNonPagedPoolExpansionStart)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if allocation is valid */
|
||||
if (!MmIsAddressValid(BaseVa))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Entry = BaseVa;
|
||||
(ULONG_PTR)Entry + sizeof(POOL_HEADER) < (ULONG_PTR)BaseVa + PAGE_SIZE;
|
||||
Entry = (PVOID)((ULONG_PTR)Entry + 8))
|
||||
{
|
||||
/* Try to find whether we have a pool entry */
|
||||
if (!ExpKdbgExtValidatePoolHeader(BaseVa, Entry, NonPagedPool))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((Entry->PoolTag & Mask) == (Tag & Mask))
|
||||
{
|
||||
if (FoundCallback != NULL)
|
||||
{
|
||||
FoundCallback(Entry, CallbackContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Print the line */
|
||||
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
|
||||
Entry, Entry->BlockSize, Entry->PreviousSize,
|
||||
Entry->PoolType ? "(Allocated)" : "(Free) ",
|
||||
(PCHAR)&Entry->PoolTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ExpKdbgExtPoolFind(
|
||||
ULONG Argc,
|
||||
PCHAR Argv[])
|
||||
{
|
||||
ULONG Tag = 0;
|
||||
ULONG Mask = 0;
|
||||
ULONG PoolType = NonPagedPool;
|
||||
|
||||
if (Argc == 1)
|
||||
{
|
||||
KdbpPrint("Specify a tag string\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* First arg is tag */
|
||||
if (strlen(Argv[1]) != 1 || Argv[1][0] != '*')
|
||||
{
|
||||
ExpKdbgExtPoolUsedGetTag(Argv[1], &Tag, &Mask);
|
||||
}
|
||||
|
||||
/* Second arg might be pool to search */
|
||||
if (Argc > 2)
|
||||
{
|
||||
PoolType = strtoul(Argv[2], NULL, 0);
|
||||
|
||||
if (PoolType > 1)
|
||||
{
|
||||
KdbpPrint("Only (non) paged pool are supported\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: What about large pool? */
|
||||
|
||||
if (PoolType == NonPagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindNonPagedPool(Tag, Mask, NULL, NULL);
|
||||
}
|
||||
else if (PoolType == PagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindPagedPool(Tag, Mask, NULL, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExpKdbgExtIrpFindPrint(
|
||||
PPOOL_HEADER Entry,
|
||||
PVOID Context)
|
||||
{
|
||||
PIRP Irp;
|
||||
PIRP_FIND_CTXT FindCtxt = Context;
|
||||
PIO_STACK_LOCATION IoStack = NULL;
|
||||
PUNICODE_STRING DriverName;
|
||||
ULONG_PTR SData = FindCtxt->SData;
|
||||
ULONG Criteria = FindCtxt->Criteria;
|
||||
|
||||
/* Free entry, ignore */
|
||||
if (Entry->PoolType == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the IRP */
|
||||
Irp = (PIRP)POOL_FREE_BLOCK(Entry);
|
||||
|
||||
/* Bail out if not matching restart address */
|
||||
if ((ULONG_PTR)Irp < FindCtxt->RestartAddress)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Avoid bogus IRP stack locations */
|
||||
if (Irp->CurrentLocation <= Irp->StackCount + 1)
|
||||
{
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* Get associated driver */
|
||||
if (IoStack->DeviceObject && IoStack->DeviceObject->DriverObject)
|
||||
DriverName = &IoStack->DeviceObject->DriverObject->DriverName;
|
||||
else
|
||||
DriverName = NULL;
|
||||
}
|
||||
|
||||
/* Display if: no data, no criteria or if criteria matches data */
|
||||
if (SData == 0 || Criteria == 0 ||
|
||||
(Criteria & 0x1 && IoStack && SData == (ULONG_PTR)IoStack->DeviceObject) ||
|
||||
(Criteria & 0x2 && SData == (ULONG_PTR)Irp->Tail.Overlay.OriginalFileObject) ||
|
||||
(Criteria & 0x4 && Irp->MdlAddress && SData == (ULONG_PTR)Irp->MdlAddress->Process) ||
|
||||
(Criteria & 0x8 && SData == (ULONG_PTR)Irp->Tail.Overlay.Thread) ||
|
||||
(Criteria & 0x10 && SData == (ULONG_PTR)Irp->UserEvent))
|
||||
{
|
||||
KdbpPrint("%p Thread %p current stack belongs to %wZ\n", Irp, Irp->Tail.Overlay.Thread, DriverName);
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ExpKdbgExtIrpFind(
|
||||
ULONG Argc,
|
||||
PCHAR Argv[])
|
||||
{
|
||||
ULONG PoolType = NonPagedPool;
|
||||
IRP_FIND_CTXT FindCtxt;
|
||||
|
||||
/* Pool type */
|
||||
if (Argc > 1)
|
||||
{
|
||||
PoolType = strtoul(Argv[1], NULL, 0);
|
||||
|
||||
if (PoolType > 1)
|
||||
{
|
||||
KdbpPrint("Only (non) paged pool are supported\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
RtlZeroMemory(&FindCtxt, sizeof(IRP_FIND_CTXT));
|
||||
|
||||
/* Restart address */
|
||||
if (Argc > 2)
|
||||
{
|
||||
if (!KdbpGetHexNumber(Argv[2], &FindCtxt.RestartAddress))
|
||||
{
|
||||
KdbpPrint("Invalid parameter: %s\n", Argv[0]);
|
||||
FindCtxt.RestartAddress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (Argc > 4)
|
||||
{
|
||||
if (!KdbpGetHexNumber(Argv[4], &FindCtxt.SData))
|
||||
{
|
||||
FindCtxt.SData = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(Argv[3], "device") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x1;
|
||||
}
|
||||
else if (strcmp(Argv[3], "fileobject") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x2;
|
||||
}
|
||||
else if (strcmp(Argv[3], "mdlprocess") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x4;
|
||||
}
|
||||
else if (strcmp(Argv[3], "thread") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x8;
|
||||
}
|
||||
else if (strcmp(Argv[3], "userevent") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x10;
|
||||
}
|
||||
else if (strcmp(Argv[3], "arg") == 0)
|
||||
{
|
||||
FindCtxt.Criteria = 0x1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PoolType == NonPagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindNonPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint, &FindCtxt);
|
||||
}
|
||||
else if (PoolType == PagedPool)
|
||||
{
|
||||
ExpKdbgExtPoolFindPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint, &FindCtxt);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // DBG && KDBG
|
||||
|
||||
/* EOF */
|
|
@ -199,6 +199,7 @@ list(APPEND SOURCE
|
|||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/expool.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/hypermap.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/iosup.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/kdbg.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/largepag.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/mdlsup.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/mmdbg.c
|
||||
|
|
Loading…
Reference in a new issue