From 36f90e7e4647d284fc2ea8c8f0810f2e71bbcefd Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sun, 6 Jan 2019 22:49:23 +0100 Subject: [PATCH] [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(-) create mode 100644 ntoskrnl/mm/ARM3/kdbg.c diff --git a/ntoskrnl/mm/ARM3/expool.c b/ntoskrnl/mm/ARM3/expool.c index e69be03cbf1..6a791e583f9 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 00000000000..6079e505296 --- /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 +#define NDEBUG +#include + +#define MODULE_INVOLVED_IN_ARM3 +#include + +/* 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 147691bd4c5..38dc52aa787 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 -- 2.17.1