/*++ 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