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.

288 lines
6.7 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Simple example of how to open a dump file and get its stack.
  4. //
  5. // This is not a debugger extension. It is a tool that can be used to replace
  6. // the debugger.
  7. //
  8. //
  9. // Copyright (C) Microsoft Corporation, 2000.
  10. //
  11. //----------------------------------------------------------------------------
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <stdarg.h>
  15. #include <windows.h>
  16. #include <dbgeng.h>
  17. #include "out.hpp"
  18. PSTR g_DumpFile;
  19. PSTR g_ImagePath;
  20. PSTR g_SymbolPath;
  21. ULONG64 g_TraceFrom[3];
  22. IDebugClient* g_Client;
  23. IDebugControl* g_Control;
  24. IDebugSymbols* g_Symbols;
  25. void
  26. Exit(int Code, PCSTR Format, ...)
  27. {
  28. // Clean up any resources.
  29. if (g_Symbols != NULL)
  30. {
  31. g_Symbols->Release();
  32. }
  33. if (g_Control != NULL)
  34. {
  35. g_Control->Release();
  36. }
  37. if (g_Client != NULL)
  38. {
  39. //
  40. // Request a simple end to any current session.
  41. // This may or may not do anything but it isn't
  42. // harmful to call it.
  43. //
  44. // We don't want to see any output from the shutdown.
  45. g_Client->SetOutputCallbacks(NULL);
  46. g_Client->EndSession(DEBUG_END_PASSIVE);
  47. g_Client->Release();
  48. }
  49. // Output an error message if given.
  50. if (Format != NULL)
  51. {
  52. va_list Args;
  53. va_start(Args, Format);
  54. vfprintf(stderr, Format, Args);
  55. va_end(Args);
  56. }
  57. exit(Code);
  58. }
  59. void
  60. CreateInterfaces(void)
  61. {
  62. HRESULT Status;
  63. // Start things off by getting an initial interface from
  64. // the engine. This can be any engine interface but is
  65. // generally IDebugClient as the client interface is
  66. // where sessions are started.
  67. if ((Status = DebugCreate(__uuidof(IDebugClient),
  68. (void**)&g_Client)) != S_OK)
  69. {
  70. Exit(1, "DebugCreate failed, 0x%X\n", Status);
  71. }
  72. // Query for some other interfaces that we'll need.
  73. if ((Status = g_Client->QueryInterface(__uuidof(IDebugControl),
  74. (void**)&g_Control)) != S_OK ||
  75. (Status = g_Client->QueryInterface(__uuidof(IDebugSymbols),
  76. (void**)&g_Symbols)) != S_OK)
  77. {
  78. Exit(1, "QueryInterface failed, 0x%X\n", Status);
  79. }
  80. }
  81. void
  82. ParseCommandLine(int Argc, char** Argv)
  83. {
  84. int i;
  85. while (--Argc > 0)
  86. {
  87. Argv++;
  88. if (!strcmp(*Argv, "-a32"))
  89. {
  90. if (Argc < 4)
  91. {
  92. Exit(1, "-a32 missing arguments\n");
  93. }
  94. for (i = 0; i < 3; i++)
  95. {
  96. int Addr;
  97. Argv++;
  98. Argc--;
  99. sscanf(*Argv, "%i", &Addr);
  100. g_TraceFrom[i] = (ULONG64)(LONG64)(LONG)Addr;
  101. }
  102. }
  103. else if (!strcmp(*Argv, "-a64"))
  104. {
  105. if (Argc < 4)
  106. {
  107. Exit(1, "-a64 missing arguments\n");
  108. }
  109. for (i = 0; i < 3; i++)
  110. {
  111. Argv++;
  112. Argc--;
  113. sscanf(*Argv, "%I64i", &g_TraceFrom[i]);
  114. }
  115. }
  116. else if (!strcmp(*Argv, "-i"))
  117. {
  118. if (Argc < 2)
  119. {
  120. Exit(1, "-i missing argument\n");
  121. }
  122. Argv++;
  123. Argc--;
  124. g_ImagePath = *Argv;
  125. }
  126. else if (!strcmp(*Argv, "-y"))
  127. {
  128. if (Argc < 2)
  129. {
  130. Exit(1, "-y missing argument\n");
  131. }
  132. Argv++;
  133. Argc--;
  134. g_SymbolPath = *Argv;
  135. }
  136. else if (!strcmp(*Argv, "-z"))
  137. {
  138. if (Argc < 2)
  139. {
  140. Exit(1, "-z missing argument\n");
  141. }
  142. Argv++;
  143. Argc--;
  144. g_DumpFile = *Argv;
  145. }
  146. else
  147. {
  148. Exit(1, "Unknown command line argument '%s'\n", *Argv);
  149. }
  150. }
  151. if (g_DumpFile == NULL)
  152. {
  153. Exit(1, "No dump file specified, use -z <file>\n");
  154. }
  155. }
  156. void
  157. ApplyCommandLineArguments(void)
  158. {
  159. HRESULT Status;
  160. // Install output callbacks so we get any output that the
  161. // later calls produce.
  162. if ((Status = g_Client->SetOutputCallbacks(&g_OutputCb)) != S_OK)
  163. {
  164. Exit(1, "SetOutputCallbacks failed, 0x%X\n", Status);
  165. }
  166. if (g_ImagePath != NULL)
  167. {
  168. if ((Status = g_Symbols->SetImagePath(g_ImagePath)) != S_OK)
  169. {
  170. Exit(1, "SetImagePath failed, 0x%X\n", Status);
  171. }
  172. }
  173. if (g_SymbolPath != NULL)
  174. {
  175. if ((Status = g_Symbols->SetSymbolPath(g_SymbolPath)) != S_OK)
  176. {
  177. Exit(1, "SetSymbolPath failed, 0x%X\n", Status);
  178. }
  179. }
  180. // Everything's set up so open the dump file.
  181. if ((Status = g_Client->OpenDumpFile(g_DumpFile)) != S_OK)
  182. {
  183. Exit(1, "OpenDumpFile failed, 0x%X\n", Status);
  184. }
  185. // Finish initialization by waiting for the event that
  186. // caused the dump. This will return immediately as the
  187. // dump file is considered to be at its event.
  188. if ((Status = g_Control->WaitForEvent(DEBUG_WAIT_DEFAULT,
  189. INFINITE)) != S_OK)
  190. {
  191. Exit(1, "WaitForEvent failed, 0x%X\n", Status);
  192. }
  193. // Everything is now initialized and we can make any
  194. // queries we want.
  195. }
  196. void
  197. DumpStack(void)
  198. {
  199. HRESULT Status;
  200. PDEBUG_STACK_FRAME Frames = NULL;
  201. int Count = 50;
  202. printf("\nFirst %d frames of the call stack:\n", Count);
  203. if (g_TraceFrom[0] || g_TraceFrom[1] || g_TraceFrom[2])
  204. {
  205. ULONG Filled;
  206. Frames = new DEBUG_STACK_FRAME[Count];
  207. if (Frames == NULL)
  208. {
  209. Exit(1, "Unable to allocate stack frames\n");
  210. }
  211. if ((Status = g_Control->
  212. GetStackTrace(g_TraceFrom[0], g_TraceFrom[1], g_TraceFrom[2],
  213. Frames, Count, &Filled)) != S_OK)
  214. {
  215. Exit(1, "GetStackTrace failed, 0x%X\n", Status);
  216. }
  217. Count = Filled;
  218. }
  219. // Print the call stack.
  220. if ((Status = g_Control->
  221. OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS, Frames,
  222. Count, DEBUG_STACK_SOURCE_LINE |
  223. DEBUG_STACK_FRAME_ADDRESSES |
  224. DEBUG_STACK_COLUMN_NAMES |
  225. DEBUG_STACK_FRAME_NUMBERS)) != S_OK)
  226. {
  227. Exit(1, "OutputStackTrace failed, 0x%X\n", Status);
  228. }
  229. delete Frames;
  230. }
  231. void __cdecl
  232. main(int Argc, char** Argv)
  233. {
  234. CreateInterfaces();
  235. ParseCommandLine(Argc, Argv);
  236. ApplyCommandLineArguments();
  237. DumpStack();
  238. Exit(0, NULL);
  239. }