Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

491 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. debug.c
  5. Abstract:
  6. Debug functions
  7. Revision History:
  8. AmritanR
  9. --*/
  10. #include "precomp.h"
  11. #define __FILE_SIG__ DEBUG_SIG
  12. #include "ipmcast.h"
  13. #define PRINT_BYTES(x) (UCHAR)x,(UCHAR)(x>>8),(UCHAR)(x>>16),(UCHAR)(x>>24)
  14. #if RT_LOCK_DEBUG
  15. KSPIN_LOCK g_kslLockLock;
  16. #endif
  17. #if RT_MEM_DEBUG
  18. RT_LOCK g_rlMemoryLock;
  19. LIST_ENTRY g_leAllocMemListHead;
  20. LIST_ENTRY g_leFreeMemListHead;
  21. #endif
  22. VOID
  23. RtInitializeDebug()
  24. {
  25. #if RT_TRACE_DEBUG
  26. g_byDebugLevel = RT_DBG_LEVEL_WARN;
  27. //g_byDebugLevel = 0x00;
  28. g_fDebugComp = 0xFFFFFFFF;
  29. #endif
  30. #if RT_LOCK_DEBUG
  31. KeInitializeSpinLock(&(g_kslLockLock));
  32. #endif
  33. #if RT_MEM_DEBUG
  34. RtInitializeSpinLock(&g_rlMemoryLock);
  35. InitializeListHead(&g_leAllocMemListHead);
  36. InitializeListHead(&g_leFreeMemListHead);
  37. #endif
  38. }
  39. #if RT_LOCK_DEBUG
  40. VOID
  41. RtpInitializeSpinLock(
  42. IN PRT_LOCK pLock,
  43. IN ULONG ulFileSig,
  44. IN ULONG ulLineNumber
  45. )
  46. {
  47. pLock->ulLockSig = RT_LOCK_SIG;
  48. pLock->ulFileSig = 0;
  49. pLock->ulLineNumber = 0;
  50. pLock->bAcquired = 0;
  51. pLock->pktLastThread = (PKTHREAD) NULL;
  52. KeInitializeSpinLock(&(pLock->kslLock));
  53. }
  54. VOID
  55. RtpAcquireSpinLock(
  56. IN PRT_LOCK pLock,
  57. OUT PKIRQL pkiIrql,
  58. IN ULONG ulFileSig,
  59. IN ULONG ulLineNumber,
  60. IN BOOLEAN bAtDpc
  61. )
  62. {
  63. PKTHREAD pThread;
  64. KIRQL kiInternalIrql;
  65. pThread = KeGetCurrentThread();
  66. if (bAtDpc) {
  67. kiInternalIrql = KeGetCurrentIrql();
  68. if (kiInternalIrql isnot DISPATCH_LEVEL) {
  69. DbgPrint("RTDBG: Called AcquireSpinLockAtDpc for lock at 0x%x when not at DISPATCH. File %c%c%c%c, Line %d\n",
  70. pLock,
  71. PRINT_BYTES(ulFileSig),
  72. ulLineNumber);
  73. DbgBreakPoint();
  74. }
  75. }
  76. KeAcquireSpinLock(&(g_kslLockLock),
  77. &kiInternalIrql);
  78. if (pLock->ulLockSig isnot RT_LOCK_SIG) {
  79. DbgPrint("RTDBG: Trying to acquire uninited lock 0x%x, File %c%c%c%c, Line %d\n",
  80. pLock,
  81. (CHAR) (ulFileSig & 0xff),
  82. (CHAR) ((ulFileSig >> 8) & 0xff),
  83. (CHAR) ((ulFileSig >> 16) & 0xff),
  84. (CHAR) ((ulFileSig >> 24) & 0xff),
  85. ulLineNumber);
  86. DbgBreakPoint();
  87. }
  88. if (pLock->bAcquired isnot 0) {
  89. if (pLock->pktLastThread is pThread) {
  90. DbgPrint("RTDBG: Detected recursive locking!: pLock 0x%x, File %c%c%c%c, Line %d\n",
  91. pLock,
  92. PRINT_BYTES(ulFileSig),
  93. ulLineNumber);
  94. DbgPrint("RTDBG: pLock 0x%x already acquired in File %c%c%c%c, Line %d\n",
  95. pLock,
  96. PRINT_BYTES(pLock->ulFileSig),
  97. pLock->ulLineNumber);
  98. DbgBreakPoint();
  99. }
  100. }
  101. KeReleaseSpinLock(&(g_kslLockLock),
  102. kiInternalIrql);
  103. if (bAtDpc) {
  104. KeAcquireSpinLockAtDpcLevel(&(pLock->kslLock));
  105. } else {
  106. KeAcquireSpinLock(&(pLock->kslLock),
  107. pkiIrql);
  108. }
  109. //
  110. // Mark this lock.
  111. //
  112. pLock->pktLastThread = pThread;
  113. pLock->ulFileSig = ulFileSig;
  114. pLock->ulLineNumber = ulLineNumber;
  115. pLock->bAcquired = TRUE;
  116. }
  117. VOID
  118. RtpReleaseSpinLock(
  119. IN PRT_LOCK pLock,
  120. IN KIRQL kiIrql,
  121. IN ULONG ulFileSig,
  122. IN ULONG ulLineNumber,
  123. IN BOOLEAN bFromDpc
  124. )
  125. {
  126. if (pLock->ulLockSig isnot RT_LOCK_SIG) {
  127. DbgPrint("RTDBG: Trying to release uninited lock 0x%x, File %c%c%c%c, Line %d\n",
  128. pLock,
  129. PRINT_BYTES(ulFileSig),
  130. ulLineNumber);
  131. DbgBreakPoint();
  132. }
  133. if (pLock->bAcquired is 0) {
  134. DbgPrint("RTDBG: Detected release of unacquired lock 0x%x, File %c%c%c%c, Line %d\n",
  135. pLock,
  136. PRINT_BYTES(ulFileSig),
  137. ulLineNumber);
  138. DbgBreakPoint();
  139. }
  140. pLock->ulFileSig = ulFileSig;
  141. pLock->ulLineNumber = ulLineNumber;
  142. pLock->bAcquired = FALSE;
  143. pLock->pktLastThread = (PKTHREAD) NULL;
  144. if (bFromDpc) {
  145. KeReleaseSpinLockFromDpcLevel(&(pLock->kslLock));
  146. } else {
  147. KeReleaseSpinLock(&(pLock->kslLock),
  148. kiIrql);
  149. }
  150. }
  151. #endif // RT_LOCK_DEBUG
  152. #if RT_MEM_DEBUG
  153. PVOID
  154. RtpAllocate(
  155. IN POOL_TYPE ptPool,
  156. IN ULONG ulSize,
  157. IN ULONG ulTag,
  158. IN ULONG ulFileSig,
  159. IN ULONG ulLineNumber
  160. )
  161. {
  162. PVOID pBuffer;
  163. PRT_ALLOCATION pwaAlloc;
  164. KIRQL kiIrql;
  165. pwaAlloc = ExAllocatePoolWithTag(ptPool,
  166. ulSize + sizeof(RT_ALLOCATION),
  167. ulTag);
  168. if (pwaAlloc is NULL) {
  169. Trace(MEMORY, ERROR,
  170. ("Failed to allocate %d bytes in file %c%c%c%c, line %d\n",
  171. ulSize, PRINT_BYTES(ulFileSig), ulLineNumber));
  172. pBuffer = NULL;
  173. } else {
  174. pBuffer = (PVOID) & (pwaAlloc->pucData);
  175. pwaAlloc->ulMemSig = RT_MEMORY_SIG;
  176. pwaAlloc->ulFileSig = ulFileSig;
  177. pwaAlloc->ulLineNumber = ulLineNumber;
  178. pwaAlloc->ulSize = ulSize;
  179. RtAcquireSpinLock(&(g_rlMemoryLock), &kiIrql);
  180. InsertHeadList(&g_leAllocMemListHead,
  181. &(pwaAlloc->leLink));
  182. RtReleaseSpinLock(&g_rlMemoryLock, kiIrql);
  183. }
  184. return pBuffer;
  185. }
  186. VOID
  187. RtpFree(
  188. PVOID pvPointer,
  189. IN ULONG ulFileSig,
  190. IN ULONG ulLineNumber
  191. )
  192. {
  193. PRT_ALLOCATION pwaAlloc;
  194. KIRQL kiIrql;
  195. PRT_FREE pFree;
  196. pwaAlloc = CONTAINING_RECORD(pvPointer, RT_ALLOCATION, pucData);
  197. if (pwaAlloc->ulMemSig is RT_FREE_SIG) {
  198. 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",
  199. pvPointer,
  200. PRINT_BYTES(ulFileSig),
  201. ulLineNumber,
  202. PRINT_BYTES(pwaAlloc->ulFileSig),
  203. pwaAlloc->ulLineNumber);
  204. return;
  205. }
  206. if (pwaAlloc->ulMemSig isnot RT_MEMORY_SIG) {
  207. DbgPrint("RTDBG: Trying to free memory whose signature is wrong. Pointer 0x%x\n",
  208. pvPointer);
  209. DbgBreakPoint();
  210. return;
  211. }
  212. //
  213. // create a warp free block for it
  214. //
  215. pFree = ExAllocatePoolWithTag(NonPagedPool,
  216. sizeof(RT_FREE),
  217. FREE_TAG);
  218. RtAssert(pFree);
  219. //
  220. // Take the lock so that no one else touches the list
  221. //
  222. RtAcquireSpinLock(&(g_rlMemoryLock), &kiIrql);
  223. RemoveEntryList(&(pwaAlloc->leLink));
  224. pFree->ulMemSig = RT_FREE_SIG;
  225. pFree->ulAllocFileSig = pwaAlloc->ulFileSig;
  226. pFree->ulAllocLineNumber = pwaAlloc->ulLineNumber;
  227. pFree->ulFreeFileSig = ulFileSig;
  228. pFree->ulFreeLineNumber = ulLineNumber;
  229. pFree->ulStartAddr = (ULONG_PTR) (pwaAlloc->pucData);
  230. pFree->ulSize = pwaAlloc->ulSize;
  231. pwaAlloc->ulMemSig = RT_FREE_SIG;
  232. pwaAlloc->ulFileSig = ulFileSig;
  233. pwaAlloc->ulLineNumber = ulLineNumber;
  234. ExFreePool(pwaAlloc);
  235. InsertTailList(&g_leFreeMemListHead,
  236. &(pFree->leLink));
  237. RtReleaseSpinLock(&(g_rlMemoryLock), kiIrql);
  238. }
  239. VOID
  240. RtAuditMemory()
  241. {
  242. PRT_ALLOCATION pwaAlloc;
  243. PLIST_ENTRY pleNode;
  244. PRT_FREE pFree;
  245. while (!IsListEmpty(&g_leAllocMemListHead)) {
  246. pleNode = RemoveHeadList(&g_leAllocMemListHead);
  247. pwaAlloc = CONTAINING_RECORD(pleNode, RT_ALLOCATION, leLink);
  248. if (pwaAlloc->ulMemSig is RT_MEMORY_SIG) {
  249. DbgPrint("RTDBG: Unfreed memory. %d bytes. Pointer 0x%x, File %c%c%c%c, Line %d\n",
  250. pwaAlloc->ulSize,
  251. pwaAlloc->pucData,
  252. PRINT_BYTES(pwaAlloc->ulFileSig),
  253. pwaAlloc->ulLineNumber);
  254. DbgBreakPoint();
  255. ExFreePool(pwaAlloc);
  256. continue;
  257. }
  258. DbgPrint("RTDBG: Allocation with bad signature. Pointer 0x%x\n",
  259. pwaAlloc->pucData);
  260. DbgBreakPoint();
  261. continue;
  262. }
  263. while (!IsListEmpty(&g_leFreeMemListHead)) {
  264. pleNode = RemoveHeadList(&g_leFreeMemListHead);
  265. pFree = CONTAINING_RECORD(pleNode, RT_FREE, leLink);
  266. if (pFree->ulMemSig is RT_FREE_SIG) {
  267. ExFreePool(pFree);
  268. continue;
  269. }
  270. DbgPrint("RTDBG: Freed memory with bad signature.\n");
  271. DbgBreakPoint();
  272. }
  273. }
  274. #endif
  275. #if IF_REFERENCE_DEBUG
  276. uint
  277. DbgLockedReferenceIF(
  278. IN Interface *RefIF,
  279. IN uchar *File,
  280. IN uint Line
  281. )
  282. /*++
  283. Routine Description:
  284. Increases the reference count of a IF and records a history of who
  285. made the call to reference.
  286. Arguments:
  287. RefIF - The IF to reference.
  288. File - The filename containing the calling fcn (output of the __FILE__ macro).
  289. Line - The line number of the call to this fcn (output of the __LINE__ macro).
  290. Return Value:
  291. Reference count
  292. --*/
  293. {
  294. void *CallersCaller;
  295. IF_REFERENCE_HISTORY *RefHistory;
  296. RefHistory = &RefIF->if_refhistory[RefIF->if_refhistory_index];
  297. RefHistory->File = File;
  298. RefHistory->Line = Line;
  299. RtlGetCallersAddress(&RefHistory->Caller, &CallersCaller);
  300. RefHistory->Count = ++RefIF->if_refcount;
  301. RefIF->if_refhistory_index = ++RefIF->if_refhistory_index % MAX_IFREFERENCE_HISTORY;
  302. return RefIF->if_refcount;
  303. }
  304. uint
  305. DbgDereferenceIF(
  306. IN Interface *DerefIF,
  307. IN uchar *File,
  308. IN uint Line
  309. )
  310. /*++
  311. Routine Description:
  312. Lock, Dereference the interface and records a history of who made the call to dereference.
  313. Arguments:
  314. DerefIF - The IF to dereference.
  315. File - The filename containing the calling fcn (output of the __FILE__ macro).
  316. Line - The line number of the call to this fcn (output of the __LINE__ macro).
  317. Return Value:
  318. Original reference count
  319. --*/
  320. {
  321. void *Caller;
  322. IF_REFERENCE_HISTORY *RefHistory;
  323. CTELockHandle RouteTableHandle;
  324. uint RefCount;
  325. CTEGetLock(&RouteTableLock.Lock, &RouteTableHandle);
  326. RefHistory = &DerefIF->if_refhistory[DerefIF->if_refhistory_index];
  327. RefHistory->File = File;
  328. RefHistory->Line = Line;
  329. RtlGetCallersAddress(&Caller, &RefHistory->Caller);
  330. RefCount = DerefIF->if_refcount;
  331. RefHistory->Count = --DerefIF->if_refcount;
  332. DerefIF->if_refhistory_index = ++DerefIF->if_refhistory_index % MAX_IFREFERENCE_HISTORY;
  333. CTEFreeLock(&RouteTableLock.Lock, RouteTableHandle);
  334. return RefCount;
  335. }
  336. uint
  337. DbgLockedDereferenceIF(
  338. IN Interface *DerefIF,
  339. IN uchar *File,
  340. IN uint Line
  341. )
  342. /*++
  343. Routine Description:
  344. Dereference the interface and records a history of who made the call to dereference.
  345. Arguments:
  346. DerefIF - The IF to dereference.
  347. File - The filename containing the calling fcn (output of the __FILE__ macro).
  348. Line - The line number of the call to this fcn (output of the __LINE__ macro).
  349. Return Value:
  350. Reference count
  351. --*/
  352. {
  353. void *Caller;
  354. IF_REFERENCE_HISTORY *RefHistory;
  355. uint RefCount;
  356. RefHistory = &DerefIF->if_refhistory[DerefIF->if_refhistory_index];
  357. RefHistory->File = File;
  358. RefHistory->Line = Line;
  359. RtlGetCallersAddress(&Caller, &RefHistory->Caller);
  360. RefCount = DerefIF->if_refcount;
  361. RefHistory->Count = --DerefIF->if_refcount;
  362. DerefIF->if_refhistory_index = ++DerefIF->if_refhistory_index % MAX_IFREFERENCE_HISTORY;
  363. return RefCount;
  364. }
  365. #endif