Leaked source code of windows server 2003
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.

295 lines
7.2 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. if (sscanf(*Argv, "%i", &Addr) == EOF)
  100. {
  101. Exit(1, "-a32 illegal argument type\n");
  102. }
  103. g_TraceFrom[i] = (ULONG64)(LONG64)(LONG)Addr;
  104. }
  105. }
  106. else if (!strcmp(*Argv, "-a64"))
  107. {
  108. if (Argc < 4)
  109. {
  110. Exit(1, "-a64 missing arguments\n");
  111. }
  112. for (i = 0; i < 3; i++)
  113. {
  114. Argv++;
  115. Argc--;
  116. if (sscanf(*Argv, "%I64i", &g_TraceFrom[i]) == EOF)
  117. {
  118. Exit(1, "-a64 illegal argument type\n");
  119. }
  120. }
  121. }
  122. else if (!strcmp(*Argv, "-i"))
  123. {
  124. if (Argc < 2)
  125. {
  126. Exit(1, "-i missing argument\n");
  127. }
  128. Argv++;
  129. Argc--;
  130. g_ImagePath = *Argv;
  131. }
  132. else if (!strcmp(*Argv, "-y"))
  133. {
  134. if (Argc < 2)
  135. {
  136. Exit(1, "-y missing argument\n");
  137. }
  138. Argv++;
  139. Argc--;
  140. g_SymbolPath = *Argv;
  141. }
  142. else if (!strcmp(*Argv, "-z"))
  143. {
  144. if (Argc < 2)
  145. {
  146. Exit(1, "-z missing argument\n");
  147. }
  148. Argv++;
  149. Argc--;
  150. g_DumpFile = *Argv;
  151. }
  152. else
  153. {
  154. Exit(1, "Unknown command line argument '%s'\n", *Argv);
  155. }
  156. }
  157. if (g_DumpFile == NULL)
  158. {
  159. Exit(1, "No dump file specified, use -z <file>\n");
  160. }
  161. }
  162. void
  163. ApplyCommandLineArguments(void)
  164. {
  165. HRESULT Status;
  166. // Install output callbacks so we get any output that the
  167. // later calls produce.
  168. if ((Status = g_Client->SetOutputCallbacks(&g_OutputCb)) != S_OK)
  169. {
  170. Exit(1, "SetOutputCallbacks failed, 0x%X\n", Status);
  171. }
  172. if (g_ImagePath != NULL)
  173. {
  174. if ((Status = g_Symbols->SetImagePath(g_ImagePath)) != S_OK)
  175. {
  176. Exit(1, "SetImagePath failed, 0x%X\n", Status);
  177. }
  178. }
  179. if (g_SymbolPath != NULL)
  180. {
  181. if ((Status = g_Symbols->SetSymbolPath(g_SymbolPath)) != S_OK)
  182. {
  183. Exit(1, "SetSymbolPath failed, 0x%X\n", Status);
  184. }
  185. }
  186. // Everything's set up so open the dump file.
  187. if ((Status = g_Client->OpenDumpFile(g_DumpFile)) != S_OK)
  188. {
  189. Exit(1, "OpenDumpFile failed, 0x%X\n", Status);
  190. }
  191. // Finish initialization by waiting for the event that
  192. // caused the dump. This will return immediately as the
  193. // dump file is considered to be at its event.
  194. if ((Status = g_Control->WaitForEvent(DEBUG_WAIT_DEFAULT,
  195. INFINITE)) != S_OK)
  196. {
  197. Exit(1, "WaitForEvent failed, 0x%X\n", Status);
  198. }
  199. // Everything is now initialized and we can make any
  200. // queries we want.
  201. }
  202. void
  203. DumpStack(void)
  204. {
  205. HRESULT Status;
  206. PDEBUG_STACK_FRAME Frames = NULL;
  207. int Count = 50;
  208. printf("\nFirst %d frames of the call stack:\n", Count);
  209. if (g_TraceFrom[0] || g_TraceFrom[1] || g_TraceFrom[2])
  210. {
  211. ULONG Filled;
  212. Frames = new DEBUG_STACK_FRAME[Count];
  213. if (Frames == NULL)
  214. {
  215. Exit(1, "Unable to allocate stack frames\n");
  216. }
  217. if ((Status = g_Control->
  218. GetStackTrace(g_TraceFrom[0], g_TraceFrom[1], g_TraceFrom[2],
  219. Frames, Count, &Filled)) != S_OK)
  220. {
  221. Exit(1, "GetStackTrace failed, 0x%X\n", Status);
  222. }
  223. Count = Filled;
  224. }
  225. // Print the call stack.
  226. if ((Status = g_Control->
  227. OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS, Frames,
  228. Count, DEBUG_STACK_SOURCE_LINE |
  229. DEBUG_STACK_FRAME_ADDRESSES |
  230. DEBUG_STACK_COLUMN_NAMES |
  231. DEBUG_STACK_FRAME_NUMBERS)) != S_OK)
  232. {
  233. Exit(1, "OutputStackTrace failed, 0x%X\n", Status);
  234. }
  235. delete[] Frames;
  236. }
  237. void __cdecl
  238. main(int Argc, char** Argv)
  239. {
  240. CreateInterfaces();
  241. ParseCommandLine(Argc, Argv);
  242. ApplyCommandLineArguments();
  243. DumpStack();
  244. Exit(0, NULL);
  245. }