tgt_active.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. /*
  2. * Wine debugger - back-end for an active target
  3. *
  4. * Copyright 2000-2006 Eric Pouech
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <stdarg.h>
  25. #include "debugger.h"
  26. #include "psapi.h"
  27. #include "resource.h"
  28. #include "winternl.h"
  29. #include "wine/debug.h"
  30. #include "wine/exception.h"
  31. #include "wine/unicode.h"
  32. WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
  33. static char* dbg_last_cmd_line;
  34. static struct be_process_io be_process_active_io;
  35. static void dbg_init_current_process(void)
  36. {
  37. }
  38. static void dbg_init_current_thread(void* start)
  39. {
  40. if (start)
  41. {
  42. if (list_count(&dbg_curr_process->threads) == 1 /* first thread ? */ &&
  43. DBG_IVAR(BreakAllThreadsStartup))
  44. {
  45. ADDRESS64 addr;
  46. break_set_xpoints(FALSE);
  47. addr.Mode = AddrModeFlat;
  48. addr.Offset = (DWORD_PTR)start;
  49. break_add_break(&addr, TRUE, TRUE);
  50. break_set_xpoints(TRUE);
  51. }
  52. }
  53. }
  54. static unsigned dbg_handle_debug_event(DEBUG_EVENT* de);
  55. /******************************************************************
  56. * dbg_attach_debuggee
  57. *
  58. * Sets the debuggee to <pid>
  59. * cofe instructs winedbg what to do when first exception is received
  60. * (break=FALSE, continue=TRUE)
  61. * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events
  62. * until the first exception is received (aka: attach to an already running process)
  63. */
  64. BOOL dbg_attach_debuggee(DWORD pid)
  65. {
  66. if (!(dbg_curr_process = dbg_add_process(&be_process_active_io, pid, 0))) return FALSE;
  67. if (!DebugActiveProcess(pid))
  68. {
  69. dbg_printf("Can't attach process %04x: error %u\n", pid, GetLastError());
  70. dbg_del_process(dbg_curr_process);
  71. return FALSE;
  72. }
  73. SetEnvironmentVariableA("DBGHELP_NOLIVE", NULL);
  74. dbg_curr_process->active_debuggee = TRUE;
  75. return TRUE;
  76. }
  77. static unsigned dbg_fetch_context(void)
  78. {
  79. if (!dbg_curr_process->be_cpu->get_context(dbg_curr_thread->handle, &dbg_context))
  80. {
  81. WINE_WARN("Can't get thread's context\n");
  82. return FALSE;
  83. }
  84. return TRUE;
  85. }
  86. BOOL dbg_set_curr_thread(DWORD tid)
  87. {
  88. struct dbg_thread* thread;
  89. if (!dbg_curr_process)
  90. {
  91. dbg_printf("No process loaded\n");
  92. return FALSE;
  93. }
  94. thread = dbg_get_thread(dbg_curr_process, tid);
  95. if (thread)
  96. {
  97. dbg_curr_thread = thread;
  98. dbg_fetch_context();
  99. stack_fetch_frames(&dbg_context);
  100. dbg_curr_tid = tid;
  101. return TRUE;
  102. }
  103. dbg_printf("No such thread\n");
  104. return thread != NULL;
  105. }
  106. /***********************************************************************
  107. * dbg_exception_prolog
  108. *
  109. * Examine exception and decide if interactive mode is entered(return TRUE)
  110. * or exception is silently continued(return FALSE)
  111. * is_debug means the exception is a breakpoint or single step exception
  112. */
  113. static BOOL dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
  114. {
  115. ADDRESS64 addr;
  116. BOOL is_break;
  117. memory_get_current_pc(&addr);
  118. break_suspend_execution();
  119. /* this will resynchronize builtin dbghelp's internal ELF module list */
  120. SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0);
  121. if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, dbg_curr_thread->first_chance, &is_break);
  122. /*
  123. * Do a quiet backtrace so that we have an idea of what the situation
  124. * is WRT the source files.
  125. */
  126. stack_fetch_frames(&dbg_context);
  127. if (is_debug && !is_break && break_should_continue(&addr, rec->ExceptionCode))
  128. return FALSE;
  129. if (addr.Mode != dbg_curr_thread->addr_mode)
  130. {
  131. const char* name = NULL;
  132. switch (addr.Mode)
  133. {
  134. case AddrMode1616: name = "16 bit"; break;
  135. case AddrMode1632: name = "segmented 32 bit"; break;
  136. case AddrModeReal: name = "vm86"; break;
  137. case AddrModeFlat: name = dbg_curr_process->be_cpu->pointer_size == 4
  138. ? "32 bit" : "64 bit"; break;
  139. }
  140. dbg_printf("In %s mode.\n", name);
  141. dbg_curr_thread->addr_mode = addr.Mode;
  142. }
  143. display_print();
  144. if (!is_debug)
  145. {
  146. /* This is a real crash, dump some info */
  147. dbg_curr_process->be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0);
  148. stack_info(-1);
  149. dbg_curr_process->be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
  150. stack_backtrace(dbg_curr_tid);
  151. }
  152. else
  153. {
  154. static char* last_name;
  155. static char* last_file;
  156. char buffer[sizeof(SYMBOL_INFO) + 256];
  157. SYMBOL_INFO* si = (SYMBOL_INFO*)buffer;
  158. void* lin = memory_to_linear_addr(&addr);
  159. DWORD64 disp64;
  160. IMAGEHLP_LINE64 il;
  161. DWORD disp;
  162. si->SizeOfStruct = sizeof(*si);
  163. si->MaxNameLen = 256;
  164. il.SizeOfStruct = sizeof(il);
  165. if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) &&
  166. SymGetLineFromAddr64(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il))
  167. {
  168. if ((!last_name || strcmp(last_name, si->Name)) ||
  169. (!last_file || strcmp(last_file, il.FileName)))
  170. {
  171. HeapFree(GetProcessHeap(), 0, last_name);
  172. HeapFree(GetProcessHeap(), 0, last_file);
  173. last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name);
  174. last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName);
  175. dbg_printf("%s () at %s:%u\n", last_name, last_file, il.LineNumber);
  176. }
  177. }
  178. }
  179. if (!is_debug || is_break ||
  180. dbg_curr_thread->exec_mode == dbg_exec_step_over_insn ||
  181. dbg_curr_thread->exec_mode == dbg_exec_step_into_insn)
  182. {
  183. ADDRESS64 tmp = addr;
  184. /* Show where we crashed */
  185. memory_disasm_one_insn(&tmp);
  186. }
  187. source_list_from_addr(&addr, 0);
  188. return TRUE;
  189. }
  190. static void dbg_exception_epilog(void)
  191. {
  192. break_restart_execution(dbg_curr_thread->exec_count);
  193. /*
  194. * This will have gotten absorbed into the breakpoint info
  195. * if it was used. Otherwise it would have been ignored.
  196. * In any case, we don't mess with it any more.
  197. */
  198. if (dbg_curr_thread->exec_mode == dbg_exec_cont)
  199. dbg_curr_thread->exec_count = 0;
  200. dbg_curr_thread->in_exception = FALSE;
  201. }
  202. static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance)
  203. {
  204. BOOL is_debug = FALSE;
  205. const THREADNAME_INFO* pThreadName;
  206. struct dbg_thread* pThread;
  207. assert(dbg_curr_thread);
  208. WINE_TRACE("exception=%x first_chance=%c\n",
  209. rec->ExceptionCode, first_chance ? 'Y' : 'N');
  210. switch (rec->ExceptionCode)
  211. {
  212. case EXCEPTION_BREAKPOINT:
  213. case EXCEPTION_SINGLE_STEP:
  214. is_debug = TRUE;
  215. break;
  216. case EXCEPTION_WINE_NAME_THREAD:
  217. pThreadName = (const THREADNAME_INFO*)(rec->ExceptionInformation);
  218. if (pThreadName->dwThreadID == -1)
  219. pThread = dbg_curr_thread;
  220. else
  221. pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID);
  222. if(!pThread)
  223. {
  224. dbg_printf("Thread ID=%04x not in our list of threads -> can't rename\n", pThreadName->dwThreadID);
  225. return DBG_CONTINUE;
  226. }
  227. if (dbg_read_memory(pThreadName->szName, pThread->name, 9))
  228. dbg_printf("Thread ID=%04x renamed using MS VC6 extension (name==\"%.9s\")\n",
  229. pThread->tid, pThread->name);
  230. return DBG_CONTINUE;
  231. case EXCEPTION_INVALID_HANDLE:
  232. return DBG_CONTINUE;
  233. }
  234. if (first_chance && !is_debug && !DBG_IVAR(BreakOnFirstChance) &&
  235. !(rec->ExceptionFlags & EH_STACK_INVALID))
  236. {
  237. /* pass exception to program except for debug exceptions */
  238. return DBG_EXCEPTION_NOT_HANDLED;
  239. }
  240. dbg_curr_thread->excpt_record = *rec;
  241. dbg_curr_thread->in_exception = TRUE;
  242. dbg_curr_thread->first_chance = first_chance;
  243. if (!is_debug) info_win32_exception();
  244. if (rec->ExceptionCode == STATUS_POSSIBLE_DEADLOCK && !DBG_IVAR(BreakOnCritSectTimeOut))
  245. {
  246. dbg_curr_thread->in_exception = FALSE;
  247. return DBG_EXCEPTION_NOT_HANDLED;
  248. }
  249. if (dbg_exception_prolog(is_debug, rec))
  250. {
  251. dbg_interactiveP = TRUE;
  252. return 0;
  253. }
  254. dbg_exception_epilog();
  255. return DBG_CONTINUE;
  256. }
  257. static BOOL tgt_process_active_close_process(struct dbg_process* pcs, BOOL kill);
  258. static void fetch_module_name(void* name_addr, BOOL unicode, void* mod_addr,
  259. WCHAR* buffer, size_t bufsz, BOOL is_pcs)
  260. {
  261. static const WCHAR pcspid[] = {'P','r','o','c','e','s','s','_','%','0','8','x',0};
  262. static const WCHAR dlladdr[] = {'D','L','L','_','%','0','8','l','x',0};
  263. memory_get_string_indirect(dbg_curr_process, name_addr, unicode, buffer, bufsz);
  264. if (!buffer[0] &&
  265. !GetModuleFileNameExW(dbg_curr_process->handle, mod_addr, buffer, bufsz))
  266. {
  267. if (is_pcs)
  268. {
  269. HMODULE h;
  270. WORD (WINAPI *gpif)(HANDLE, LPWSTR, DWORD);
  271. /* On Windows, when we get the process creation debug event for a process
  272. * created by winedbg, the modules' list is not initialized yet. Hence,
  273. * GetModuleFileNameExA (on the main module) will generate an error.
  274. * Psapi (starting on XP) provides GetProcessImageFileName() which should
  275. * give us the expected result
  276. */
  277. if (!(h = GetModuleHandleA("psapi")) ||
  278. !(gpif = (void*)GetProcAddress(h, "GetProcessImageFileNameW")) ||
  279. !(gpif)(dbg_curr_process->handle, buffer, bufsz))
  280. snprintfW(buffer, bufsz, pcspid, dbg_curr_pid);
  281. }
  282. else
  283. snprintfW(buffer, bufsz, dlladdr, (ULONG_PTR)mod_addr);
  284. }
  285. }
  286. static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
  287. {
  288. union {
  289. char bufferA[256];
  290. WCHAR buffer[256];
  291. } u;
  292. DWORD cont = DBG_CONTINUE;
  293. dbg_curr_pid = de->dwProcessId;
  294. dbg_curr_tid = de->dwThreadId;
  295. if ((dbg_curr_process = dbg_get_process(de->dwProcessId)) != NULL)
  296. dbg_curr_thread = dbg_get_thread(dbg_curr_process, de->dwThreadId);
  297. else
  298. dbg_curr_thread = NULL;
  299. switch (de->dwDebugEventCode)
  300. {
  301. case EXCEPTION_DEBUG_EVENT:
  302. if (!dbg_curr_thread)
  303. {
  304. WINE_ERR("%04x:%04x: not a registered process or thread (perhaps a 16 bit one ?)\n",
  305. de->dwProcessId, de->dwThreadId);
  306. break;
  307. }
  308. WINE_TRACE("%04x:%04x: exception code=%08x\n",
  309. de->dwProcessId, de->dwThreadId,
  310. de->u.Exception.ExceptionRecord.ExceptionCode);
  311. if (dbg_curr_process->event_on_first_exception)
  312. {
  313. SetEvent(dbg_curr_process->event_on_first_exception);
  314. CloseHandle(dbg_curr_process->event_on_first_exception);
  315. dbg_curr_process->event_on_first_exception = NULL;
  316. if (!DBG_IVAR(BreakOnAttach)) break;
  317. }
  318. if (dbg_fetch_context())
  319. {
  320. cont = dbg_handle_exception(&de->u.Exception.ExceptionRecord,
  321. de->u.Exception.dwFirstChance);
  322. if (cont && dbg_curr_thread)
  323. {
  324. dbg_curr_process->be_cpu->set_context(dbg_curr_thread->handle, &dbg_context);
  325. }
  326. }
  327. break;
  328. case CREATE_PROCESS_DEBUG_EVENT:
  329. dbg_curr_process = dbg_add_process(&be_process_active_io, de->dwProcessId,
  330. de->u.CreateProcessInfo.hProcess);
  331. if (dbg_curr_process == NULL)
  332. {
  333. WINE_ERR("Couldn't create process\n");
  334. break;
  335. }
  336. fetch_module_name(de->u.CreateProcessInfo.lpImageName,
  337. de->u.CreateProcessInfo.fUnicode,
  338. de->u.CreateProcessInfo.lpBaseOfImage,
  339. u.buffer, ARRAY_SIZE(u.buffer), TRUE);
  340. WINE_TRACE("%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
  341. de->dwProcessId, de->dwThreadId,
  342. wine_dbgstr_w(u.buffer),
  343. de->u.CreateProcessInfo.lpImageName,
  344. de->u.CreateProcessInfo.lpStartAddress,
  345. de->u.CreateProcessInfo.dwDebugInfoFileOffset,
  346. de->u.CreateProcessInfo.nDebugInfoSize);
  347. dbg_set_process_name(dbg_curr_process, u.buffer);
  348. if (!dbg_init(dbg_curr_process->handle, u.buffer, FALSE))
  349. dbg_printf("Couldn't initiate DbgHelp\n");
  350. if (!dbg_load_module(dbg_curr_process->handle, de->u.CreateProcessInfo.hFile, u.buffer,
  351. (DWORD_PTR)de->u.CreateProcessInfo.lpBaseOfImage, 0))
  352. dbg_printf("couldn't load main module (%u)\n", GetLastError());
  353. WINE_TRACE("%04x:%04x: create thread I @%p\n",
  354. de->dwProcessId, de->dwThreadId, de->u.CreateProcessInfo.lpStartAddress);
  355. dbg_curr_thread = dbg_add_thread(dbg_curr_process,
  356. de->dwThreadId,
  357. de->u.CreateProcessInfo.hThread,
  358. de->u.CreateProcessInfo.lpThreadLocalBase);
  359. if (!dbg_curr_thread)
  360. {
  361. WINE_ERR("Couldn't create thread\n");
  362. break;
  363. }
  364. dbg_init_current_process();
  365. dbg_init_current_thread(de->u.CreateProcessInfo.lpStartAddress);
  366. break;
  367. case EXIT_PROCESS_DEBUG_EVENT:
  368. WINE_TRACE("%04x:%04x: exit process (%d)\n",
  369. de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
  370. if (dbg_curr_process == NULL)
  371. {
  372. WINE_ERR("Unknown process\n");
  373. break;
  374. }
  375. tgt_process_active_close_process(dbg_curr_process, FALSE);
  376. dbg_printf("Process of pid=%04x has terminated\n", de->dwProcessId);
  377. break;
  378. case CREATE_THREAD_DEBUG_EVENT:
  379. WINE_TRACE("%04x:%04x: create thread D @%p\n",
  380. de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
  381. if (dbg_curr_process == NULL)
  382. {
  383. WINE_ERR("Unknown process\n");
  384. break;
  385. }
  386. if (dbg_get_thread(dbg_curr_process, de->dwThreadId) != NULL)
  387. {
  388. WINE_TRACE("Thread already listed, skipping\n");
  389. break;
  390. }
  391. dbg_curr_thread = dbg_add_thread(dbg_curr_process,
  392. de->dwThreadId,
  393. de->u.CreateThread.hThread,
  394. de->u.CreateThread.lpThreadLocalBase);
  395. if (!dbg_curr_thread)
  396. {
  397. WINE_ERR("Couldn't create thread\n");
  398. break;
  399. }
  400. dbg_init_current_thread(de->u.CreateThread.lpStartAddress);
  401. break;
  402. case EXIT_THREAD_DEBUG_EVENT:
  403. WINE_TRACE("%04x:%04x: exit thread (%d)\n",
  404. de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
  405. if (dbg_curr_thread == NULL)
  406. {
  407. WINE_ERR("Unknown thread\n");
  408. break;
  409. }
  410. /* FIXME: remove break point set on thread startup */
  411. dbg_del_thread(dbg_curr_thread);
  412. break;
  413. case LOAD_DLL_DEBUG_EVENT:
  414. if (dbg_curr_thread == NULL)
  415. {
  416. WINE_ERR("Unknown thread\n");
  417. break;
  418. }
  419. fetch_module_name(de->u.LoadDll.lpImageName,
  420. de->u.LoadDll.fUnicode,
  421. de->u.LoadDll.lpBaseOfDll,
  422. u.buffer, ARRAY_SIZE(u.buffer), FALSE);
  423. WINE_TRACE("%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
  424. de->dwProcessId, de->dwThreadId,
  425. wine_dbgstr_w(u.buffer), de->u.LoadDll.lpBaseOfDll,
  426. de->u.LoadDll.dwDebugInfoFileOffset,
  427. de->u.LoadDll.nDebugInfoSize);
  428. dbg_load_module(dbg_curr_process->handle, de->u.LoadDll.hFile, u.buffer,
  429. (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
  430. break_set_xpoints(FALSE);
  431. break_check_delayed_bp();
  432. break_set_xpoints(TRUE);
  433. if (DBG_IVAR(BreakOnDllLoad))
  434. {
  435. dbg_printf("Stopping on DLL %s loading at %p\n",
  436. dbg_W2A(u.buffer, -1), de->u.LoadDll.lpBaseOfDll);
  437. if (dbg_fetch_context()) cont = 0;
  438. }
  439. break;
  440. case UNLOAD_DLL_DEBUG_EVENT:
  441. WINE_TRACE("%04x:%04x: unload DLL @%p\n",
  442. de->dwProcessId, de->dwThreadId,
  443. de->u.UnloadDll.lpBaseOfDll);
  444. break_delete_xpoints_from_module((DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
  445. SymUnloadModule64(dbg_curr_process->handle, (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
  446. break;
  447. case OUTPUT_DEBUG_STRING_EVENT:
  448. if (dbg_curr_thread == NULL)
  449. {
  450. WINE_ERR("Unknown thread\n");
  451. break;
  452. }
  453. memory_get_string(dbg_curr_process,
  454. de->u.DebugString.lpDebugStringData, TRUE,
  455. de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
  456. WINE_TRACE("%04x:%04x: output debug string (%s)\n",
  457. de->dwProcessId, de->dwThreadId, u.bufferA);
  458. break;
  459. case RIP_EVENT:
  460. WINE_TRACE("%04x:%04x: rip error=%u type=%u\n",
  461. de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
  462. de->u.RipInfo.dwType);
  463. break;
  464. default:
  465. WINE_TRACE("%04x:%04x: unknown event (%x)\n",
  466. de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
  467. }
  468. if (!cont) return TRUE; /* stop execution */
  469. ContinueDebugEvent(de->dwProcessId, de->dwThreadId, cont);
  470. return FALSE; /* continue execution */
  471. }
  472. static void dbg_resume_debuggee(DWORD cont)
  473. {
  474. if (dbg_curr_thread->in_exception)
  475. {
  476. ADDRESS64 addr;
  477. char hexbuf[MAX_OFFSET_TO_STR_LEN];
  478. dbg_exception_epilog();
  479. memory_get_current_pc(&addr);
  480. WINE_TRACE("Exiting debugger PC=%s mode=%d count=%d\n",
  481. memory_offset_to_string(hexbuf, addr.Offset, 0),
  482. dbg_curr_thread->exec_mode,
  483. dbg_curr_thread->exec_count);
  484. if (dbg_curr_thread)
  485. {
  486. if (!dbg_curr_process->be_cpu->set_context(dbg_curr_thread->handle, &dbg_context))
  487. dbg_printf("Cannot set ctx on %04lx\n", dbg_curr_tid);
  488. }
  489. }
  490. dbg_interactiveP = FALSE;
  491. if (!ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, cont))
  492. dbg_printf("Cannot continue on %04lx (%08x)\n", dbg_curr_tid, cont);
  493. }
  494. static void wait_exception(void)
  495. {
  496. DEBUG_EVENT de;
  497. while (dbg_num_processes() && WaitForDebugEvent(&de, INFINITE))
  498. {
  499. if (dbg_handle_debug_event(&de)) break;
  500. }
  501. dbg_interactiveP = TRUE;
  502. }
  503. void dbg_wait_next_exception(DWORD cont, int count, int mode)
  504. {
  505. ADDRESS64 addr;
  506. char hexbuf[MAX_OFFSET_TO_STR_LEN];
  507. if (cont == DBG_CONTINUE)
  508. {
  509. dbg_curr_thread->exec_count = count;
  510. dbg_curr_thread->exec_mode = mode;
  511. }
  512. dbg_resume_debuggee(cont);
  513. wait_exception();
  514. if (!dbg_curr_process) return;
  515. memory_get_current_pc(&addr);
  516. WINE_TRACE("Entering debugger PC=%s mode=%d count=%d\n",
  517. memory_offset_to_string(hexbuf, addr.Offset, 0),
  518. dbg_curr_thread->exec_mode,
  519. dbg_curr_thread->exec_count);
  520. }
  521. void dbg_active_wait_for_first_exception(void)
  522. {
  523. dbg_interactiveP = FALSE;
  524. /* wait for first exception */
  525. wait_exception();
  526. }
  527. static BOOL dbg_start_debuggee(LPSTR cmdLine)
  528. {
  529. PROCESS_INFORMATION info;
  530. STARTUPINFOA startup, current;
  531. DWORD flags;
  532. GetStartupInfoA(&current);
  533. memset(&startup, 0, sizeof(startup));
  534. startup.cb = sizeof(startup);
  535. startup.dwFlags = STARTF_USESHOWWINDOW;
  536. startup.wShowWindow = (current.dwFlags & STARTF_USESHOWWINDOW) ?
  537. current.wShowWindow : SW_SHOWNORMAL;
  538. /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUIs need it
  539. * while GUIs don't
  540. */
  541. flags = DEBUG_PROCESS | CREATE_NEW_CONSOLE;
  542. if (!DBG_IVAR(AlsoDebugProcChild)) flags |= DEBUG_ONLY_THIS_PROCESS;
  543. if (!CreateProcessA(NULL, cmdLine, NULL, NULL, FALSE, flags,
  544. NULL, NULL, &startup, &info))
  545. {
  546. dbg_printf("Couldn't start process '%s'\n", cmdLine);
  547. return FALSE;
  548. }
  549. if (!info.dwProcessId)
  550. {
  551. /* this happens when the program being run is not a Wine binary
  552. * (for example, a shell wrapper around a WineLib app)
  553. */
  554. /* Current fix: list running processes and let the user attach
  555. * to one of them (sic)
  556. * FIXME: implement a real fix => grab the process (from the
  557. * running processes) from its name
  558. */
  559. dbg_printf("Debuggee has been started (%s)\n"
  560. "But WineDbg isn't attached to it. Maybe you're trying to debug a winelib wrapper ??\n"
  561. "Try to attach to one of those processes:\n", cmdLine);
  562. /* FIXME: (HACK) we need some time before the wrapper executes the winelib app */
  563. Sleep(100);
  564. info_win32_processes();
  565. return TRUE;
  566. }
  567. dbg_curr_pid = info.dwProcessId;
  568. if (!(dbg_curr_process = dbg_add_process(&be_process_active_io, dbg_curr_pid, 0))) return FALSE;
  569. dbg_curr_process->active_debuggee = TRUE;
  570. return TRUE;
  571. }
  572. void dbg_run_debuggee(const char* args)
  573. {
  574. if (args)
  575. {
  576. WINE_FIXME("Re-running current program with %s as args is broken\n", wine_dbgstr_a(args));
  577. return;
  578. }
  579. else
  580. {
  581. if (!dbg_last_cmd_line)
  582. {
  583. dbg_printf("Cannot find previously used command line.\n");
  584. return;
  585. }
  586. dbg_start_debuggee(dbg_last_cmd_line);
  587. dbg_active_wait_for_first_exception();
  588. source_list_from_addr(NULL, 0);
  589. }
  590. }
  591. static BOOL str2int(const char* str, DWORD_PTR* val)
  592. {
  593. char* ptr;
  594. *val = strtol(str, &ptr, 10);
  595. return str < ptr && !*ptr;
  596. }
  597. static HANDLE create_temp_file(void)
  598. {
  599. static const WCHAR prefixW[] = {'w','d','b',0};
  600. WCHAR path[MAX_PATH], name[MAX_PATH];
  601. if (!GetTempPathW( MAX_PATH, path ) || !GetTempFileNameW( path, prefixW, 0, name ))
  602. return INVALID_HANDLE_VALUE;
  603. return CreateFileW( name, GENERIC_READ|GENERIC_WRITE|DELETE, FILE_SHARE_DELETE,
  604. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0 );
  605. }
  606. static const struct
  607. {
  608. int type;
  609. int platform;
  610. int major;
  611. int minor;
  612. const char *str;
  613. }
  614. version_table[] =
  615. {
  616. { 0, VER_PLATFORM_WIN32s, 2, 0, "2.0" },
  617. { 0, VER_PLATFORM_WIN32s, 3, 0, "3.0" },
  618. { 0, VER_PLATFORM_WIN32s, 3, 10, "3.1" },
  619. { 0, VER_PLATFORM_WIN32_WINDOWS, 4, 0, "95" },
  620. { 0, VER_PLATFORM_WIN32_WINDOWS, 4, 10, "98" },
  621. { 0, VER_PLATFORM_WIN32_WINDOWS, 4, 90, "ME" },
  622. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 3, 51, "NT 3.51" },
  623. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 4, 0, "NT 4.0" },
  624. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 5, 0, "2000" },
  625. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 5, 1, "XP" },
  626. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 5, 2, "XP" },
  627. { VER_NT_SERVER, VER_PLATFORM_WIN32_NT, 5, 2, "Server 2003" },
  628. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 6, 0, "Vista" },
  629. { VER_NT_SERVER, VER_PLATFORM_WIN32_NT, 6, 0, "Server 2008" },
  630. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 6, 1, "7" },
  631. { VER_NT_SERVER, VER_PLATFORM_WIN32_NT, 6, 1, "Server 2008 R2" },
  632. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 6, 2, "8" },
  633. { VER_NT_SERVER, VER_PLATFORM_WIN32_NT, 6, 2, "Server 2012" },
  634. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 6, 3, "8.1" },
  635. { VER_NT_SERVER, VER_PLATFORM_WIN32_NT, 6, 3, "Server 2012 R2" },
  636. { VER_NT_WORKSTATION, VER_PLATFORM_WIN32_NT, 10, 0, "10" },
  637. };
  638. static const char *get_windows_version(void)
  639. {
  640. RTL_OSVERSIONINFOEXW info = { sizeof(RTL_OSVERSIONINFOEXW) };
  641. static char str[64];
  642. int i;
  643. RtlGetVersion( &info );
  644. for (i = 0; i < ARRAY_SIZE(version_table); i++)
  645. {
  646. if (version_table[i].type == info.wProductType &&
  647. version_table[i].platform == info.dwPlatformId &&
  648. version_table[i].major == info.dwMajorVersion &&
  649. version_table[i].minor == info.dwMinorVersion)
  650. {
  651. return version_table[i].str;
  652. }
  653. }
  654. snprintf( str, sizeof(str), "%d.%d (%d)", info.dwMajorVersion,
  655. info.dwMinorVersion, info.wProductType );
  656. return str;
  657. }
  658. static void output_system_info(void)
  659. {
  660. #ifdef __i386__
  661. static const char platform[] = "i386";
  662. #elif defined(__x86_64__)
  663. static const char platform[] = "x86_64";
  664. #elif defined(__arm__)
  665. static const char platform[] = "arm";
  666. #elif defined(__aarch64__)
  667. static const char platform[] = "arm64";
  668. #else
  669. # error CPU unknown
  670. #endif
  671. const char *(CDECL *wine_get_build_id)(void);
  672. void (CDECL *wine_get_host_version)( const char **sysname, const char **release );
  673. BOOL is_wow64;
  674. wine_get_build_id = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_build_id");
  675. wine_get_host_version = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_host_version");
  676. if (!IsWow64Process( dbg_curr_process->handle, &is_wow64 )) is_wow64 = FALSE;
  677. dbg_printf( "System information:\n" );
  678. if (wine_get_build_id) dbg_printf( " Wine build: %s\n", wine_get_build_id() );
  679. dbg_printf( " Platform: %s%s\n", platform, is_wow64 ? " (WOW64)" : "" );
  680. dbg_printf( " Version: Windows %s\n", get_windows_version() );
  681. if (wine_get_host_version)
  682. {
  683. const char *sysname, *release;
  684. wine_get_host_version( &sysname, &release );
  685. dbg_printf( " Host system: %s\n", sysname );
  686. dbg_printf( " Host version: %s\n", release );
  687. }
  688. }
  689. /******************************************************************
  690. * dbg_active_attach
  691. *
  692. * Tries to attach to a running process
  693. * Handles the <pid> or <pid> <evt> forms
  694. */
  695. enum dbg_start dbg_active_attach(int argc, char* argv[])
  696. {
  697. DWORD_PTR pid, evt;
  698. /* try the form <myself> pid */
  699. if (argc == 1 && str2int(argv[0], &pid) && pid != 0)
  700. {
  701. if (!dbg_attach_debuggee(pid))
  702. return start_error_init;
  703. }
  704. /* try the form <myself> pid evt (Win32 JIT debugger) */
  705. else if (argc == 2 && str2int(argv[0], &pid) && pid != 0 &&
  706. str2int(argv[1], &evt) && evt != 0)
  707. {
  708. if (!dbg_attach_debuggee(pid))
  709. {
  710. /* don't care about result */
  711. SetEvent((HANDLE)evt);
  712. return start_error_init;
  713. }
  714. dbg_curr_process->event_on_first_exception = (HANDLE)evt;
  715. }
  716. else return start_error_parse;
  717. dbg_curr_pid = pid;
  718. return start_ok;
  719. }
  720. /******************************************************************
  721. * dbg_active_launch
  722. *
  723. * Launches a debuggee (with its arguments) from argc/argv
  724. */
  725. enum dbg_start dbg_active_launch(int argc, char* argv[])
  726. {
  727. int i, len;
  728. LPSTR cmd_line;
  729. if (argc == 0) return start_error_parse;
  730. if (!(cmd_line = HeapAlloc(GetProcessHeap(), 0, len = 1)))
  731. {
  732. oom_leave:
  733. dbg_printf("Out of memory\n");
  734. return start_error_init;
  735. }
  736. cmd_line[0] = '\0';
  737. for (i = 0; i < argc; i++)
  738. {
  739. len += strlen(argv[i]) + 1;
  740. if (!(cmd_line = HeapReAlloc(GetProcessHeap(), 0, cmd_line, len)))
  741. goto oom_leave;
  742. strcat(cmd_line, argv[i]);
  743. cmd_line[len - 2] = ' ';
  744. cmd_line[len - 1] = '\0';
  745. }
  746. if (!dbg_start_debuggee(cmd_line))
  747. {
  748. HeapFree(GetProcessHeap(), 0, cmd_line);
  749. return start_error_init;
  750. }
  751. HeapFree(GetProcessHeap(), 0, dbg_last_cmd_line);
  752. dbg_last_cmd_line = cmd_line;
  753. return start_ok;
  754. }
  755. /******************************************************************
  756. * dbg_active_auto
  757. *
  758. * Starts (<pid> or <pid> <evt>) in automatic mode
  759. */
  760. enum dbg_start dbg_active_auto(int argc, char* argv[])
  761. {
  762. HANDLE thread = 0, event = 0, input, output = INVALID_HANDLE_VALUE;
  763. enum dbg_start ds = start_error_parse;
  764. DBG_IVAR(BreakOnDllLoad) = 0;
  765. /* auto mode */
  766. argc--; argv++;
  767. ds = dbg_active_attach(argc, argv);
  768. if (ds != start_ok) {
  769. msgbox_res_id(NULL, IDS_INVALID_PARAMS, IDS_AUTO_CAPTION, MB_OK);
  770. return ds;
  771. }
  772. switch (display_crash_dialog())
  773. {
  774. case ID_DEBUG:
  775. AllocConsole();
  776. dbg_init_console();
  777. dbg_start_interactive(INVALID_HANDLE_VALUE);
  778. return start_ok;
  779. case ID_DETAILS:
  780. event = CreateEventW( NULL, TRUE, FALSE, NULL );
  781. if (event) thread = display_crash_details( event );
  782. if (thread) dbg_houtput = output = create_temp_file();
  783. break;
  784. }
  785. input = parser_generate_command_file("echo Modules:", "info share",
  786. "echo Threads:", "info threads", NULL);
  787. if (input == INVALID_HANDLE_VALUE) return start_error_parse;
  788. if (dbg_curr_process->active_debuggee)
  789. dbg_active_wait_for_first_exception();
  790. dbg_interactiveP = TRUE;
  791. parser_handle(input);
  792. output_system_info();
  793. if (output != INVALID_HANDLE_VALUE)
  794. {
  795. SetEvent( event );
  796. WaitForSingleObject( thread, INFINITE );
  797. CloseHandle( output );
  798. CloseHandle( thread );
  799. CloseHandle( event );
  800. }
  801. CloseHandle( input );
  802. dbg_curr_process->process_io->close_process(dbg_curr_process, TRUE);
  803. return start_ok;
  804. }
  805. /******************************************************************
  806. * dbg_active_minidump
  807. *
  808. * Starts (<pid> or <pid> <evt>) in minidump mode
  809. */
  810. enum dbg_start dbg_active_minidump(int argc, char* argv[])
  811. {
  812. HANDLE hFile;
  813. enum dbg_start ds = start_error_parse;
  814. const char* file = NULL;
  815. char tmp[8 + 1 + 2 + MAX_PATH]; /* minidump "<file>" */
  816. dbg_houtput = GetStdHandle(STD_ERROR_HANDLE);
  817. DBG_IVAR(BreakOnDllLoad) = 0;
  818. argc--; argv++;
  819. /* hard stuff now ; we can get things like:
  820. * --minidump <pid> 1 arg
  821. * --minidump <pid> <evt> 2 args
  822. * --minidump <file> <pid> 2 args
  823. * --minidump <file> <pid> <evt> 3 args
  824. */
  825. switch (argc)
  826. {
  827. case 1:
  828. ds = dbg_active_attach(argc, argv);
  829. break;
  830. case 2:
  831. if ((ds = dbg_active_attach(argc, argv)) != start_ok)
  832. {
  833. file = argv[0];
  834. ds = dbg_active_attach(argc - 1, argv + 1);
  835. }
  836. break;
  837. case 3:
  838. file = argv[0];
  839. ds = dbg_active_attach(argc - 1, argv + 1);
  840. break;
  841. default:
  842. return start_error_parse;
  843. }
  844. if (ds != start_ok) return ds;
  845. memcpy(tmp, "minidump \"", 10);
  846. if (!file)
  847. {
  848. char path[MAX_PATH];
  849. GetTempPathA(sizeof(path), path);
  850. GetTempFileNameA(path, "WD", 0, tmp + 10);
  851. }
  852. else strcpy(tmp + 10, file);
  853. strcat(tmp, "\"");
  854. if (!file)
  855. {
  856. /* FIXME: should generate unix name as well */
  857. dbg_printf("Capturing program state in %s\n", tmp + 9);
  858. }
  859. hFile = parser_generate_command_file(tmp, "detach", NULL);
  860. if (hFile == INVALID_HANDLE_VALUE) return start_error_parse;
  861. if (dbg_curr_process->active_debuggee)
  862. dbg_active_wait_for_first_exception();
  863. dbg_interactiveP = TRUE;
  864. parser_handle(hFile);
  865. return start_ok;
  866. }
  867. static BOOL tgt_process_active_close_process(struct dbg_process* pcs, BOOL kill)
  868. {
  869. if (kill)
  870. {
  871. DWORD exit_code = 0;
  872. if (pcs == dbg_curr_process && dbg_curr_thread->in_exception)
  873. exit_code = dbg_curr_thread->excpt_record.ExceptionCode;
  874. TerminateProcess(pcs->handle, exit_code);
  875. }
  876. else if (pcs == dbg_curr_process)
  877. {
  878. /* remove all set breakpoints in debuggee code */
  879. break_set_xpoints(FALSE);
  880. /* needed for single stepping (ugly).
  881. * should this be handled inside the server ???
  882. */
  883. dbg_curr_process->be_cpu->single_step(&dbg_context, FALSE);
  884. if (dbg_curr_thread->in_exception)
  885. {
  886. dbg_curr_process->be_cpu->set_context(dbg_curr_thread->handle, &dbg_context);
  887. ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE);
  888. }
  889. }
  890. if (!kill)
  891. {
  892. if (!DebugActiveProcessStop(pcs->pid)) return FALSE;
  893. }
  894. SymCleanup(pcs->handle);
  895. dbg_del_process(pcs);
  896. return TRUE;
  897. }
  898. static BOOL tgt_process_active_read(HANDLE hProcess, const void* addr,
  899. void* buffer, SIZE_T len, SIZE_T* rlen)
  900. {
  901. return ReadProcessMemory( hProcess, addr, buffer, len, rlen );
  902. }
  903. static BOOL tgt_process_active_write(HANDLE hProcess, void* addr,
  904. const void* buffer, SIZE_T len, SIZE_T* wlen)
  905. {
  906. return WriteProcessMemory( hProcess, addr, buffer, len, wlen );
  907. }
  908. static BOOL tgt_process_active_get_selector(HANDLE hThread, DWORD sel, LDT_ENTRY* le)
  909. {
  910. return GetThreadSelectorEntry( hThread, sel, le );
  911. }
  912. static struct be_process_io be_process_active_io =
  913. {
  914. tgt_process_active_close_process,
  915. tgt_process_active_read,
  916. tgt_process_active_write,
  917. tgt_process_active_get_selector
  918. };