492 lines
12 KiB
C
492 lines
12 KiB
C
/*++
|
|
|
|
Copyright (c) 1995-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
debug.c
|
|
|
|
Abstract:
|
|
|
|
Debug functions
|
|
|
|
Revision History:
|
|
|
|
AmritanR
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define __FILE_SIG__ DEBUG_SIG
|
|
|
|
#include "ipmcast.h"
|
|
|
|
#define PRINT_BYTES(x) (UCHAR)x,(UCHAR)(x>>8),(UCHAR)(x>>16),(UCHAR)(x>>24)
|
|
|
|
#if RT_LOCK_DEBUG
|
|
|
|
KSPIN_LOCK g_kslLockLock;
|
|
|
|
#endif
|
|
|
|
#if RT_MEM_DEBUG
|
|
|
|
RT_LOCK g_rlMemoryLock;
|
|
LIST_ENTRY g_leAllocMemListHead;
|
|
LIST_ENTRY g_leFreeMemListHead;
|
|
|
|
#endif
|
|
|
|
VOID
|
|
RtInitializeDebug()
|
|
{
|
|
|
|
#if RT_TRACE_DEBUG
|
|
|
|
g_byDebugLevel = RT_DBG_LEVEL_WARN;
|
|
//g_byDebugLevel = 0x00;
|
|
g_fDebugComp = 0xFFFFFFFF;
|
|
|
|
#endif
|
|
|
|
#if RT_LOCK_DEBUG
|
|
|
|
KeInitializeSpinLock(&(g_kslLockLock));
|
|
|
|
#endif
|
|
|
|
#if RT_MEM_DEBUG
|
|
|
|
RtInitializeSpinLock(&g_rlMemoryLock);
|
|
|
|
InitializeListHead(&g_leAllocMemListHead);
|
|
InitializeListHead(&g_leFreeMemListHead);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#if RT_LOCK_DEBUG
|
|
|
|
VOID
|
|
RtpInitializeSpinLock(
|
|
IN PRT_LOCK pLock,
|
|
IN ULONG ulFileSig,
|
|
IN ULONG ulLineNumber
|
|
)
|
|
{
|
|
pLock->ulLockSig = RT_LOCK_SIG;
|
|
pLock->ulFileSig = 0;
|
|
pLock->ulLineNumber = 0;
|
|
pLock->bAcquired = 0;
|
|
pLock->pktLastThread = (PKTHREAD) NULL;
|
|
|
|
KeInitializeSpinLock(&(pLock->kslLock));
|
|
}
|
|
|
|
VOID
|
|
RtpAcquireSpinLock(
|
|
IN PRT_LOCK pLock,
|
|
OUT PKIRQL pkiIrql,
|
|
IN ULONG ulFileSig,
|
|
IN ULONG ulLineNumber,
|
|
IN BOOLEAN bAtDpc
|
|
)
|
|
{
|
|
PKTHREAD pThread;
|
|
KIRQL kiInternalIrql;
|
|
|
|
pThread = KeGetCurrentThread();
|
|
|
|
if (bAtDpc) {
|
|
kiInternalIrql = KeGetCurrentIrql();
|
|
|
|
if (kiInternalIrql isnot DISPATCH_LEVEL) {
|
|
DbgPrint("RTDBG: Called AcquireSpinLockAtDpc for lock at 0x%x when not at DISPATCH. File %c%c%c%c, Line %d\n",
|
|
pLock,
|
|
PRINT_BYTES(ulFileSig),
|
|
ulLineNumber);
|
|
|
|
DbgBreakPoint();
|
|
}
|
|
}
|
|
KeAcquireSpinLock(&(g_kslLockLock),
|
|
&kiInternalIrql);
|
|
|
|
if (pLock->ulLockSig isnot RT_LOCK_SIG) {
|
|
DbgPrint("RTDBG: Trying to acquire uninited lock 0x%x, File %c%c%c%c, Line %d\n",
|
|
pLock,
|
|
(CHAR) (ulFileSig & 0xff),
|
|
(CHAR) ((ulFileSig >> 8) & 0xff),
|
|
(CHAR) ((ulFileSig >> 16) & 0xff),
|
|
(CHAR) ((ulFileSig >> 24) & 0xff),
|
|
ulLineNumber);
|
|
|
|
DbgBreakPoint();
|
|
}
|
|
if (pLock->bAcquired isnot 0) {
|
|
if (pLock->pktLastThread is pThread) {
|
|
DbgPrint("RTDBG: Detected recursive locking!: pLock 0x%x, File %c%c%c%c, Line %d\n",
|
|
pLock,
|
|
PRINT_BYTES(ulFileSig),
|
|
ulLineNumber);
|
|
|
|
DbgPrint("RTDBG: pLock 0x%x already acquired in File %c%c%c%c, Line %d\n",
|
|
pLock,
|
|
PRINT_BYTES(pLock->ulFileSig),
|
|
pLock->ulLineNumber);
|
|
|
|
DbgBreakPoint();
|
|
}
|
|
}
|
|
KeReleaseSpinLock(&(g_kslLockLock),
|
|
kiInternalIrql);
|
|
|
|
if (bAtDpc) {
|
|
KeAcquireSpinLockAtDpcLevel(&(pLock->kslLock));
|
|
} else {
|
|
KeAcquireSpinLock(&(pLock->kslLock),
|
|
pkiIrql);
|
|
}
|
|
|
|
//
|
|
// Mark this lock.
|
|
//
|
|
|
|
pLock->pktLastThread = pThread;
|
|
pLock->ulFileSig = ulFileSig;
|
|
pLock->ulLineNumber = ulLineNumber;
|
|
pLock->bAcquired = TRUE;
|
|
}
|
|
|
|
VOID
|
|
RtpReleaseSpinLock(
|
|
IN PRT_LOCK pLock,
|
|
IN KIRQL kiIrql,
|
|
IN ULONG ulFileSig,
|
|
IN ULONG ulLineNumber,
|
|
IN BOOLEAN bFromDpc
|
|
)
|
|
{
|
|
if (pLock->ulLockSig isnot RT_LOCK_SIG) {
|
|
DbgPrint("RTDBG: Trying to release uninited lock 0x%x, File %c%c%c%c, Line %d\n",
|
|
pLock,
|
|
PRINT_BYTES(ulFileSig),
|
|
ulLineNumber);
|
|
DbgBreakPoint();
|
|
}
|
|
if (pLock->bAcquired is 0) {
|
|
DbgPrint("RTDBG: Detected release of unacquired lock 0x%x, File %c%c%c%c, Line %d\n",
|
|
pLock,
|
|
PRINT_BYTES(ulFileSig),
|
|
ulLineNumber);
|
|
|
|
DbgBreakPoint();
|
|
}
|
|
pLock->ulFileSig = ulFileSig;
|
|
pLock->ulLineNumber = ulLineNumber;
|
|
pLock->bAcquired = FALSE;
|
|
pLock->pktLastThread = (PKTHREAD) NULL;
|
|
|
|
if (bFromDpc) {
|
|
KeReleaseSpinLockFromDpcLevel(&(pLock->kslLock));
|
|
} else {
|
|
KeReleaseSpinLock(&(pLock->kslLock),
|
|
kiIrql);
|
|
}
|
|
}
|
|
|
|
#endif // RT_LOCK_DEBUG
|
|
|
|
#if RT_MEM_DEBUG
|
|
|
|
PVOID
|
|
RtpAllocate(
|
|
IN POOL_TYPE ptPool,
|
|
IN ULONG ulSize,
|
|
IN ULONG ulTag,
|
|
IN ULONG ulFileSig,
|
|
IN ULONG ulLineNumber
|
|
)
|
|
{
|
|
PVOID pBuffer;
|
|
PRT_ALLOCATION pwaAlloc;
|
|
KIRQL kiIrql;
|
|
|
|
pwaAlloc = ExAllocatePoolWithTag(ptPool,
|
|
ulSize + sizeof(RT_ALLOCATION),
|
|
ulTag);
|
|
|
|
if (pwaAlloc is NULL) {
|
|
Trace(MEMORY, ERROR,
|
|
("Failed to allocate %d bytes in file %c%c%c%c, line %d\n",
|
|
ulSize, PRINT_BYTES(ulFileSig), ulLineNumber));
|
|
|
|
pBuffer = NULL;
|
|
} else {
|
|
pBuffer = (PVOID) & (pwaAlloc->pucData);
|
|
|
|
pwaAlloc->ulMemSig = RT_MEMORY_SIG;
|
|
pwaAlloc->ulFileSig = ulFileSig;
|
|
pwaAlloc->ulLineNumber = ulLineNumber;
|
|
pwaAlloc->ulSize = ulSize;
|
|
|
|
RtAcquireSpinLock(&(g_rlMemoryLock), &kiIrql);
|
|
|
|
InsertHeadList(&g_leAllocMemListHead,
|
|
&(pwaAlloc->leLink));
|
|
|
|
RtReleaseSpinLock(&g_rlMemoryLock, kiIrql);
|
|
}
|
|
|
|
return pBuffer;
|
|
|
|
}
|
|
|
|
VOID
|
|
RtpFree(
|
|
PVOID pvPointer,
|
|
IN ULONG ulFileSig,
|
|
IN ULONG ulLineNumber
|
|
)
|
|
{
|
|
PRT_ALLOCATION pwaAlloc;
|
|
KIRQL kiIrql;
|
|
PRT_FREE pFree;
|
|
|
|
pwaAlloc = CONTAINING_RECORD(pvPointer, RT_ALLOCATION, pucData);
|
|
|
|
if (pwaAlloc->ulMemSig is RT_FREE_SIG) {
|
|
DbgPrint("RTDBG: Trying to free memory that is already freed. Pointer0x%x, File %c%c%c%c, Line %d. Was freed at File %c%c%c%c, Line %d. \n",
|
|
pvPointer,
|
|
PRINT_BYTES(ulFileSig),
|
|
ulLineNumber,
|
|
PRINT_BYTES(pwaAlloc->ulFileSig),
|
|
pwaAlloc->ulLineNumber);
|
|
|
|
return;
|
|
}
|
|
if (pwaAlloc->ulMemSig isnot RT_MEMORY_SIG) {
|
|
DbgPrint("RTDBG: Trying to free memory whose signature is wrong. Pointer 0x%x\n",
|
|
pvPointer);
|
|
|
|
DbgBreakPoint();
|
|
|
|
return;
|
|
}
|
|
//
|
|
// create a warp free block for it
|
|
//
|
|
|
|
pFree = ExAllocatePoolWithTag(NonPagedPool,
|
|
sizeof(RT_FREE),
|
|
FREE_TAG);
|
|
|
|
RtAssert(pFree);
|
|
|
|
//
|
|
// Take the lock so that no one else touches the list
|
|
//
|
|
|
|
RtAcquireSpinLock(&(g_rlMemoryLock), &kiIrql);
|
|
|
|
RemoveEntryList(&(pwaAlloc->leLink));
|
|
|
|
pFree->ulMemSig = RT_FREE_SIG;
|
|
pFree->ulAllocFileSig = pwaAlloc->ulFileSig;
|
|
pFree->ulAllocLineNumber = pwaAlloc->ulLineNumber;
|
|
pFree->ulFreeFileSig = ulFileSig;
|
|
pFree->ulFreeLineNumber = ulLineNumber;
|
|
pFree->ulStartAddr = (ULONG_PTR) (pwaAlloc->pucData);
|
|
pFree->ulSize = pwaAlloc->ulSize;
|
|
|
|
pwaAlloc->ulMemSig = RT_FREE_SIG;
|
|
pwaAlloc->ulFileSig = ulFileSig;
|
|
pwaAlloc->ulLineNumber = ulLineNumber;
|
|
|
|
ExFreePool(pwaAlloc);
|
|
|
|
InsertTailList(&g_leFreeMemListHead,
|
|
&(pFree->leLink));
|
|
|
|
RtReleaseSpinLock(&(g_rlMemoryLock), kiIrql);
|
|
}
|
|
|
|
VOID
|
|
RtAuditMemory()
|
|
{
|
|
PRT_ALLOCATION pwaAlloc;
|
|
PLIST_ENTRY pleNode;
|
|
PRT_FREE pFree;
|
|
|
|
while (!IsListEmpty(&g_leAllocMemListHead)) {
|
|
pleNode = RemoveHeadList(&g_leAllocMemListHead);
|
|
|
|
pwaAlloc = CONTAINING_RECORD(pleNode, RT_ALLOCATION, leLink);
|
|
|
|
if (pwaAlloc->ulMemSig is RT_MEMORY_SIG) {
|
|
DbgPrint("RTDBG: Unfreed memory. %d bytes. Pointer 0x%x, File %c%c%c%c, Line %d\n",
|
|
pwaAlloc->ulSize,
|
|
pwaAlloc->pucData,
|
|
PRINT_BYTES(pwaAlloc->ulFileSig),
|
|
pwaAlloc->ulLineNumber);
|
|
|
|
DbgBreakPoint();
|
|
|
|
ExFreePool(pwaAlloc);
|
|
|
|
continue;
|
|
}
|
|
DbgPrint("RTDBG: Allocation with bad signature. Pointer 0x%x\n",
|
|
pwaAlloc->pucData);
|
|
|
|
DbgBreakPoint();
|
|
|
|
continue;
|
|
}
|
|
|
|
while (!IsListEmpty(&g_leFreeMemListHead)) {
|
|
pleNode = RemoveHeadList(&g_leFreeMemListHead);
|
|
|
|
pFree = CONTAINING_RECORD(pleNode, RT_FREE, leLink);
|
|
|
|
if (pFree->ulMemSig is RT_FREE_SIG) {
|
|
ExFreePool(pFree);
|
|
|
|
continue;
|
|
}
|
|
DbgPrint("RTDBG: Freed memory with bad signature.\n");
|
|
|
|
DbgBreakPoint();
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if IF_REFERENCE_DEBUG
|
|
|
|
uint
|
|
DbgLockedReferenceIF(
|
|
IN Interface *RefIF,
|
|
IN uchar *File,
|
|
IN uint Line
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Increases the reference count of a IF and records a history of who
|
|
made the call to reference.
|
|
|
|
Arguments:
|
|
|
|
RefIF - The IF to reference.
|
|
File - The filename containing the calling fcn (output of the __FILE__ macro).
|
|
Line - The line number of the call to this fcn (output of the __LINE__ macro).
|
|
|
|
Return Value:
|
|
|
|
Reference count
|
|
|
|
--*/
|
|
{
|
|
void *CallersCaller;
|
|
IF_REFERENCE_HISTORY *RefHistory;
|
|
|
|
RefHistory = &RefIF->if_refhistory[RefIF->if_refhistory_index];
|
|
RefHistory->File = File;
|
|
RefHistory->Line = Line;
|
|
RtlGetCallersAddress(&RefHistory->Caller, &CallersCaller);
|
|
RefHistory->Count = ++RefIF->if_refcount;
|
|
RefIF->if_refhistory_index = ++RefIF->if_refhistory_index % MAX_IFREFERENCE_HISTORY;
|
|
|
|
return RefIF->if_refcount;
|
|
|
|
}
|
|
|
|
|
|
uint
|
|
DbgDereferenceIF(
|
|
IN Interface *DerefIF,
|
|
IN uchar *File,
|
|
IN uint Line
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Lock, Dereference the interface and records a history of who made the call to dereference.
|
|
|
|
Arguments:
|
|
|
|
DerefIF - The IF to dereference.
|
|
File - The filename containing the calling fcn (output of the __FILE__ macro).
|
|
Line - The line number of the call to this fcn (output of the __LINE__ macro).
|
|
|
|
Return Value:
|
|
Original reference count
|
|
|
|
--*/
|
|
{
|
|
void *Caller;
|
|
IF_REFERENCE_HISTORY *RefHistory;
|
|
CTELockHandle RouteTableHandle;
|
|
uint RefCount;
|
|
|
|
CTEGetLock(&RouteTableLock.Lock, &RouteTableHandle);
|
|
RefHistory = &DerefIF->if_refhistory[DerefIF->if_refhistory_index];
|
|
RefHistory->File = File;
|
|
RefHistory->Line = Line;
|
|
RtlGetCallersAddress(&Caller, &RefHistory->Caller);
|
|
RefCount = DerefIF->if_refcount;
|
|
RefHistory->Count = --DerefIF->if_refcount;
|
|
DerefIF->if_refhistory_index = ++DerefIF->if_refhistory_index % MAX_IFREFERENCE_HISTORY;
|
|
CTEFreeLock(&RouteTableLock.Lock, RouteTableHandle);
|
|
|
|
return RefCount;
|
|
|
|
}
|
|
|
|
uint
|
|
DbgLockedDereferenceIF(
|
|
IN Interface *DerefIF,
|
|
IN uchar *File,
|
|
IN uint Line
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dereference the interface and records a history of who made the call to dereference.
|
|
|
|
Arguments:
|
|
|
|
DerefIF - The IF to dereference.
|
|
File - The filename containing the calling fcn (output of the __FILE__ macro).
|
|
Line - The line number of the call to this fcn (output of the __LINE__ macro).
|
|
|
|
Return Value:
|
|
Reference count
|
|
|
|
--*/
|
|
{
|
|
void *Caller;
|
|
IF_REFERENCE_HISTORY *RefHistory;
|
|
uint RefCount;
|
|
|
|
RefHistory = &DerefIF->if_refhistory[DerefIF->if_refhistory_index];
|
|
RefHistory->File = File;
|
|
RefHistory->Line = Line;
|
|
RtlGetCallersAddress(&Caller, &RefHistory->Caller);
|
|
RefCount = DerefIF->if_refcount;
|
|
RefHistory->Count = --DerefIF->if_refcount;
|
|
DerefIF->if_refhistory_index = ++DerefIF->if_refhistory_index % MAX_IFREFERENCE_HISTORY;
|
|
|
|
return RefCount;
|
|
|
|
}
|
|
|
|
#endif
|