/docs/dox/using_minidump.dox

http://crashrpt.googlecode.com/ · Unknown · 254 lines · 191 code · 63 blank · 0 comment · 0 complexity · e0c782102afdf5e90aa1e7ebb3662663 MD5 · raw file

  1. /*!
  2. \page using_minidump Using Crash Minidump
  3. A crash minidump file (DMP file) contains various information about the state of
  4. the application at the moment of time when it crashed.
  5. Technically, the crash minidump file may contain:
  6. - general system information (OS version, CPU count, etc.);
  7. - blocks of process memory (including values of global variables,
  8. the call stack and local variables for each execution thread);
  9. - the list of loaded and unloaded modules (including their versions
  10. and timestamps).
  11. Minidump size is typically about several tens of kilobytes, but
  12. the actual content of the minidump depends on the minidump type you pass
  13. as the value of the \ref CR_INSTALL_INFO::uMiniDumpType field.
  14. To analyze crash minidump files generated by the CrashRpt library,
  15. you typically open those files in Visual Studio or in WinDbg.
  16. The following two sections of this page describe minidump opening
  17. instructions in details:
  18. - \ref opening_minidump_in_vs
  19. - \ref opening_minidump_in_windbg
  20. \note In order to recover the stack trace from the crash minidump,
  21. you need the debugging symbols (program database, PDB) generated by the
  22. compiler/linker for modules of your application. You may also need the source
  23. code of your application to be able to edit the place in the
  24. code where the crash happened.
  25. \section opening_minidump_in_vs Opening Minidump in Visual Studio
  26. In order to illustrate how to open a minidump file in Visual Studio,
  27. we will use a minidump file created for the <i>WTLDemo.exe</i> demo
  28. application which is distributed with CrashRpt distribution archive.
  29. To create such a minidump, you can follow the steps below:
  30. - Compile (if you haven't yet compiled) the CrashRpt in Release
  31. configuration as described on \ref compiling_crashrpt page.
  32. - Go to the <i>bin</i> directory under the top-level directory of
  33. CrashRpt distribution. You can see that Visual Studio has
  34. created several EXE and DLL binary files (<i>WTLDemo.exe</i>, <i>CrashRptXXXX.dll</i>, etc.)
  35. and PDB files for those binaries (<i>WTLDemo.pdb</i>, <i>CrashRptXXXX.pdb</i>, etc.) The XXXX is the placeholder
  36. for the actual version of CrashRpt library.
  37. - Save the binary files and PDB files to some folder (see also
  38. \ref preparing_to_software_release page for additional information).
  39. Finally, you should have a directory structure like this:
  40. - WTLDemo
  41. - 1.4.1
  42. - WTLDemo.exe
  43. - WTLDemo.pdb
  44. - CrashRpt1401.dll
  45. - CrashRpt1401.pdb
  46. - Save the source code of the WTLDemo application to some directory (we will need it later).
  47. The source code of the WTLDemo app is located inside of <i>\\demos\\WTLDemo</i> subdirectory
  48. under the top-level directory of CrashRpt distribution.
  49. \note If you use SVN or another version control system for
  50. storing your code, you can just mark the revision with
  51. a tag to be able to restore the state of the code at any time.
  52. - Next, go to the <i>bin</i> directory again and run the <i>WTLDemo.exe</i>. When the dialog appears, click the
  53. "Crash" button. When <i>Error Report</i> dialog appears, click the "What does this error report contains?"
  54. link. Then in the <i>Error Report Details</i> dialog, click the "Export..." button to export the error report
  55. files as a ZIP archive. Export your error report to some directory.
  56. - Unzip the error report archive. It contains <i>crashdump.dmp</i> file and several other files.
  57. Now, when you have the <i>crashdump.dmp</i> file, you can open it in Visual Studio. In order to open crash minidump file,
  58. double-click its file name.
  59. \note Alternatively, if you have several versions of Visual Studio installed (for example a
  60. commercial one and an Express edition) right-click the filename and in the context menu select <i>Open With</i>
  61. and then choose what Visual Studio version to use.
  62. A new Visual Studio window appears displaying general information on the <i>crashdump.dmp</i> (see the figure below).
  63. \image html crashdump_sln.png "Visual Studio: crashdump.dmp"
  64. In the Visual Studio window, click the <i>Debug with Native Only</i>
  65. to load the minidump data. When the data has been loaded,
  66. you should be able to see the dialog containing information about the
  67. exception, such as exception address, module name, exception code and
  68. its textual description (see the figure below). Press the 'Break'
  69. button to continue.
  70. \image html vs_unhandled_exception.png "Unhandled Exception Message"
  71. In the <i>Output</i> window, you should be able to see the log of
  72. minidump loading progress. If you do not see the <i>Output window</i>,
  73. open menu <i>View</i> and click the <i>Output</i> menu item.
  74. \image html output_window.png "Output Window"
  75. Now look at the <i>Modules</i> window. If you do not see such a window,
  76. open menu <i>Debug->Windows</i> and select the <i>Modules</i> menu item.
  77. Click the <i>Symbol Status</i> column header twice to sort modules by symbol
  78. load status in descending order. Now you should be able to see what symbols
  79. have beel loaded for <i>WTLDemo.exe</i> and <i>CrashRptXXXX.dll</i> modules.
  80. \image html modules.png "Modules: Symbols load status for each module"
  81. As the debug symbols seem to be loaded successfully for the main modules
  82. of the application, in the code window (see the figure below) you should be able to see the place
  83. in your source code where the exception occurred. We can see that the crash
  84. occurred in file <i>CrashRpt.cpp</i> at line 829 inside of crEmulateCrash()
  85. function because of assigning a null pointer variable with the value 0.
  86. If the reason of the crash is clear, you even can edit the source code
  87. right in place to fix the problem.
  88. \image html code_line.png "Line of the code where exception occurred"
  89. \note If line numbers are not displayed (this is the default), open menu
  90. <i>Tools->Options...</i>, in appeared dialog's tree choose <i>Text Editor->C++</i>,
  91. and then set the check mark in the <i>Line numbers</i> field.
  92. You can see the values of local variables by moving the mouse cursor over the
  93. variable name. The value (if known) is displayed in a tooltip window. Not
  94. all variable's values can be recovered, this depends on the minidump
  95. type you use and on other factors, such as code optimizations.
  96. In order to better understand the reason of the crash, we would like to know
  97. what C++ class or function called the crEmulateCrash() function and for what
  98. purpose. We can do that with the help of the <i>Call stack</i> window
  99. (see the figure below). If the Call stack window is hidden, open menu
  100. <i>Debug->Windows</i> and select the 'Call Stack' menu item.
  101. \image html call_stack.png "Call Stack"
  102. Each line (also called a <i>stack frame</i>) of the stack trace contains
  103. the name of module the code belongs to, the name of symbol (function or
  104. class), offset from beginning of symbol code, source file and line number.
  105. Moving down the stack, we can see that crEmulateCrash() was called by the
  106. <b>CMainDlg::DoCrash()</b> class method, which, in turn was called by
  107. the <b>CMainDlg::OnOK()</b> method as the result of button click.
  108. Typically, the program has several execution threads. You can switch
  109. between threads using the <i>Threads</i> tab and browse the stack for
  110. each thread. We can see that there are two threads in the application:
  111. the main thread and the worker thread. The exception occured
  112. in the main thread, the second thread didn't crash.
  113. \image html threads.png "Threads Window"
  114. Finally, when you have finished with analyzing minidump data, close the Visual Studio window.
  115. \section troubleshooting_pdb Troubleshooting
  116. The case described above is the easiest one, because Visual Studio located
  117. all binaries, PDB files and source files automatically. But in general,
  118. there may be some problems with reading minidumps, when Visual Studio can't locate
  119. those files, or when the timestamps of those files do not match.
  120. In order to locate matching binaries, PDB files and source code files,
  121. Visual Studio uses the absolute paths embedded into the PDB file
  122. at the time of compilation and linking. So, when you do not delete/move/modify
  123. the files you used to build the solution, Visual Studio can locate them
  124. automatically. But, if you delete/move or modify those files, Visual Studio
  125. won't be able to locate them.
  126. In order to illustrate such a case, we will remove the entire <i>bin</i> and <i>\\demos\\WTLDemo</i>
  127. folders containing WTLDemo's source code we used for compilation, together
  128. with resulting binaries and PDB files. Then if we open the minidump file again, in the <i>Modules</i> window
  129. we will see that the symbols could not be loaded (see the figure below).
  130. \image html no_symbols_loaded.png "No Symbols Loaded"
  131. Symbol status for <i>WTLDemo.exe</i>
  132. and <i>CrashRpt1401.dll</i> modules shows that
  133. there were no matching binaries found. In order to fix this, you
  134. should specify symbol search path manually. In the minidump window,
  135. click the <i>Set symbol paths</i> and enter the path to the directory
  136. where your PDB files are located (see the figure below for example).
  137. \image html symbols_load_paths.png "Where to load symbols from"
  138. Now reload the minidump. You can see that the stack trace is now recovered
  139. correctly. But there is still one problem - the correct source code files are not displayed.
  140. In the <i>Call Stack</i> window, double-click the topmost stack frame. A dialog titled 'Find Source: crashrpt.cpp'
  141. will appear. In this dialog, browse to the folder where you saved the source code
  142. and pick the <i>crashrpt.cpp</i> file. Now the correct source file should
  143. be displayed in Visual Studio source code window.
  144. At this point, you should be able to read the minidump correctly.
  145. If the problem remains, follow the instructions below:
  146. - Ensure that correct matching binaries and/or PDB files were
  147. saved after compilation. Ensure you save excatly the same
  148. binaries and PDB files that were generated during the
  149. compilation/linking process. If you rebuild (or partially rebuild)
  150. your solution, you should save those files again.
  151. - If symbols for some modules of your program are loaded,
  152. and you are still unable to read the stack trace, than
  153. there were no debugging symbols generated for the module
  154. where crash had occurred. Check that you set Program Database
  155. (/Zi) compiler flag and Generate Debug Info (/DEBUG) linker flag
  156. for all modules of your application. For additional info, see \ref prgdb.
  157. - If the stack trace is not as accurate as you expect, the reason may be
  158. the code optimizations. It is recommended that you turn the frame pointer
  159. omission (FPO) optimizations off.
  160. \section opening_minidump_in_windbg Opening Minidump in WinDbg
  161. You can use \b WinDbg program from <b>Microsoft Debugging Tools for Windows</b> for opening
  162. crash minidumps. It is freely distributed.
  163. To open the minidump file, launch WinDbg and open the crash
  164. dump by pressing <i>CTRL+D</i> key combination. In the appeared Open File
  165. dialog, pick the <i>crashdump.dmp</i> and press the Open button.
  166. The <i>Command</i> window appears (see the figure below) allowing you to enter commands and
  167. see the output.
  168. \image html dbghelp_open_minidump.png "Opening a crash minidump in WinDbg"
  169. Next, you need to set the symbol path for WinDbg with the \c .sympath command. Switch
  170. to the command window (ALT+1) and enter \c .sympath followed by a space followed by the
  171. semi-colon delimited list of directories to search.
  172. \code
  173. .sympath D:\Projects\symbols\WTLDemo\1.4.1
  174. \endcode
  175. Similarly you need to set the executable and source search paths with the .exepath
  176. and \c .srcpath commands.
  177. \code
  178. .exepath D:\Projects\symbols\WTLDemo\1.4.1
  179. .srcpath D:\Projects\WTLDemo
  180. \endcode
  181. The final step is to change the debugger context to the context record associated
  182. with the exception by entering the \c .ecxr command.
  183. \code
  184. .ecxr
  185. \endcode
  186. If everything is configured correctly, you should now be able to walk the call stack,
  187. see local variables, and loaded modules. You can even have WinDbg highlight the offending
  188. line of code by double clicking the WTLDemo frame in the Call Stack window (ALT+6).
  189. Note: The exact line number may be a little off due to linker optimizations.
  190. <i>Further reading:</i> \ref automating_crash_report_processing.
  191. */