https://git.reactos.org/?p=reactos.git;a=commitdiff;h=47b48520b511842e9e9b7…
commit 47b48520b511842e9e9b74f9e59277ae4710c92f
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sun Jan 6 12:49:57 2019 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sun Jan 6 12:49:57 2019 +0100
[NTOSKRNL] Reimplement !irpfind using !poolfind helpers
This allows avoiding one of the previous implementation limits:
leaked IRP not queued to a thread are now totally visible since
we look directly in the memory pool.
---
ntoskrnl/kdbg/kdb_cli.c | 5 +-
ntoskrnl/mm/ARM3/expool.c | 184 ++++++++++++++++++++++++++++++++++++++++++----
ntoskrnl/ps/process.c | 114 ----------------------------
3 files changed, 172 insertions(+), 131 deletions(-)
diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c
index ef97693414..6b7ee2752b 100644
--- a/ntoskrnl/kdbg/kdb_cli.c
+++ b/ntoskrnl/kdbg/kdb_cli.c
@@ -96,8 +96,7 @@ BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
-
-BOOLEAN PspKdbgIrpFind(ULONG Argc, PCHAR Argv[]);
+BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
#ifdef __ROS_DWARF__
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
@@ -194,7 +193,7 @@ static const struct
{ "!poolfind", "!poolfind Tag [Pool]", "Search for pool tag
allocations.", ExpKdbgExtPoolFind },
{ "!filecache", "!filecache", "Display cache usage.",
ExpKdbgExtFileCache },
{ "!defwrites", "!defwrites", "Display cache write
values.", ExpKdbgExtDefWrites },
- { "!irpfind", "!irpfind [criteria data]", "Lists IRPs
potentially matching criteria", PspKdbgIrpFind },
+ { "!irpfind", "!irpfind [Pool [Restart Address [criteria
data]]]", "Lists IRPs potentially matching criteria", ExpKdbgExtIrpFind },
};
/* FUNCTIONS *****************************************************************/
diff --git a/ntoskrnl/mm/ARM3/expool.c b/ntoskrnl/mm/ARM3/expool.c
index b321b52044..e03645387a 100644
--- a/ntoskrnl/mm/ARM3/expool.c
+++ b/ntoskrnl/mm/ARM3/expool.c
@@ -3156,7 +3156,9 @@ static
VOID
ExpKdbgExtPoolFindPagedPool(
ULONG Tag,
- ULONG Mask)
+ ULONG Mask,
+ VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
+ PVOID CallbackContext)
{
ULONG i = 0;
PPOOL_HEADER Entry;
@@ -3210,11 +3212,18 @@ ExpKdbgExtPoolFindPagedPool(
if ((Entry->PoolTag & Mask) == (Tag & Mask))
{
- /* 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);
+ 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);
+ }
}
}
}
@@ -3228,7 +3237,9 @@ static
VOID
ExpKdbgExtPoolFindNonPagedPool(
ULONG Tag,
- ULONG Mask)
+ ULONG Mask,
+ VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
+ PVOID CallbackContext)
{
PPOOL_HEADER Entry;
PVOID BaseVa;
@@ -3270,11 +3281,18 @@ ExpKdbgExtPoolFindNonPagedPool(
if ((Entry->PoolTag & Mask) == (Tag & Mask))
{
- /* 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);
+ 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);
+ }
}
}
}
@@ -3318,11 +3336,149 @@ ExpKdbgExtPoolFind(
if (PoolType == NonPagedPool)
{
- ExpKdbgExtPoolFindNonPagedPool(Tag, Mask);
+ 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, Mask);
+ ExpKdbgExtPoolFindPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint,
&FindCtxt);
}
return TRUE;
diff --git a/ntoskrnl/ps/process.c b/ntoskrnl/ps/process.c
index 3554d601c1..179fd1d8fa 100644
--- a/ntoskrnl/ps/process.c
+++ b/ntoskrnl/ps/process.c
@@ -1615,118 +1615,4 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
return Status;
}
-#if DBG && defined(KDBG)
-BOOLEAN
-PspKdbgIrpFind(
- ULONG Argc,
- PCHAR Argv[])
-{
- PLIST_ENTRY PsEntry, TdEntry, IrpEntry;
- PEPROCESS Process = NULL;
- PETHREAD Thread = NULL;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION IoStack = NULL;
- PUNICODE_STRING DriverName;
- ULONG_PTR SData = 0;
- ULONG Criteria = 0;
-
- /*
- * FIXME: To improve, badly
- * This should just be a wrapper over !poolfind
- * As a hack, here we just browse all the queued IRPs
- * and return them
- * If that's not *that* wrong, it makes sure that leaked
- * IRPs are invisible!
- * We also don't care about pool type, nor address start
- */
-
- /* Gets the criteria and its data */
- if (Argc > 2)
- {
- if (!KdbpGetHexNumber(Argv[2], &SData))
- {
- SData = 0;
- }
- else
- {
- if (strcmp(Argv[1], "device") == 0)
- {
- Criteria = 0x1;
- }
- else if (strcmp(Argv[1], "fileobject") == 0)
- {
- Criteria = 0x2;
- }
- else if (strcmp(Argv[1], "mdlprocess") == 0)
- {
- Criteria = 0x4;
- }
- else if (strcmp(Argv[1], "thread") == 0)
- {
- Criteria = 0x8;
- }
- else if (strcmp(Argv[1], "userevent") == 0)
- {
- Criteria = 0x10;
- }
- else if (strcmp(Argv[1], "arg") == 0)
- {
- Criteria = 0x1f;
- }
- }
- }
-
- PsEntry = PsActiveProcessHead.Flink;
- /* Loop the process list */
- while (PsEntry != &PsActiveProcessHead)
- {
- /* Get the process */
- Process = CONTAINING_RECORD(PsEntry, EPROCESS, ActiveProcessLinks);
-
- /* Loop the thread list */
- TdEntry = Process->ThreadListHead.Flink;
- while (TdEntry != &Process->ThreadListHead)
- {
- /* Get the thread */
- Thread = CONTAINING_RECORD(TdEntry, ETHREAD, ThreadListEntry);
-
- /* Loop the IRP list */
- IrpEntry = Thread->IrpList.Flink;
- while (IrpEntry != &Thread->IrpList)
- {
- /* Get the IRP and its current stack */
- Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
- 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 && 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, Thread, DriverName);
- }
-
- IrpEntry = IrpEntry->Flink;
- }
-
- TdEntry = TdEntry->Flink;
- }
-
- PsEntry = PsEntry->Flink;
- }
-
- return TRUE;
-}
-
-#endif // DBG && KDBG
-
/* EOF */