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.

250 lines
4.8 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. reftrace.c
  5. Abstract:
  6. This module implements a reference count tracing facility.
  7. Author:
  8. Keith Moore (keithmo) 01-May-1997
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <pudebug.h>
  16. #include <reftrace.h>
  17. #include <stktrace.h>
  18. PTRACE_LOG
  19. CreateRefTraceLog(
  20. IN LONG LogSize,
  21. IN LONG ExtraBytesInHeader
  22. )
  23. /*++
  24. Routine Description:
  25. Creates a new (empty) ref count trace log buffer.
  26. Arguments:
  27. LogSize - The number of entries in the log.
  28. ExtraBytesInHeader - The number of extra bytes to include in the
  29. log header. This is useful for adding application-specific
  30. data to the log.
  31. Return Value:
  32. PTRACE_LOG - Pointer to the newly created log if successful,
  33. NULL otherwise.
  34. --*/
  35. {
  36. return CreateTraceLog(
  37. LogSize,
  38. ExtraBytesInHeader,
  39. sizeof(REF_TRACE_LOG_ENTRY)
  40. );
  41. } // CreateRefTraceLog
  42. VOID
  43. DestroyRefTraceLog(
  44. IN PTRACE_LOG Log
  45. )
  46. /*++
  47. Routine Description:
  48. Destroys a ref count trace log buffer created with CreateRefTraceLog().
  49. Arguments:
  50. Log - The ref count trace log buffer to destroy.
  51. Return Value:
  52. None.
  53. --*/
  54. {
  55. DestroyTraceLog( Log );
  56. } // DestroyRefTraceLog
  57. //
  58. // N.B. For IISCaptureStackBackTrace() to work properly, the calling function
  59. // *must* be __cdecl, and must have a "normal" stack frame. So, we decorate
  60. // WriteRefTraceLog[Ex]() with the __cdecl modifier and disable the frame
  61. // pointer omission (FPO) optimization.
  62. //
  63. #pragma optimize( "y", off ) // disable frame pointer omission (FPO)
  64. LONG
  65. __cdecl
  66. WriteRefTraceLog(
  67. IN PTRACE_LOG Log,
  68. IN LONG NewRefCount,
  69. IN PVOID Context
  70. )
  71. /*++
  72. Routine Description:
  73. Writes a new entry to the specified ref count trace log. The entry
  74. written contains the updated reference count and a stack backtrace
  75. leading up to the current caller.
  76. Arguments:
  77. Log - The log to write to.
  78. NewRefCount - The updated reference count.
  79. Context - An uninterpreted context to associate with the log entry.
  80. Return Value:
  81. Index of entry in log.
  82. --*/
  83. {
  84. return WriteRefTraceLogEx(
  85. Log,
  86. NewRefCount,
  87. Context,
  88. REF_TRACE_EMPTY_CONTEXT, // suppress use of optional extra contexts
  89. REF_TRACE_EMPTY_CONTEXT,
  90. REF_TRACE_EMPTY_CONTEXT
  91. );
  92. } // WriteRefTraceLog
  93. LONG
  94. __cdecl
  95. WriteRefTraceLogEx(
  96. IN PTRACE_LOG Log,
  97. IN LONG NewRefCount,
  98. IN PVOID Context,
  99. IN PVOID Context1, // optional extra context
  100. IN PVOID Context2, // optional extra context
  101. IN PVOID Context3 // optional extra context
  102. )
  103. /*++
  104. Routine Description:
  105. Writes a new "extended" entry to the specified ref count trace log.
  106. The entry written contains the updated reference count, stack backtrace
  107. leading up to the current caller and extra context information.
  108. Arguments:
  109. Log - The log to write to.
  110. NewRefCount - The updated reference count.
  111. Context - An uninterpreted context to associate with the log entry.
  112. Context1 - An uninterpreted context to associate with the log entry.
  113. Context2 - An uninterpreted context to associate with the log entry.
  114. Context3 - An uninterpreted context to associate with the log entry.
  115. NOTE Context1/2/3 are "optional" in that the caller may suppress
  116. debug display of these values by passing REF_TRACE_EMPTY_CONTEXT
  117. for each of them.
  118. Return Value:
  119. Index of entry in log.
  120. --*/
  121. {
  122. REF_TRACE_LOG_ENTRY entry;
  123. ULONG hash;
  124. DWORD cStackFramesSkipped;
  125. //
  126. // Initialize the entry.
  127. //
  128. RtlZeroMemory(
  129. &entry,
  130. sizeof(entry)
  131. );
  132. //
  133. // Set log entry members.
  134. //
  135. entry.NewRefCount = NewRefCount;
  136. entry.Context = Context;
  137. entry.Thread = GetCurrentThreadId();
  138. entry.Context1 = Context1;
  139. entry.Context2 = Context2;
  140. entry.Context3 = Context3;
  141. //
  142. // Capture the stack backtrace. Normally, we skip two stack frames:
  143. // one for this routine, and one for IISCaptureStackBackTrace() itself.
  144. // For non-Ex callers who come in via WriteRefTraceLog,
  145. // we skip three stack frames.
  146. //
  147. if ( entry.Context1 == REF_TRACE_EMPTY_CONTEXT
  148. && entry.Context2 == REF_TRACE_EMPTY_CONTEXT
  149. && entry.Context3 == REF_TRACE_EMPTY_CONTEXT
  150. ) {
  151. cStackFramesSkipped = 3;
  152. } else {
  153. cStackFramesSkipped = 2;
  154. }
  155. IISCaptureStackBackTrace(
  156. cStackFramesSkipped,
  157. REF_TRACE_LOG_STACK_DEPTH,
  158. entry.Stack,
  159. &hash
  160. );
  161. //
  162. // Write it to the log.
  163. //
  164. return WriteTraceLog(
  165. Log,
  166. &entry
  167. );
  168. } // WriteRefTraceLogEx
  169. #pragma optimize( "", on ) // restore frame pointer omission (FPO)