https://git.reactos.org/?p=reactos.git;a=commitdiff;h=36f90e7e4647d284fc2ea…
commit 36f90e7e4647d284fc2ea8c8f0810f2e71bbcefd
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sun Jan 6 22:49:23 2019 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sun Jan 6 22:50:57 2019 +0100
[NTOSKRNL] Move KDBG MM functions implementation to their own file
---
ntoskrnl/mm/ARM3/expool.c | 540 -------------------------------------------
ntoskrnl/mm/ARM3/kdbg.c | 573 ++++++++++++++++++++++++++++++++++++++++++++++
ntoskrnl/ntos.cmake | 1 +
3 files changed, 574 insertions(+), 540 deletions(-)
diff --git a/ntoskrnl/mm/ARM3/expool.c b/ntoskrnl/mm/ARM3/expool.c
index e69be03cbf..6a791e583f 100644
--- a/ntoskrnl/mm/ARM3/expool.c
+++ b/ntoskrnl/mm/ARM3/expool.c
@@ -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 */
diff --git a/ntoskrnl/mm/ARM3/kdbg.c b/ntoskrnl/mm/ARM3/kdbg.c
new file mode 100644
index 0000000000..6079e50529
--- /dev/null
+++ b/ntoskrnl/mm/ARM3/kdbg.c
@@ -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 */
diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake
index 147691bd4c..38dc52aa78 100644
--- a/ntoskrnl/ntos.cmake
+++ b/ntoskrnl/ntos.cmake
@@ -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