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.

360 lines
7.1 KiB

  1. // test : test program for multithreaded stack walk
  2. //
  3. #include <stdio.h>
  4. #include <windows.h>
  5. #include <dbghelp.h>
  6. #ifndef _WIN64
  7. CRITICAL_SECTION g_cs;
  8. BOOL CALLBACK cbEnumSym(
  9. PSYMBOL_INFO si,
  10. ULONG size,
  11. PVOID context
  12. )
  13. {
  14. // printf("%s ", si->Name);
  15. return TRUE;
  16. }
  17. BOOL CALLBACK cbEnumMods(
  18. PSTR name,
  19. DWORD64 base,
  20. PVOID context
  21. )
  22. {
  23. HANDLE hp = (HANDLE)context;
  24. SymEnumSymbols(hp, base, "*", cbEnumSym, NULL);
  25. return TRUE;
  26. }
  27. BOOL
  28. cbSymbol(
  29. HANDLE hProcess,
  30. ULONG ActionCode,
  31. ULONG64 CallbackData,
  32. ULONG64 UserContext
  33. )
  34. {
  35. PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl;
  36. PIMAGEHLP_CBA_READ_MEMORY prm;
  37. IMAGEHLP_MODULE64 mi;
  38. PUCHAR p;
  39. ULONG i;
  40. idsl = (PIMAGEHLP_DEFERRED_SYMBOL_LOAD64) CallbackData;
  41. switch ( ActionCode ) {
  42. case CBA_DEBUG_INFO:
  43. printf("%s", (LPSTR)CallbackData);
  44. break;
  45. #if 0
  46. case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
  47. if (fControlC)
  48. {
  49. fControlC = 0;
  50. return TRUE;
  51. }
  52. break;
  53. #endif
  54. case CBA_DEFERRED_SYMBOL_LOAD_START:
  55. printf("loading symbols for %s\n", idsl->FileName);
  56. break;
  57. case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
  58. if (idsl->FileName && *idsl->FileName)
  59. printf( "*** Error: could not load symbols for %s\n", idsl->FileName );
  60. else
  61. printf( "*** Error: could not load symbols [MODNAME UNKNOWN]\n");
  62. break;
  63. case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
  64. printf("loaded symbols for %s\n", idsl->FileName);
  65. SymEnumSymbols(hProcess, idsl->BaseOfImage, "*", cbEnumSym, NULL);
  66. break;
  67. case CBA_SYMBOLS_UNLOADED:
  68. printf("unloaded symbols for %s\n", idsl->FileName);
  69. break;
  70. #if 1
  71. case CBA_READ_MEMORY:
  72. prm = (PIMAGEHLP_CBA_READ_MEMORY)CallbackData;
  73. return ReadProcessMemory(GetCurrentProcess(),
  74. (LPCVOID)prm->addr,
  75. prm->buf,
  76. prm->bytes,
  77. prm->bytesread);
  78. #endif
  79. default:
  80. return FALSE;
  81. }
  82. return FALSE;
  83. }
  84. BOOL CALLBACK
  85. MyReadProcessMemory(
  86. HANDLE hProcess, // handle to the process
  87. DWORD lpBaseAddress, // base of memory area
  88. LPVOID lpBuffer, // data buffer
  89. DWORD nSize, // number of bytes to read
  90. LPDWORD lpNumberOfBytesRead) // number of bytes read
  91. {
  92. DWORD i = 0;
  93. BOOL fRet = FALSE;
  94. if (nSize == 0)
  95. {
  96. fRet = TRUE;
  97. goto Exit;
  98. }
  99. //
  100. // Try to read as much as possible
  101. //
  102. __try
  103. {
  104. for (i = 0; i < nSize; i++)
  105. {
  106. ((PBYTE)lpBuffer)[i] = *((PBYTE)lpBaseAddress + i);
  107. }
  108. }
  109. __except(EXCEPTION_EXECUTE_HANDLER)
  110. {
  111. //
  112. // We have a partial read in this case
  113. //
  114. }
  115. if (lpNumberOfBytesRead)
  116. {
  117. *lpNumberOfBytesRead = i;
  118. }
  119. fRet = (i > 0);
  120. Exit:
  121. return fRet;
  122. }
  123. VOID
  124. GetStack()
  125. {
  126. BOOL fRet = FALSE;
  127. HANDLE hProcess = GetCurrentProcess();
  128. HANDLE hThread = GetCurrentThread();
  129. DWORD dwStackDepth = 0;
  130. DWORD i = 0;
  131. DWORD dwStackAddr[16];
  132. CONTEXT Context;
  133. STACKFRAME StackFrame;
  134. //
  135. // First initialize data used by the
  136. // stack walker
  137. //
  138. ZeroMemory(&Context, sizeof(CONTEXT));
  139. Context.ContextFlags = CONTEXT_FULL;
  140. ZeroMemory(&StackFrame, sizeof(STACKFRAME));
  141. fRet = GetThreadContext(hThread, &Context);
  142. if (!fRet)
  143. {
  144. printf("Could not get the thread context -0x%x\n", GetLastError());
  145. goto Exit;
  146. }
  147. //
  148. // Fill in our stack frame
  149. //
  150. StackFrame.AddrStack.Mode = AddrModeFlat;
  151. StackFrame.AddrFrame.Mode = AddrModeFlat;
  152. StackFrame.AddrPC.Mode = AddrModeFlat;
  153. __asm
  154. {
  155. mov StackFrame.AddrStack.Offset, esp;
  156. mov StackFrame.AddrFrame.Offset, ebp;
  157. mov StackFrame.AddrPC.Offset, offset DummyLabel;
  158. DummyLabel:
  159. }
  160. //
  161. // Start walking the stack.
  162. //
  163. while (dwStackDepth < 16)
  164. {
  165. fRet = StackWalk(
  166. IMAGE_FILE_MACHINE_I386, // MachineType
  167. hProcess, // Current process
  168. hThread, // Current thread
  169. &StackFrame, // StackFrame
  170. &Context, // ContextRecord - can be NULL for x86
  171. &MyReadProcessMemory, // use our own read process memory
  172. &SymFunctionTableAccess, // FunctionTableAccessRoutine
  173. &SymGetModuleBase, // GetModuleBaseRoutine
  174. NULL); // TranslateAddressProc
  175. if (!fRet)
  176. {
  177. break;
  178. }
  179. dwStackAddr[dwStackDepth] = StackFrame.AddrPC.Offset;
  180. dwStackDepth++;
  181. }
  182. EnterCriticalSection(&g_cs);
  183. printf("\nThread: 0x%x\n", GetCurrentThreadId());
  184. for (i = 0; i < dwStackDepth; i++)
  185. {
  186. printf("\t-0x%x\n", dwStackAddr[i]);
  187. }
  188. LeaveCriticalSection(&g_cs);
  189. SymEnumerateModules64(hProcess, cbEnumMods, hProcess);
  190. Exit:
  191. fflush(stdout);
  192. return;
  193. }
  194. VOID
  195. Dummy2()
  196. {
  197. ULONG ul = (GetCurrentThreadId() % 2);
  198. if (ul == 0)
  199. {
  200. GetStack();
  201. }
  202. else
  203. return;
  204. }
  205. VOID
  206. Dummy1()
  207. {
  208. ULONG ul = (GetCurrentThreadId() % 5);
  209. if (ul == 0 || ul == 4)
  210. {
  211. Dummy2();
  212. }
  213. else
  214. {
  215. GetStack();
  216. }
  217. GetStack();
  218. }
  219. DWORD WINAPI
  220. DwThreadFn(
  221. LPVOID pvParam)
  222. {
  223. ULONG ul = (GetCurrentThreadId() % 7);
  224. if (ul == 3 || ul == 1 || ul == 5 || ul == 6)
  225. {
  226. GetStack();
  227. Dummy1();
  228. }
  229. else
  230. {
  231. Dummy2();
  232. }
  233. GetStack();
  234. return 0;
  235. }
  236. #define THREAD_COUNT MAXIMUM_WAIT_OBJECTS
  237. int __cdecl main(int argc, char* argv[])
  238. {
  239. int i = 0;
  240. HANDLE rghThread[THREAD_COUNT] = {0};
  241. InitializeCriticalSection(&g_cs);
  242. #if 0
  243. if (argc < 2 || argv[1] == NULL)
  244. {
  245. printf("usage: s.exe <sympath>\n");
  246. goto Exit;
  247. }
  248. #endif
  249. printf("Starting test!\n");
  250. //
  251. // Initialize the symbols handler
  252. //
  253. SymSetOptions(SymGetOptions() | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES |
  254. SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG);
  255. if (!SymInitialize(
  256. GetCurrentProcess(), // hProcess
  257. NULL, // UserSearchPath
  258. TRUE))
  259. {
  260. printf("Cannot initialize the symbols - 0x%x!\n", GetLastError());
  261. goto Exit;
  262. }
  263. SymRegisterCallback64(GetCurrentProcess(), cbSymbol, 0);
  264. printf("Creating %u threads!\n", THREAD_COUNT);
  265. for (i = 0; i < THREAD_COUNT; i++)
  266. {
  267. rghThread[i] = CreateThread(
  268. NULL,
  269. 0,
  270. &DwThreadFn,
  271. NULL,
  272. CREATE_SUSPENDED,
  273. NULL);
  274. if (!rghThread[i])
  275. {
  276. printf("Cannot create thread - 0x%x", GetLastError());
  277. }
  278. else printf("Created thread %x\n", rghThread[i]);
  279. }
  280. //
  281. // Now resume all threads
  282. //
  283. for (i = 0; i < THREAD_COUNT; i++)
  284. {
  285. ResumeThread(rghThread[i]);
  286. }
  287. //
  288. // Wait for the threads to finish
  289. //
  290. WaitForMultipleObjects(THREAD_COUNT, rghThread, TRUE, INFINITE);
  291. for (i = 0; i < THREAD_COUNT; i++)
  292. {
  293. CloseHandle(rghThread[i]);
  294. }
  295. printf("Test finished!\n");
  296. Exit:
  297. DeleteCriticalSection(&g_cs);
  298. return 0;
  299. }
  300. #else
  301. int __cdecl main(int argc, char* argv[])
  302. {
  303. printf("storm.exe is not implemented for 64 bit platforms.\n");
  304. return 0;
  305. }
  306. #endif // #ifndef _WIN64