diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 1e4796dd8dd..a3a041bcceb 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -558,6 +558,24 @@ VOID NTAPI ExFreePagedPool(IN PVOID Block); +BOOLEAN +NTAPI +ExpIsPoolTagDebuggable(ULONG Tag); + +PVOID +NTAPI +ExpAllocateDebugPool( + POOL_TYPE Type, + ULONG Size, + ULONG Tag, + PVOID Caller, + BOOLEAN EndOfPage +); + +VOID +NTAPI +ExpFreeDebugPool(PVOID Block); + VOID NTAPI MmInitializePagedPool(VOID); diff --git a/reactos/ntoskrnl/mm/dbgpool.c b/reactos/ntoskrnl/mm/dbgpool.c new file mode 100644 index 00000000000..8e11d900948 --- /dev/null +++ b/reactos/ntoskrnl/mm/dbgpool.c @@ -0,0 +1,117 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/mm/dbgpool.c + * PURPOSE: Debug version of a pool allocator + * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) + */ + +/* INCLUDES ***************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS **************************************************************/ + +typedef struct _EI_WHOLE_PAGE_HEADER { + PVOID ActualAddress; + ULONG Size; + ULONG Tag; +} EI_WHOLE_PAGE_HEADER, *PEI_WHOLE_PAGE_HEADER; + +BOOLEAN +NTAPI +ExpIsPoolTagDebuggable(ULONG Tag) +{ + if (Tag == TAG('C', 'a', 'l', 'l')) return FALSE; + if (Tag == TAG('D', 'r', 'i', 'v')) return FALSE; + if (Tag == TAG('D', 'e', 'v', 'i')) return FALSE; + if (Tag == TAG('A', 'd', 'a', 'p')) return FALSE; + + return FALSE;//TRUE; +} + + +PVOID +NTAPI +ExpAllocateDebugPool(POOL_TYPE Type, ULONG Size, ULONG Tag, PVOID Caller, BOOLEAN EndOfPage) +{ + ULONG UserSize = Size + sizeof(EI_WHOLE_PAGE_HEADER); + ULONG TotalSize = UserSize + 2*PAGE_SIZE; + ULONG_PTR UserData, GuardArea; + PEI_WHOLE_PAGE_HEADER Header; + ULONG_PTR Buffer; + + /* Right now we support only end-of-page allocations */ + ASSERT(EndOfPage); + + /* Allocate space using default routine */ + if (Type & PAGED_POOL_MASK) + { + Buffer = (ULONG_PTR) + ExAllocatePagedPoolWithTag(Type, TotalSize, Tag); + } + else + { + Buffer = (ULONG_PTR) + ExAllocateNonPagedPoolWithTag(Type, TotalSize, Tag, Caller); + } + + /* If allocation failed - fail too */ + if (!Buffer) + { + DPRINT1("A big problem! Pool allocation failed!\n"); + return NULL; + } + + /* Calculate guard area as placed on a page boundary + * at the end of allocated area */ + GuardArea = PAGE_ROUND_DOWN(Buffer + TotalSize - PAGE_SIZE + 1); + + /* Calculate user data and header pointers */ + UserData = GuardArea - Size; + Header = (PEI_WHOLE_PAGE_HEADER)(UserData - sizeof(EI_WHOLE_PAGE_HEADER)); + + /* Fill out the header */ + Header->ActualAddress = (PVOID)Buffer; + Header->Tag = Tag; + Header->Size = Size; + + /* Protect the guard page */ + MmSetPageProtect(NULL, (PVOID)GuardArea, PAGE_NOACCESS); + + DPRINT1("Allocating whole page block Tag %c%c%c%c, Buffer %p, Header %p, UserData %p, GuardArea %p, Size %d\n", + Tag & 0xFF, (Tag >> 8) & 0xFF, + (Tag >> 16) & 0xFF, (Tag >> 24) & 0xFF, + Buffer, Header, UserData, GuardArea, Size); + + return (PVOID)UserData; +} + +VOID +NTAPI +ExpFreeDebugPool(PVOID Block) +{ + PEI_WHOLE_PAGE_HEADER Header; + PVOID ProtectedPage; + + /* Get pointer to our special header */ + Header = (PEI_WHOLE_PAGE_HEADER) + (((PCHAR)Block) - sizeof(EI_WHOLE_PAGE_HEADER)); + + DPRINT1("Freeing whole page block at %08x (Tag %c%c%c%c, %x Header %x)\n", Block, + Header->Tag & 0xFF, (Header->Tag >> 8) & 0xFF, + (Header->Tag >> 16) & 0xFF, (Header->Tag >> 24) & 0xFF, Header->Tag, Header); + + /* Calculate protected page adresss */ + ProtectedPage = ((PCHAR)Block) + Header->Size; + + /* Unprotect it */ + MmSetPageProtect(NULL, ProtectedPage, PAGE_READWRITE); + + /* Free storage */ + ExFreeNonPagedPool(Header->ActualAddress); +} + +/* EOF */ diff --git a/reactos/ntoskrnl/mm/pool.c b/reactos/ntoskrnl/mm/pool.c index d3a04071293..a789ab7c813 100644 --- a/reactos/ntoskrnl/mm/pool.c +++ b/reactos/ntoskrnl/mm/pool.c @@ -14,6 +14,10 @@ #define NDEBUG #include +/* Uncomment to enable pool overruns debugging */ +//#define DEBUG_NPOOL +//#define DEBUG_PPOOL + extern PVOID MiNonPagedPoolStart; extern ULONG MiNonPagedPoolLength; extern ULONG MmTotalPagedPoolQuota; @@ -60,7 +64,12 @@ EiAllocatePool(POOL_TYPE PoolType, { if (KeGetCurrentIrql() > DISPATCH_LEVEL) KeBugCheckEx(BAD_POOL_CALLER, 0x08, KeGetCurrentIrql(), PoolType, Tag); - Block = ExAllocateNonPagedPoolWithTag(PoolType, NumberOfBytes, Tag, Caller); +#ifdef DEBUG_NPOOL + if (ExpIsPoolTagDebuggable(Tag)) + Block = ExpAllocateDebugPool(PoolType, NumberOfBytes, Tag, Caller, TRUE); + else +#endif + Block = ExAllocateNonPagedPoolWithTag(PoolType, NumberOfBytes, Tag, Caller); } if ((PoolType & MUST_SUCCEED_POOL_MASK) && !Block) @@ -292,7 +301,12 @@ ExFreePoolWithTag( (ULONG_PTR)Block); /* Free from non-paged pool */ - ExFreeNonPagedPool(Block); +#ifdef DEBUG_NPOOL + if (ExpIsPoolTagDebuggable(Tag)) + ExpFreeDebugPool(Block); + else +#endif + ExFreeNonPagedPool(Block); } else { diff --git a/reactos/ntoskrnl/ntoskrnl-generic.rbuild b/reactos/ntoskrnl/ntoskrnl-generic.rbuild index 18cefa3a4cf..ca0f7187f38 100644 --- a/reactos/ntoskrnl/ntoskrnl-generic.rbuild +++ b/reactos/ntoskrnl/ntoskrnl-generic.rbuild @@ -362,6 +362,7 @@ anonmem.c balance.c cont.c + dbgpool.c drvlck.c freelist.c hypermap.c