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.

302 lines
9.0 KiB

  1. Title:
  2. C++ Debug Library
  3. Author:
  4. Steve Kiraly (SteveKi)
  5. 6-17-1998
  6. 1-31-1999
  7. 3-03-1999
  8. Purpose:
  9. The purpose of this document is to describe the design and
  10. document features of this debug library. It will in addition outline some
  11. of the basic design premises and include direction on how to extend or
  12. add features to this library.
  13. Description:
  14. Everyone has at one time or another developed there own mini debug messging
  15. class, function or library which usually includes a set of macros that
  16. expand to calls to output strings to the debugger or console in the checked
  17. builds and nothing in the free builds. This debug library offers a similar
  18. feature however grows on this idea to permit sending the output string to one
  19. or many debug devices simultaniously.
  20. Extensions:
  21. All file names have a dbg prefix because I wanted to ensure that it's
  22. obvious these files are debug files and can be ignored in the free
  23. version. If any files are added please stick to the dbg prefix for new
  24. file names. Do not add dependencies to dlls in this library that you would
  25. not normally have clients of this library link to. For example the back
  26. tracing code uses imagehlp.dll it does not implicity link to imagehlp.dll
  27. because this would require the client to link to imagehlp.dll. Sources
  28. files do not have an easy way to conditionally link to certain libraries
  29. in either the checked of free version. As a result clients are then equired to
  30. link to imagehlp.dll in both the checked and free version. If there is a
  31. library that you only need in this library and is not used in the
  32. checked version then lazy load the library, using LoadLibrary().
  33. To Do List:
  34. 1. Add memory leak detection code, both C and C++ allocations.
  35. 2. Add memory debug output device type that is compatible with splx
  36. debug extension.
  37. 3. Add counter to critical section, that will be used to determine if we
  38. are in the critical when the TUnLock class is used.
  39. 4. Add global variable that can be set to indicate that the backtrace
  40. code should reload symbols using a new symbol path specified in the
  41. registry.
  42. 5. Add code for random failed allocations. Requirements include introducing
  43. random program memory allocations using backtraces to preventing duplicate
  44. allocation failures.
  45. 6. Implement the Debug serial terminal. This debug device will allow you to
  46. send output to a remote via a dumb serial terminal.
  47. 7. Create a method to track generic resources for leak detection. The current
  48. thinking is to create a set of macros for tracking and releasing a generic
  49. resource handle. The way this could work is the when a resouce is allocated
  50. it is entered into a mini database along with a backtrace. When the resource
  51. is release it is removed from the mini database. At the end of the program or
  52. in a stratigic checkpoint the resouces that are left in the mini database can
  53. be dump, these are potential resource leaks.
  54. 8. Look at the environment for the symbol path when capturing backtraces.
  55. Example Usage:
  56. -------------------------------------------------------------------------------
  57. 1. Display basic debug messages to the default device, debugger.
  58. //
  59. // Initialize the debug library, this is optional.
  60. //
  61. DBG_INIT();
  62. //
  63. // Open the debug message class, this function does the following.
  64. //
  65. // 1. Seting the module prefix to "DEBUG".
  66. // 2. The default output device will be enabled, i.e. Debugger.
  67. // 3. Trace, warning and error messages will be displayed.
  68. // 4. Error messages will break to the debugger.
  69. //
  70. DBG_OPEN(_T("DEBUG"), DBG_DEFAULT, DBG_TRACE|DBG_WARN|DBG_ERROR, DBG_ERROR);
  71. //
  72. // Call to display a unicode debug message string.
  73. //
  74. DBG_MSG(DBG_TRACE, (_T("Trace testing Param %d String %s\n"), 1, _T("Test")));
  75. //
  76. // Call to display a ansi debug message string.
  77. //
  78. DBG_MSG(DBG_TRACE, ("Trace testing Param %d String %s\n", 1, "Test"));
  79. //
  80. // Close the debug message class, this is optional if you use DBG_RELEASE().
  81. //
  82. DBG_CLOSE();
  83. //
  84. // Release the debug library.
  85. //
  86. DBG_RELEASE();
  87. -------------------------------------------------------------------------------
  88. 2. Dumping trace messages the debugger.
  89. //
  90. // Initialize the debug library, this is optional.
  91. //
  92. DBG_INIT();
  93. //
  94. // Open the message class.
  95. //
  96. DBG_OPEN(_T("TRACE"), DBG_DEFAULT, DBG_TRACE, DBG_NONE);
  97. //
  98. // Display a entry and exit trace message after each scope.
  99. //
  100. //
  101. DBG_TRACE(_T("Test Scope 1"))
  102. {
  103. DBG_TRACE(_T("Test Scope 2"))
  104. }
  105. //
  106. // Release the debug library.
  107. //
  108. DBG_RELEASE();
  109. -------------------------------------------------------------------------------
  110. 3. Log messages to multiple devices, file, debugger.
  111. //
  112. // Initialize the debug library, this is optional.
  113. //
  114. DBG_INIT();
  115. //
  116. // Open the message class.
  117. //
  118. DBG_OPEN(_T("DEBUG"), DBG_DEBUGGER, DBG_TRACE, DBG_NONE);
  119. //
  120. // Declare the debug file device handle.
  121. //
  122. DBG_HANDLE_(hDebugFile);
  123. //
  124. // Attach the messages to file output device.
  125. //
  126. DBG_ATTACH_(hDebugFile, DBG_FILE, _T("output.log"));
  127. //
  128. // Display a message, this message will be sent to both the debugger and the
  129. // output.log file.
  130. //
  131. DBG_MSG(DBG_TRACE, (_T( "Trace testing Param %d String %s\n"), 1, _T("Test")));
  132. //
  133. // Detach the file device from the output stream, this step is optional if you
  134. // use either the DBG_CLOSE or the DBG_RELEASE functions they will release the
  135. // the attached devices.
  136. //
  137. DBG_DETACH_(hDebugFile);
  138. //
  139. // Close the debug message class, this is optional if you use DBG_RELEASE().
  140. //
  141. DBG_CLOSE();
  142. //
  143. // Release the debug library.
  144. //
  145. DBG_RELEASE();
  146. -------------------------------------------------------------------------------
  147. 4. Display message with time stamp and thread id.
  148. //
  149. // Initialize the debug library, this is optional.
  150. //
  151. DBG_INIT();
  152. //
  153. // Open the message class, displaying a thread id and time stamp.
  154. //
  155. DBG_OPEN(_T("DEBUG"), DBG_TRHEADID|DBG_TIMESTAMP|DBG_DEBUGGER, DBG_TRACE, DBG_NONE);
  156. //
  157. // Display trace message.
  158. //
  159. DBG_MSG(DBG_TRACE, (_T("Trace testing Param %d String %s\n"), 1, _T("Test")));
  160. //
  161. // Close the debug message class, this is optional if you use DBG_RELEASE().
  162. //
  163. DBG_CLOSE();
  164. //
  165. // Release the debug library.
  166. //
  167. DBG_RELEASE();
  168. -------------------------------------------------------------------------------
  169. 5. Display message with custom time stamp and thread id formats.
  170. DBG_OPEN(_T("DBG_TIME"), DBG_DEFAULT, DBG_TRACE|DBG_TIMESTAMP|DBG_THREADID, DBG_NONE);
  171. DBG_SET_FIELD_FORMAT(DBG_TIMESTAMP, _T(" Tick Count (%x)"));
  172. DBG_SET_FIELD_FORMAT(DBG_THREADID, _T(" Thread Id = [%d]"));
  173. DBG_MSG(DBG_TRACE, ("Test Message\n"));
  174. DBG_CLOSE();
  175. -------------------------------------------------------------------------------
  176. 6. Capture macros used for capturing stack backtraces.
  177. The symbol path by default will look in .;%_NT_SYMBOL_PATH%;_ALT_SYMBOL_PATH;
  178. if you need to specify an alternate symbol path the debug library will look in
  179. the following registry key for an alternate symbol path.
  180. HKLM\Software\Microsoft\Windows NT\CurrentVersion\PrintSysDebugLibrary
  181. Sympath REG_SZ ="Your own symbol path"
  182. //
  183. // Initialize the debug library, this is optional.
  184. //
  185. DBG_INIT();
  186. DBG_CAPTURE_HANDLE(Capture);
  187. DBG_CAPTURE_OPEN(Capture, _T("nosymbols"), DBG_DEBUGGER, NULL);
  188. DBG_CAPTURE(Capture, 0, ("Ansi %d Multi Thread Test.\n", dwThread));
  189. DBG_CAPTURE_CLOSE(Capture);
  190. //
  191. // Capture stack back traces with symbols and output to debugger.
  192. //
  193. DBG_CAPTURE_HANDLE(Capture);
  194. DBG_CAPTURE_OPEN(Capture, _T("symbols"), DBG_DEBUGGER, NULL);
  195. DBG_CAPTURE(Capture, 0, (_T("Unicode %d Multi Thread Test.\n"), dwThread));
  196. DBG_CAPTURE_CLOSE(Capture);
  197. //
  198. // Capture stack back traces with symbols and output to file "backtrace.log"
  199. //
  200. DBG_CAPTURE_HANDLE(Capture);
  201. DBG_CAPTURE_OPEN(Capture, _T("symbols"), DBG_FILE, _T("backtrace.log"));
  202. DBG_CAPTURE(Capture, 0, (_T("Unicode %d Multi Thread Test.\n"), dwThread));
  203. DBG_CAPTURE_CLOSE(Capture);
  204. //
  205. // Release the debug library.
  206. //
  207. DBG_RELEASE();
  208. -------------------------------------------------------------------------------
  209. 7. Misc assert and macro usage examples.
  210. //
  211. // Some other useful macros.
  212. //
  213. // Call to output a string to the debugger with no formatting.
  214. // The passed string must use the _T() or TEXT() macros and
  215. // have a trailing semicolan;
  216. //
  217. DBG_RAW(_T("Trace message"));
  218. //
  219. // Break to the debugger.
  220. //
  221. DBG_BREAK();
  222. //
  223. // Normal assert message
  224. //
  225. DBG_ASSERT(FALSE);
  226. //
  227. // Assert message with ansi description string
  228. //
  229. DBG_ASSERT_MSG(i==0, ("Null pointer found %s.\n", "Here"));
  230. //
  231. // Assert message with unicode description string
  232. //
  233. DBG_ASSERT_MSG(i==0, (_T("Null pointer found %s.\n"), _T("Here")));