mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
PagedPool improvements: differenciate between hiredzone and loredzone, added double-free detection including stack trace of free'er, keep track of Tags, two new utility functions for debugging ( VOID ExRosDumpPagedPoolByTag(ULONG) and ULONG ExRosQueryPoolTag(PVOID) ).
svn path=/trunk/; revision=12006
This commit is contained in:
parent
0bcccac59e
commit
2c781cf79e
5 changed files with 246 additions and 66 deletions
|
@ -678,6 +678,16 @@ ExReleaseRundownProtectionEx (
|
||||||
IN PEX_RUNDOWN_REF RunRef,
|
IN PEX_RUNDOWN_REF RunRef,
|
||||||
IN ULONG Count
|
IN ULONG Count
|
||||||
);
|
);
|
||||||
|
/* ReactOS Specific: begin */
|
||||||
|
VOID STDCALL
|
||||||
|
ExRosDumpPagedPoolByTag (
|
||||||
|
IN ULONG Tag
|
||||||
|
);
|
||||||
|
ULONG STDCALL
|
||||||
|
ExRosQueryPoolTag (
|
||||||
|
IN PVOID Block
|
||||||
|
);
|
||||||
|
/* ReactOS Specific: end */
|
||||||
VOID
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
ExRundownCompleted (
|
ExRundownCompleted (
|
||||||
|
|
|
@ -937,7 +937,30 @@ int HEAP_IsInsideHeap(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DumpStackFrames ( PULONG Frame, ULONG FrameCount )
|
||||||
|
{
|
||||||
|
ULONG i=0;
|
||||||
|
|
||||||
|
DbgPrint("Frames: ");
|
||||||
|
if ( !Frame )
|
||||||
|
{
|
||||||
|
#if defined __GNUC__
|
||||||
|
__asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
__asm mov [Frame], ebp
|
||||||
|
#endif
|
||||||
|
Frame = (PULONG)Frame[0]; // step out of DumpStackFrames
|
||||||
|
}
|
||||||
|
while ( Frame != 0 && (ULONG)Frame != 0xDEADBEEF && (ULONG)Frame != 0xcdcdcdcd && (ULONG)Frame != 0xcccccccc && i++ < FrameCount )
|
||||||
|
{
|
||||||
|
DbgPrint("<%X>", (PVOID)Frame[1]);
|
||||||
|
if (Frame[1] == 0xdeadbeef)
|
||||||
|
break;
|
||||||
|
Frame = (PULONG)Frame[0];
|
||||||
|
DbgPrint(" ");
|
||||||
|
}
|
||||||
|
DbgPrint("\n");
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* HEAP_IsRealArena [Internal]
|
* HEAP_IsRealArena [Internal]
|
||||||
|
@ -985,11 +1008,13 @@ static BOOLEAN HEAP_IsRealArena(
|
||||||
{
|
{
|
||||||
DPRINT("Heap %p: block %p is not inside heap\n",
|
DPRINT("Heap %p: block %p is not inside heap\n",
|
||||||
heap, block );
|
heap, block );
|
||||||
|
DumpStackFrames(NULL,10);
|
||||||
}
|
}
|
||||||
else if (WARN_ON(heap))
|
else if (WARN_ON(heap))
|
||||||
{
|
{
|
||||||
DPRINT1("Heap %p: block %p is not inside heap\n",
|
DPRINT1("Heap %p: block %p is not inside heap\n",
|
||||||
heap, block );
|
heap, block );
|
||||||
|
DumpStackFrames(NULL,10);
|
||||||
}
|
}
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: pool.c,v 1.35 2004/10/01 20:51:29 arty Exp $
|
/* $Id: pool.c,v 1.36 2004/12/11 00:13:37 royce Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -24,6 +24,9 @@ extern MM_STATS MmStats;
|
||||||
|
|
||||||
#define TAG_NONE (ULONG)(('N'<<0) + ('o'<<8) + ('n'<<16) + ('e'<<24))
|
#define TAG_NONE (ULONG)(('N'<<0) + ('o'<<8) + ('n'<<16) + ('e'<<24))
|
||||||
|
|
||||||
|
ULONG STDCALL
|
||||||
|
ExRosQueryPagedPoolTag ( PVOID Block );
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
STATIC PVOID STDCALL
|
STATIC PVOID STDCALL
|
||||||
|
@ -336,4 +339,20 @@ MiRaisePoolQuota(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG STDCALL
|
||||||
|
ExRosQueryPoolTag ( PVOID Block )
|
||||||
|
{
|
||||||
|
ASSERT_IRQL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
if (Block >= MmPagedPoolBase && (char*)Block < ((char*)MmPagedPoolBase + MmPagedPoolSize))
|
||||||
|
{
|
||||||
|
return ExRosQueryPagedPoolTag(Block);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: ppool.c,v 1.33 2004/11/20 21:16:38 navaraf Exp $
|
/* $Id: ppool.c,v 1.34 2004/12/11 00:13:37 royce Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -22,28 +22,46 @@
|
||||||
|
|
||||||
#undef assert
|
#undef assert
|
||||||
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
|
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
|
||||||
#define ASSERT_SIZE(n) assert ( (n) <= MmPagedPoolSize && (n) >= 0 )
|
#define ASSERT_SIZE(n) assert ( (n) <= MmPagedPoolSize && (n) > 0 )
|
||||||
#define ASSERT_PTR(p) assert ( ((size_t)(p)) >= ((size_t)MmPagedPoolBase) && ((size_t)(p)) < ((size_t)((size_t)MmPagedPoolBase+MmPagedPoolSize)) )
|
#define IS_PPOOL_PTR(p) ((size_t)(p)) >= ((size_t)MmPagedPoolBase) && ((size_t)(p)) < ((size_t)((size_t)MmPagedPoolBase+MmPagedPoolSize))
|
||||||
|
#define ASSERT_PTR(p) assert ( IS_PPOOL_PTR(p) )
|
||||||
|
|
||||||
// to disable buffer over/under-run detection, set the following macro to 0
|
// to disable buffer over/under-run detection, set the following macro to 0
|
||||||
|
#if !defined(DBG) && !defined(KDBG)
|
||||||
|
#define MM_PPOOL_REDZONE_BYTES 0
|
||||||
|
#else
|
||||||
#define MM_PPOOL_REDZONE_BYTES 4
|
#define MM_PPOOL_REDZONE_BYTES 4
|
||||||
#define MM_PPOOL_REDZONE_VALUE 0xCD
|
#define MM_PPOOL_REDZONE_LOVALUE 0x87
|
||||||
|
#define MM_PPOOL_REDZONE_HIVALUE 0xA5
|
||||||
|
#define MM_PPOOL_FREEMAGIC (ULONG)(('F'<<0) + ('r'<<8) + ('E'<<16) + ('e'<<24))
|
||||||
|
#define MM_PPOOL_USEDMAGIC (ULONG)(('u'<<0) + ('S'<<8) + ('e'<<16) + ('D'<<24))
|
||||||
|
#define MM_PPOOL_LASTOWNER_ENTRIES 3
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct _MM_PPOOL_FREE_BLOCK_HEADER
|
typedef struct _MM_PPOOL_FREE_BLOCK_HEADER
|
||||||
{
|
{
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
ULONG FreeMagic;
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree;
|
struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree;
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
ULONG LastOwnerStack[MM_PPOOL_LASTOWNER_ENTRIES];
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
}
|
}
|
||||||
MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER;
|
MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER;
|
||||||
|
|
||||||
typedef struct _MM_PPOOL_USED_BLOCK_HEADER
|
typedef struct _MM_PPOOL_USED_BLOCK_HEADER
|
||||||
{
|
{
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
ULONG UsedMagic;
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
#if MM_PPOOL_REDZONE_BYTES
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
|
||||||
ULONG UserSize; // how many bytes the user actually asked for...
|
ULONG UserSize; // how many bytes the user actually asked for...
|
||||||
struct _MM_PPOOL_USED_BLOCK_HEADER* NextUsed;
|
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
|
struct _MM_PPOOL_USED_BLOCK_HEADER* NextUsed;
|
||||||
|
ULONG Tag;
|
||||||
}
|
}
|
||||||
MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER;
|
MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER;
|
||||||
|
|
||||||
|
@ -52,9 +70,7 @@ ULONG MmPagedPoolSize;
|
||||||
ULONG MmTotalPagedPoolQuota = 0;
|
ULONG MmTotalPagedPoolQuota = 0;
|
||||||
static FAST_MUTEX MmPagedPoolLock;
|
static FAST_MUTEX MmPagedPoolLock;
|
||||||
static PMM_PPOOL_FREE_BLOCK_HEADER MmPagedPoolFirstFreeBlock;
|
static PMM_PPOOL_FREE_BLOCK_HEADER MmPagedPoolFirstFreeBlock;
|
||||||
#if MM_PPOOL_REDZONE_BYTES
|
|
||||||
static PMM_PPOOL_USED_BLOCK_HEADER MmPagedPoolFirstUsedBlock;
|
static PMM_PPOOL_USED_BLOCK_HEADER MmPagedPoolFirstUsedBlock;
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -86,6 +102,12 @@ MmInitializePagedPool(VOID)
|
||||||
MmPagedPoolFirstFreeBlock->NextFree = NULL;
|
MmPagedPoolFirstFreeBlock->NextFree = NULL;
|
||||||
|
|
||||||
#if MM_PPOOL_REDZONE_BYTES
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
MmPagedPoolFirstFreeBlock->FreeMagic = MM_PPOOL_FREEMAGIC;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for ( i = 0; i < MM_PPOOL_LASTOWNER_ENTRIES; i++ )
|
||||||
|
MmPagedPoolFirstFreeBlock->LastOwnerStack[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
MmPagedPoolFirstUsedBlock = NULL;
|
MmPagedPoolFirstUsedBlock = NULL;
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
|
@ -102,6 +124,9 @@ static void VerifyPagedPool ( int line )
|
||||||
while ( p )
|
while ( p )
|
||||||
{
|
{
|
||||||
DPRINT ( " 0x%x: %lu bytes (next 0x%x)\n", p, p->Size, p->NextFree );
|
DPRINT ( " 0x%x: %lu bytes (next 0x%x)\n", p, p->Size, p->NextFree );
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
ASSERT ( p->FreeMagic == MM_PPOOL_FREEMAGIC );
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ASSERT_PTR(p);
|
ASSERT_PTR(p);
|
||||||
ASSERT_SIZE(p->Size);
|
ASSERT_SIZE(p->Size);
|
||||||
count++;
|
count++;
|
||||||
|
@ -114,34 +139,84 @@ static void VerifyPagedPool ( int line )
|
||||||
#define VerifyPagedPool()
|
#define VerifyPagedPool()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
BOOLEAN STDCALL
|
||||||
|
KeRosPrintAddress(PVOID address);
|
||||||
|
|
||||||
|
#if !MM_PPOOL_REDZONE_BYTES
|
||||||
|
#define MmpRedZoneCheck(pUsed,Addr,file,line)
|
||||||
|
#else//MM_PPOOL_REDZONE_BYTES
|
||||||
|
static VOID FASTCALL
|
||||||
|
MmpRedZoneCheck ( PMM_PPOOL_USED_BLOCK_HEADER pUsed, PUCHAR Addr, const char* file, int line )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
PUCHAR AddrEnd = Addr + pUsed->UserSize;
|
||||||
|
BOOL bLow = TRUE;
|
||||||
|
BOOL bHigh = TRUE;
|
||||||
|
|
||||||
|
ASSERT_PTR(Addr);
|
||||||
|
if ( pUsed->UsedMagic == MM_PPOOL_FREEMAGIC )
|
||||||
|
{
|
||||||
|
PMM_PPOOL_FREE_BLOCK_HEADER pFree = (PMM_PPOOL_FREE_BLOCK_HEADER)pUsed;
|
||||||
|
DPRINT1 ( "Double-free detected for Block 0x%x (kthread=0x%x)!\n", Addr, KeGetCurrentThread() );
|
||||||
|
DbgPrint ( "First Free Stack Frames:" );
|
||||||
|
for ( i = 0; i < MM_PPOOL_LASTOWNER_ENTRIES; i++ )
|
||||||
|
{
|
||||||
|
if ( pFree->LastOwnerStack[i] != 0xDEADBEEF )
|
||||||
|
{
|
||||||
|
DbgPrint(" ");
|
||||||
|
if (!KeRosPrintAddress ((PVOID)pFree->LastOwnerStack[i]) )
|
||||||
|
{
|
||||||
|
DbgPrint("<%X>", pFree->LastOwnerStack[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DbgPrint ( "\n" );
|
||||||
|
KEBUGCHECK(BAD_POOL_HEADER);
|
||||||
|
}
|
||||||
|
if ( pUsed->UsedMagic != MM_PPOOL_USEDMAGIC )
|
||||||
|
{
|
||||||
|
DPRINT1 ( "Bad magic in Block 0x%x!\n", Addr );
|
||||||
|
KEBUGCHECK(BAD_POOL_HEADER);
|
||||||
|
}
|
||||||
|
ASSERT_SIZE(pUsed->Size);
|
||||||
|
ASSERT_SIZE(pUsed->UserSize);
|
||||||
|
ASSERT_PTR(AddrEnd);
|
||||||
|
Addr -= MM_PPOOL_REDZONE_BYTES; // this is to simplify indexing below...
|
||||||
|
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES && bLow && bHigh; i++ )
|
||||||
|
{
|
||||||
|
bLow = bLow && ( Addr[i] == MM_PPOOL_REDZONE_LOVALUE );
|
||||||
|
bHigh = bHigh && ( AddrEnd[i] == MM_PPOOL_REDZONE_HIVALUE );
|
||||||
|
}
|
||||||
|
if ( !bLow || !bHigh )
|
||||||
|
{
|
||||||
|
const char* violation = "High and Low-side";
|
||||||
|
if ( bHigh ) // high is okay, so it was just low failed
|
||||||
|
violation = "Low-side";
|
||||||
|
else if ( bLow ) // low side is okay, so it was just high failed
|
||||||
|
violation = "High-side";
|
||||||
|
DbgPrint("%s(%i): %s redzone violation detected for paged pool address 0x%x\n",
|
||||||
|
file, line, violation, Addr );
|
||||||
|
DbgPrint ( "UsedMagic 0x%x, LoZone ", pUsed->UsedMagic );
|
||||||
|
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||||
|
DbgPrint ( "%02x", Addr[i] );
|
||||||
|
DbgPrint ( ", HiZone " );
|
||||||
|
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||||
|
DbgPrint ( "%02x", AddrEnd[i] );
|
||||||
|
DbgPrint ( "\n" );
|
||||||
|
KEBUGCHECK(BAD_POOL_HEADER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
MmDbgPagedPoolRedZoneCheck ( const char* file, int line )
|
MmDbgPagedPoolRedZoneCheck ( const char* file, int line )
|
||||||
{
|
{
|
||||||
#if MM_PPOOL_REDZONE_BYTES
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
PMM_PPOOL_USED_BLOCK_HEADER pUsed = MmPagedPoolFirstUsedBlock;
|
PMM_PPOOL_USED_BLOCK_HEADER pUsed = MmPagedPoolFirstUsedBlock;
|
||||||
int i;
|
|
||||||
BOOL bLow = TRUE;
|
|
||||||
BOOL bHigh = TRUE;
|
|
||||||
|
|
||||||
while ( pUsed )
|
while ( pUsed )
|
||||||
{
|
{
|
||||||
PUCHAR Addr = (PUCHAR)block_to_address(pUsed);
|
MmpRedZoneCheck ( pUsed, block_to_address(pUsed), __FILE__, __LINE__ );
|
||||||
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
|
||||||
{
|
|
||||||
bLow = bLow && ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
|
|
||||||
bHigh = bHigh && ( *(Addr+pUsed->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
|
|
||||||
}
|
|
||||||
if ( !bLow || !bHigh )
|
|
||||||
{
|
|
||||||
const char* violation = "High and Low-side";
|
|
||||||
if ( bHigh ) // high is okay, so it was just low failed
|
|
||||||
violation = "Low-side";
|
|
||||||
else if ( bLow ) // low side is okay, so it was just high failed
|
|
||||||
violation = "High-side";
|
|
||||||
DbgPrint("%s(%i): %s redzone violation detected for paged pool address 0x%x\n",
|
|
||||||
file, line, violation, Addr );
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
pUsed = pUsed->NextUsed;
|
pUsed = pUsed->NextUsed;
|
||||||
}
|
}
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
|
@ -270,6 +345,9 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||||
(PMM_PPOOL_FREE_BLOCK_HEADER)address_to_block(BestAlignedAddr);
|
(PMM_PPOOL_FREE_BLOCK_HEADER)address_to_block(BestAlignedAddr);
|
||||||
assert ( BestAlignedAddr > Addr );
|
assert ( BestAlignedAddr > Addr );
|
||||||
NewFreeBlock->Size = (char*)Addr + BestBlock->Size - (char*)BestAlignedAddr;
|
NewFreeBlock->Size = (char*)Addr + BestBlock->Size - (char*)BestAlignedAddr;
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
NewFreeBlock->FreeMagic = MM_PPOOL_FREEMAGIC;
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ASSERT_SIZE(NewFreeBlock->Size);
|
ASSERT_SIZE(NewFreeBlock->Size);
|
||||||
BestBlock->Size = (size_t)NewFreeBlock - (size_t)Addr;
|
BestBlock->Size = (size_t)NewFreeBlock - (size_t)Addr;
|
||||||
ASSERT_SIZE(BestBlock->Size);
|
ASSERT_SIZE(BestBlock->Size);
|
||||||
|
@ -344,6 +422,9 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||||
NextBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)((char*)BestBlock + BlockSize);
|
NextBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)((char*)BestBlock + BlockSize);
|
||||||
//DPRINT(".");
|
//DPRINT(".");
|
||||||
NextBlock->Size = NewSize;
|
NextBlock->Size = NewSize;
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
NextBlock->FreeMagic = MM_PPOOL_FREEMAGIC;
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ASSERT_SIZE ( NextBlock->Size );
|
ASSERT_SIZE ( NextBlock->Size );
|
||||||
//DPRINT(".");
|
//DPRINT(".");
|
||||||
NextBlock->NextFree = BestBlock->NextFree;
|
NextBlock->NextFree = BestBlock->NextFree;
|
||||||
|
@ -372,6 +453,9 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||||
NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
|
NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
|
||||||
//DPRINT(".");
|
//DPRINT(".");
|
||||||
NewBlock->Size = BlockSize;
|
NewBlock->Size = BlockSize;
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
NewBlock->UsedMagic = MM_PPOOL_USEDMAGIC;
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ASSERT_SIZE ( NewBlock->Size );
|
ASSERT_SIZE ( NewBlock->Size );
|
||||||
//DPRINT(".\n");
|
//DPRINT(".\n");
|
||||||
}
|
}
|
||||||
|
@ -397,14 +481,17 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||||
*/
|
*/
|
||||||
NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
|
NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
|
||||||
NewBlock->Size = NewSize;
|
NewBlock->Size = NewSize;
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
NewBlock->UsedMagic = MM_PPOOL_USEDMAGIC;
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ASSERT_SIZE ( NewBlock->Size );
|
ASSERT_SIZE ( NewBlock->Size );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MM_PPOOL_REDZONE_BYTES
|
|
||||||
// now add the block to the used block list
|
// now add the block to the used block list
|
||||||
NewBlock->NextUsed = MmPagedPoolFirstUsedBlock;
|
NewBlock->NextUsed = MmPagedPoolFirstUsedBlock;
|
||||||
MmPagedPoolFirstUsedBlock = NewBlock;
|
MmPagedPoolFirstUsedBlock = NewBlock;
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
|
||||||
|
NewBlock->Tag = Tag;
|
||||||
|
|
||||||
VerifyPagedPool();
|
VerifyPagedPool();
|
||||||
|
|
||||||
|
@ -421,17 +508,9 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||||
PUCHAR Addr = (PUCHAR)BlockAddress;
|
PUCHAR Addr = (PUCHAR)BlockAddress;
|
||||||
//DbgPrint ( "writing buffer-overrun detection bytes" );
|
//DbgPrint ( "writing buffer-overrun detection bytes" );
|
||||||
memset ( Addr - MM_PPOOL_REDZONE_BYTES,
|
memset ( Addr - MM_PPOOL_REDZONE_BYTES,
|
||||||
MM_PPOOL_REDZONE_VALUE, MM_PPOOL_REDZONE_BYTES );
|
MM_PPOOL_REDZONE_LOVALUE, MM_PPOOL_REDZONE_BYTES );
|
||||||
memset ( Addr + NewBlock->UserSize, MM_PPOOL_REDZONE_VALUE,
|
memset ( Addr + NewBlock->UserSize, MM_PPOOL_REDZONE_HIVALUE,
|
||||||
MM_PPOOL_REDZONE_BYTES );
|
MM_PPOOL_REDZONE_BYTES );
|
||||||
/*for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
|
||||||
{
|
|
||||||
//DbgPrint(".");
|
|
||||||
*(Addr-i-1) = 0xCD;
|
|
||||||
//DbgPrint("o");
|
|
||||||
*(Addr+NewBlock->UserSize+i) = 0xCD;
|
|
||||||
}*/
|
|
||||||
//DbgPrint ( "done!\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
|
@ -452,33 +531,14 @@ ExFreePagedPool(IN PVOID Block)
|
||||||
|
|
||||||
ASSERT_IRQL(APC_LEVEL);
|
ASSERT_IRQL(APC_LEVEL);
|
||||||
|
|
||||||
#if MM_PPOOL_REDZONE_BYTES
|
MmpRedZoneCheck ( UsedBlock, Block, __FILE__, __LINE__ );
|
||||||
// write out buffer-overrun detection bytes
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
PUCHAR Addr = (PUCHAR)Block;
|
|
||||||
//DbgPrint ( "checking buffer-overrun detection bytes..." );
|
|
||||||
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
|
||||||
{
|
|
||||||
if (*(Addr-i-1) != MM_PPOOL_REDZONE_VALUE)
|
|
||||||
{
|
|
||||||
DPRINT1("Attempt to free memory %#08x. Redzone underrun!\n", Block);
|
|
||||||
}
|
|
||||||
if (*(Addr+UsedBlock->UserSize+i) != MM_PPOOL_REDZONE_VALUE)
|
|
||||||
{
|
|
||||||
DPRINT1("Attempt to free memory %#08x. Redzone overrun!\n", Block);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
assert ( *(Addr+UsedBlock->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
|
memset ( Block, 0xCD, UsedBlock->UserSize );
|
||||||
}
|
#endif
|
||||||
//DbgPrint ( "done!\n" );
|
|
||||||
}
|
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
|
||||||
|
|
||||||
ExAcquireFastMutex(&MmPagedPoolLock);
|
ExAcquireFastMutex(&MmPagedPoolLock);
|
||||||
|
|
||||||
#if MM_PPOOL_REDZONE_BYTES
|
|
||||||
// remove from used list...
|
// remove from used list...
|
||||||
{
|
{
|
||||||
PMM_PPOOL_USED_BLOCK_HEADER pPrev = MmPagedPoolFirstUsedBlock;
|
PMM_PPOOL_USED_BLOCK_HEADER pPrev = MmPagedPoolFirstUsedBlock;
|
||||||
|
@ -497,12 +557,38 @@ ExFreePagedPool(IN PVOID Block)
|
||||||
pPrev->NextUsed = UsedBlock->NextUsed;
|
pPrev->NextUsed = UsedBlock->NextUsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif//MM_PPOOL_REDZONE_BYTES
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Begin setting up the newly freed block's header.
|
* Begin setting up the newly freed block's header.
|
||||||
*/
|
*/
|
||||||
FreeBlock->Size = UsedSize;
|
FreeBlock->Size = UsedSize;
|
||||||
|
#if MM_PPOOL_REDZONE_BYTES
|
||||||
|
FreeBlock->FreeMagic = MM_PPOOL_FREEMAGIC;
|
||||||
|
{
|
||||||
|
PULONG Frame;
|
||||||
|
int i;
|
||||||
|
#if defined __GNUC__
|
||||||
|
__asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
__asm mov [Frame], ebp
|
||||||
|
#endif
|
||||||
|
//DbgPrint ( "Stack Frames for Free Block 0x%x:", Block );
|
||||||
|
Frame = (PULONG)Frame[0]; // step out of ExFreePagedPool
|
||||||
|
for ( i = 0; i < MM_PPOOL_LASTOWNER_ENTRIES; i++ )
|
||||||
|
{
|
||||||
|
if ( Frame == 0 || (ULONG)Frame == 0xDEADBEEF )
|
||||||
|
FreeBlock->LastOwnerStack[i] = 0xDEADBEEF;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//DbgPrint ( " 0x%x", Frame[1] );
|
||||||
|
FreeBlock->LastOwnerStack[i] = Frame[1];
|
||||||
|
Frame = (PULONG)Frame[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//DbgPrint ( "\n" );
|
||||||
|
//KeRosDumpStackFrames ( NULL, 4 );
|
||||||
|
}
|
||||||
|
#endif//MM_PPOOL_REDZONE_BYTES
|
||||||
ASSERT_SIZE ( FreeBlock->Size );
|
ASSERT_SIZE ( FreeBlock->Size );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -533,6 +619,7 @@ ExFreePagedPool(IN PVOID Block)
|
||||||
/*
|
/*
|
||||||
* If the next block is immediately adjacent to the newly freed one then
|
* If the next block is immediately adjacent to the newly freed one then
|
||||||
* merge them.
|
* merge them.
|
||||||
|
* PLEASE DO NOT WIPE OUT 'MAGIC' OR 'LASTOWNER' DATA FOR MERGED FREE BLOCKS
|
||||||
*/
|
*/
|
||||||
if (NextBlock != NULL &&
|
if (NextBlock != NULL &&
|
||||||
((char*)FreeBlock + FreeBlock->Size) == (char*)NextBlock)
|
((char*)FreeBlock + FreeBlock->Size) == (char*)NextBlock)
|
||||||
|
@ -550,6 +637,7 @@ ExFreePagedPool(IN PVOID Block)
|
||||||
/*
|
/*
|
||||||
* If the previous block is adjacent to the newly freed one then
|
* If the previous block is adjacent to the newly freed one then
|
||||||
* merge them.
|
* merge them.
|
||||||
|
* PLEASE DO NOT WIPE OUT 'MAGIC' OR 'LASTOWNER' DATA FOR MERGED FREE BLOCKS
|
||||||
*/
|
*/
|
||||||
if (PreviousBlock != NULL &&
|
if (PreviousBlock != NULL &&
|
||||||
((char*)PreviousBlock + PreviousBlock->Size) == (char*)FreeBlock)
|
((char*)PreviousBlock + PreviousBlock->Size) == (char*)FreeBlock)
|
||||||
|
@ -564,4 +652,40 @@ ExFreePagedPool(IN PVOID Block)
|
||||||
ExReleaseFastMutex(&MmPagedPoolLock);
|
ExReleaseFastMutex(&MmPagedPoolLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
ExRosDumpPagedPoolByTag ( ULONG Tag )
|
||||||
|
{
|
||||||
|
PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = MmPagedPoolFirstUsedBlock;
|
||||||
|
int count = 0;
|
||||||
|
char tag[5];
|
||||||
|
|
||||||
|
// TODO FIXME - should we validate params or ASSERT_IRQL?
|
||||||
|
*(ULONG*)&tag[0] = Tag;
|
||||||
|
tag[4] = 0;
|
||||||
|
DbgPrint ( "PagedPool Dump by tag '%s'\n", tag );
|
||||||
|
DbgPrint ( " -BLOCK-- --SIZE--\n" );
|
||||||
|
while ( IS_PPOOL_PTR(UsedBlock) )
|
||||||
|
{
|
||||||
|
if ( UsedBlock->Tag == Tag )
|
||||||
|
{
|
||||||
|
DbgPrint ( " %08X %08X\n", UsedBlock, UsedBlock->Size );
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
UsedBlock = UsedBlock->NextUsed;
|
||||||
|
}
|
||||||
|
if ( UsedBlock && !IS_PPOOL_PTR(UsedBlock) )
|
||||||
|
{
|
||||||
|
DPRINT1 ( "!!NextUsed took me to lala land: 0x%08X\n", UsedBlock );
|
||||||
|
}
|
||||||
|
DbgPrint ( "Entries found for tag '%s': %i\n", tag, count );
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDCALL
|
||||||
|
ExRosQueryPagedPoolTag ( PVOID Block )
|
||||||
|
{
|
||||||
|
PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = address_to_block(Block);
|
||||||
|
// TODO FIXME - should we validate params or ASSERT_IRQL?
|
||||||
|
return UsedBlock->Tag;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
; $Id: ntoskrnl.def,v 1.202 2004/11/27 13:04:06 navaraf Exp $
|
; $Id: ntoskrnl.def,v 1.203 2004/12/11 00:13:37 royce Exp $
|
||||||
;
|
;
|
||||||
; reactos/ntoskrnl/ntoskrnl.def
|
; reactos/ntoskrnl/ntoskrnl.def
|
||||||
;
|
;
|
||||||
|
@ -139,6 +139,8 @@ ExReleaseResourceForThreadLite@8
|
||||||
@ExReleaseResourceLite@4
|
@ExReleaseResourceLite@4
|
||||||
@ExReleaseRundownProtection@4
|
@ExReleaseRundownProtection@4
|
||||||
@ExReleaseRundownProtectionEx@8
|
@ExReleaseRundownProtectionEx@8
|
||||||
|
ExRosDumpPagedPoolByTag@4
|
||||||
|
ExRosQueryPoolTag@4
|
||||||
@ExRundownCompleted@4
|
@ExRundownCompleted@4
|
||||||
ExSetResourceOwnerPointer@8
|
ExSetResourceOwnerPointer@8
|
||||||
ExSetTimerResolution@8
|
ExSetTimerResolution@8
|
||||||
|
|
Loading…
Reference in a new issue