winedbg.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. /* Wine internal debugger
  2. * Interface to Windows debugger API
  3. * Copyright 2000-2004 Eric Pouech
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  18. */
  19. #include "config.h"
  20. #include "wine/port.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include "debugger.h"
  25. #include "winternl.h"
  26. #include "wine/exception.h"
  27. #include "wine/debug.h"
  28. /* TODO list:
  29. *
  30. * - minidump
  31. * + ensure that all commands work as expected in minidump reload function
  32. * (and re-enable parser usage)
  33. * - CPU adherence
  34. * + we always assume the stack grows as on i386 (i.e. downwards)
  35. * - UI
  36. * + re-enable the limited output (depth of structure printing and number of
  37. * lines)
  38. * + make the output as close as possible to what gdb does
  39. * - symbol management:
  40. * + symbol table loading is broken
  41. * + in symbol_get_lvalue, we don't do any scoping (as C does) between local and
  42. * global vars (we may need this to force some display for example). A solution
  43. * would be always to return arrays with: local vars, global vars, thunks
  44. * - type management:
  45. * + some bits of internal types are missing (like type casts and the address
  46. * operator)
  47. * + the type for an enum's value is always inferred as int (winedbg & dbghelp)
  48. * + most of the code implies that sizeof(void*) = sizeof(int)
  49. * + all computations should be made on long long
  50. * o expr computations are in int:s
  51. * o bitfield size is on a 4-bytes
  52. * - execution:
  53. * + set a better fix for gdb (proxy mode) than the step-mode hack
  54. * + implement function call in debuggee
  55. * + trampoline management is broken when getting 16 <=> 32 thunk destination
  56. * address
  57. * + thunking of delayed imports doesn't work as expected (ie, when stepping,
  58. * it currently stops at first insn with line number during the library
  59. * loading). We should identify this (__wine_delay_import) and set a
  60. * breakpoint instead of single stepping the library loading.
  61. * + it's wrong to copy thread->step_over_bp into process->bp[0] (when
  62. * we have a multi-thread debuggee). complete fix must include storing all
  63. * thread's step-over bp in process-wide bp array, and not to handle bp
  64. * when we have the wrong thread running into that bp
  65. * + code in CREATE_PROCESS debug event doesn't work on Windows, as we cannot
  66. * get the name of the main module this way. We should rewrite all this code
  67. * and store in struct dbg_process as early as possible (before process
  68. * creation or attachment), the name of the main module
  69. * - global:
  70. * + define a better way to enable the wine extensions (either DBG SDK function
  71. * in dbghelp, or TLS variable, or environment variable or ...)
  72. * + audit all files to ensure that we check all potential return values from
  73. * every function call to catch the errors
  74. * + BTW check also whether the exception mechanism is the best way to return
  75. * errors (or find a proper fix for MinGW port)
  76. */
  77. WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
  78. struct dbg_process* dbg_curr_process = NULL;
  79. struct dbg_thread* dbg_curr_thread = NULL;
  80. DWORD_PTR dbg_curr_tid = 0;
  81. DWORD_PTR dbg_curr_pid = 0;
  82. dbg_ctx_t dbg_context;
  83. BOOL dbg_interactiveP = FALSE;
  84. HANDLE dbg_houtput = 0;
  85. static struct list dbg_process_list = LIST_INIT(dbg_process_list);
  86. struct dbg_internal_var dbg_internal_vars[DBG_IV_LAST];
  87. static void dbg_outputA(const char* buffer, int len)
  88. {
  89. static char line_buff[4096];
  90. static unsigned int line_pos;
  91. DWORD w, i;
  92. while (len > 0)
  93. {
  94. unsigned int count = min( len, sizeof(line_buff) - line_pos );
  95. memcpy( line_buff + line_pos, buffer, count );
  96. buffer += count;
  97. len -= count;
  98. line_pos += count;
  99. for (i = line_pos; i > 0; i--) if (line_buff[i-1] == '\n') break;
  100. if (!i) /* no newline found */
  101. {
  102. if (len > 0) i = line_pos; /* buffer is full, flush anyway */
  103. else break;
  104. }
  105. WriteFile(dbg_houtput, line_buff, i, &w, NULL);
  106. memmove( line_buff, line_buff + i, line_pos - i );
  107. line_pos -= i;
  108. }
  109. }
  110. const char* dbg_W2A(const WCHAR* buffer, unsigned len)
  111. {
  112. static unsigned ansilen;
  113. static char* ansi;
  114. unsigned newlen;
  115. newlen = WideCharToMultiByte(CP_ACP, 0, buffer, len, NULL, 0, NULL, NULL);
  116. if (newlen > ansilen)
  117. {
  118. static char* newansi;
  119. if (ansi)
  120. newansi = HeapReAlloc(GetProcessHeap(), 0, ansi, newlen);
  121. else
  122. newansi = HeapAlloc(GetProcessHeap(), 0, newlen);
  123. if (!newansi) return NULL;
  124. ansilen = newlen;
  125. ansi = newansi;
  126. }
  127. WideCharToMultiByte(CP_ACP, 0, buffer, len, ansi, newlen, NULL, NULL);
  128. return ansi;
  129. }
  130. void dbg_outputW(const WCHAR* buffer, int len)
  131. {
  132. const char* ansi = dbg_W2A(buffer, len);
  133. if (ansi) dbg_outputA(ansi, strlen(ansi));
  134. /* FIXME: should CP_ACP be GetConsoleCP()? */
  135. }
  136. int dbg_printf(const char* format, ...)
  137. {
  138. static char buf[4*1024];
  139. va_list valist;
  140. int len;
  141. va_start(valist, format);
  142. len = vsnprintf(buf, sizeof(buf), format, valist);
  143. va_end(valist);
  144. if (len <= -1 || len >= sizeof(buf))
  145. {
  146. len = sizeof(buf) - 1;
  147. buf[len] = 0;
  148. buf[len - 1] = buf[len - 2] = buf[len - 3] = '.';
  149. }
  150. dbg_outputA(buf, len);
  151. return len;
  152. }
  153. static unsigned dbg_load_internal_vars(void)
  154. {
  155. HKEY hkey;
  156. DWORD type = REG_DWORD;
  157. DWORD val;
  158. DWORD count = sizeof(val);
  159. int i;
  160. struct dbg_internal_var* div = dbg_internal_vars;
  161. /* initializes internal vars table */
  162. #define INTERNAL_VAR(_var,_val,_ref,_tid) \
  163. div->val = _val; div->name = #_var; div->pval = _ref; \
  164. div->typeid = _tid; div++;
  165. #include "intvar.h"
  166. #undef INTERNAL_VAR
  167. /* @@ Wine registry key: HKCU\Software\Wine\WineDbg */
  168. if (RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey))
  169. {
  170. WINE_ERR("Cannot create WineDbg key in registry\n");
  171. return FALSE;
  172. }
  173. for (i = 0; i < DBG_IV_LAST; i++)
  174. {
  175. if (!dbg_internal_vars[i].pval)
  176. {
  177. if (!RegQueryValueExA(hkey, dbg_internal_vars[i].name, 0,
  178. &type, (LPBYTE)&val, &count))
  179. dbg_internal_vars[i].val = val;
  180. dbg_internal_vars[i].pval = &dbg_internal_vars[i].val;
  181. }
  182. }
  183. RegCloseKey(hkey);
  184. return TRUE;
  185. }
  186. static unsigned dbg_save_internal_vars(void)
  187. {
  188. HKEY hkey;
  189. int i;
  190. /* @@ Wine registry key: HKCU\Software\Wine\WineDbg */
  191. if (RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey))
  192. {
  193. WINE_ERR("Cannot create WineDbg key in registry\n");
  194. return FALSE;
  195. }
  196. for (i = 0; i < DBG_IV_LAST; i++)
  197. {
  198. /* FIXME: type should be inferred from basic type -if any- of intvar */
  199. if (dbg_internal_vars[i].pval == &dbg_internal_vars[i].val)
  200. {
  201. DWORD val = dbg_internal_vars[i].val;
  202. RegSetValueExA(hkey, dbg_internal_vars[i].name, 0, REG_DWORD, (BYTE *)&val, sizeof(val));
  203. }
  204. }
  205. RegCloseKey(hkey);
  206. return TRUE;
  207. }
  208. const struct dbg_internal_var* dbg_get_internal_var(const char* name)
  209. {
  210. const struct dbg_internal_var* div;
  211. for (div = &dbg_internal_vars[DBG_IV_LAST - 1]; div >= dbg_internal_vars; div--)
  212. {
  213. if (!strcmp(div->name, name)) return div;
  214. }
  215. for (div = dbg_curr_process->be_cpu->context_vars; div->name; div++)
  216. {
  217. if (!strcasecmp(div->name, name))
  218. {
  219. struct dbg_internal_var* ret = (void*)lexeme_alloc_size(sizeof(*ret));
  220. /* relocate register's field against current context */
  221. *ret = *div;
  222. ret->pval = (DWORD_PTR*)((char*)&dbg_context + (DWORD_PTR)div->pval);
  223. return ret;
  224. }
  225. }
  226. return NULL;
  227. }
  228. unsigned dbg_num_processes(void)
  229. {
  230. return list_count(&dbg_process_list);
  231. }
  232. struct dbg_process* dbg_get_process(DWORD pid)
  233. {
  234. struct dbg_process* p;
  235. LIST_FOR_EACH_ENTRY(p, &dbg_process_list, struct dbg_process, entry)
  236. if (p->pid == pid) return p;
  237. return NULL;
  238. }
  239. struct dbg_process* dbg_get_process_h(HANDLE h)
  240. {
  241. struct dbg_process* p;
  242. LIST_FOR_EACH_ENTRY(p, &dbg_process_list, struct dbg_process, entry)
  243. if (p->handle == h) return p;
  244. return NULL;
  245. }
  246. #ifdef __i386__
  247. extern struct backend_cpu be_i386;
  248. #elif defined(__x86_64__)
  249. extern struct backend_cpu be_i386;
  250. extern struct backend_cpu be_x86_64;
  251. #elif defined(__arm__) && !defined(__ARMEB__)
  252. extern struct backend_cpu be_arm;
  253. #elif defined(__aarch64__) && !defined(__AARCH64EB__)
  254. extern struct backend_cpu be_arm64;
  255. #else
  256. # error CPU unknown
  257. #endif
  258. struct dbg_process* dbg_add_process(const struct be_process_io* pio, DWORD pid, HANDLE h)
  259. {
  260. struct dbg_process* p;
  261. BOOL wow64;
  262. if ((p = dbg_get_process(pid)))
  263. return p;
  264. if (!h)
  265. h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
  266. if (!(p = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dbg_process)))) return NULL;
  267. p->handle = h;
  268. p->pid = pid;
  269. p->process_io = pio;
  270. p->pio_data = NULL;
  271. p->imageName = NULL;
  272. list_init(&p->threads);
  273. p->event_on_first_exception = NULL;
  274. p->active_debuggee = FALSE;
  275. p->next_bp = 1; /* breakpoint 0 is reserved for step-over */
  276. memset(p->bp, 0, sizeof(p->bp));
  277. p->delayed_bp = NULL;
  278. p->num_delayed_bp = 0;
  279. p->source_ofiles = NULL;
  280. p->search_path = NULL;
  281. p->source_current_file[0] = '\0';
  282. p->source_start_line = -1;
  283. p->source_end_line = -1;
  284. list_add_head(&dbg_process_list, &p->entry);
  285. IsWow64Process(h, &wow64);
  286. #ifdef __i386__
  287. p->be_cpu = &be_i386;
  288. #elif defined(__x86_64__)
  289. p->be_cpu = wow64 ? &be_i386 : &be_x86_64;
  290. #elif defined(__arm__) && !defined(__ARMEB__)
  291. p->be_cpu = &be_arm;
  292. #elif defined(__aarch64__) && !defined(__AARCH64EB__)
  293. p->be_cpu = &be_arm64;
  294. #else
  295. # error CPU unknown
  296. #endif
  297. return p;
  298. }
  299. void dbg_set_process_name(struct dbg_process* p, const WCHAR* imageName)
  300. {
  301. assert(p->imageName == NULL);
  302. if (imageName)
  303. {
  304. WCHAR* tmp = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(imageName) + 1) * sizeof(WCHAR));
  305. if (tmp) p->imageName = lstrcpyW(tmp, imageName);
  306. }
  307. }
  308. void dbg_del_process(struct dbg_process* p)
  309. {
  310. struct dbg_thread* t;
  311. struct dbg_thread* t2;
  312. int i;
  313. LIST_FOR_EACH_ENTRY_SAFE(t, t2, &p->threads, struct dbg_thread, entry)
  314. dbg_del_thread(t);
  315. for (i = 0; i < p->num_delayed_bp; i++)
  316. if (p->delayed_bp[i].is_symbol)
  317. HeapFree(GetProcessHeap(), 0, p->delayed_bp[i].u.symbol.name);
  318. HeapFree(GetProcessHeap(), 0, p->delayed_bp);
  319. source_nuke_path(p);
  320. source_free_files(p);
  321. list_remove(&p->entry);
  322. if (p == dbg_curr_process) dbg_curr_process = NULL;
  323. if (p->event_on_first_exception) CloseHandle(p->event_on_first_exception);
  324. HeapFree(GetProcessHeap(), 0, (char*)p->imageName);
  325. HeapFree(GetProcessHeap(), 0, p);
  326. }
  327. /******************************************************************
  328. * dbg_init
  329. *
  330. * Initializes the dbghelp library, and also sets the application directory
  331. * as a place holder for symbol searches.
  332. */
  333. BOOL dbg_init(HANDLE hProc, const WCHAR* in, BOOL invade)
  334. {
  335. BOOL ret;
  336. ret = SymInitialize(hProc, NULL, invade);
  337. if (ret && in)
  338. {
  339. const WCHAR* last;
  340. for (last = in + lstrlenW(in) - 1; last >= in; last--)
  341. {
  342. if (*last == '/' || *last == '\\')
  343. {
  344. WCHAR* tmp;
  345. tmp = HeapAlloc(GetProcessHeap(), 0, (1024 + 1 + (last - in) + 1) * sizeof(WCHAR));
  346. if (tmp && SymGetSearchPathW(hProc, tmp, 1024))
  347. {
  348. WCHAR* x = tmp + lstrlenW(tmp);
  349. *x++ = ';';
  350. memcpy(x, in, (last - in) * sizeof(WCHAR));
  351. x[last - in] = '\0';
  352. ret = SymSetSearchPathW(hProc, tmp);
  353. }
  354. else ret = FALSE;
  355. HeapFree(GetProcessHeap(), 0, tmp);
  356. break;
  357. }
  358. }
  359. }
  360. return ret;
  361. }
  362. struct mod_loader_info
  363. {
  364. HANDLE handle;
  365. IMAGEHLP_MODULE64* imh_mod;
  366. };
  367. static BOOL CALLBACK mod_loader_cb(PCSTR mod_name, DWORD64 base, PVOID ctx)
  368. {
  369. struct mod_loader_info* mli = ctx;
  370. if (!strcmp(mod_name, "<wine-loader>"))
  371. {
  372. if (SymGetModuleInfo64(mli->handle, base, mli->imh_mod))
  373. return FALSE; /* stop enum */
  374. }
  375. return TRUE;
  376. }
  377. BOOL dbg_get_debuggee_info(HANDLE hProcess, IMAGEHLP_MODULE64* imh_mod)
  378. {
  379. struct mod_loader_info mli;
  380. BOOL opt;
  381. /* this will resynchronize builtin dbghelp's internal ELF module list */
  382. SymLoadModule(hProcess, 0, 0, 0, 0, 0);
  383. mli.handle = hProcess;
  384. mli.imh_mod = imh_mod;
  385. imh_mod->SizeOfStruct = sizeof(*imh_mod);
  386. imh_mod->BaseOfImage = 0;
  387. /* this is a wine specific options to return also ELF modules in the
  388. * enumeration
  389. */
  390. opt = SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, TRUE);
  391. SymEnumerateModules64(hProcess, mod_loader_cb, &mli);
  392. SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt);
  393. return imh_mod->BaseOfImage != 0;
  394. }
  395. BOOL dbg_load_module(HANDLE hProc, HANDLE hFile, const WCHAR* name, DWORD_PTR base, DWORD size)
  396. {
  397. BOOL ret = SymLoadModuleExW(hProc, NULL, name, NULL, base, size, NULL, 0);
  398. if (ret)
  399. {
  400. IMAGEHLP_MODULEW64 ihm;
  401. ihm.SizeOfStruct = sizeof(ihm);
  402. if (SymGetModuleInfoW64(hProc, base, &ihm) && (ihm.PdbUnmatched || ihm.DbgUnmatched))
  403. dbg_printf("Loaded unmatched debug information for %s\n", wine_dbgstr_w(name));
  404. }
  405. return ret;
  406. }
  407. struct dbg_thread* dbg_get_thread(struct dbg_process* p, DWORD tid)
  408. {
  409. struct dbg_thread* t;
  410. if (!p) return NULL;
  411. LIST_FOR_EACH_ENTRY(t, &p->threads, struct dbg_thread, entry)
  412. if (t->tid == tid) return t;
  413. return NULL;
  414. }
  415. struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid,
  416. HANDLE h, void* teb)
  417. {
  418. struct dbg_thread* t = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dbg_thread));
  419. if (!t)
  420. return NULL;
  421. t->handle = h;
  422. t->tid = tid;
  423. t->teb = teb;
  424. t->process = p;
  425. t->exec_mode = dbg_exec_cont;
  426. t->exec_count = 0;
  427. t->step_over_bp.enabled = FALSE;
  428. t->step_over_bp.refcount = 0;
  429. t->stopped_xpoint = -1;
  430. t->in_exception = FALSE;
  431. t->frames = NULL;
  432. t->num_frames = 0;
  433. t->curr_frame = -1;
  434. t->addr_mode = AddrModeFlat;
  435. t->suspended = FALSE;
  436. snprintf(t->name, sizeof(t->name), "%04x", tid);
  437. list_add_head(&p->threads, &t->entry);
  438. return t;
  439. }
  440. void dbg_del_thread(struct dbg_thread* t)
  441. {
  442. HeapFree(GetProcessHeap(), 0, t->frames);
  443. list_remove(&t->entry);
  444. if (t == dbg_curr_thread) dbg_curr_thread = NULL;
  445. HeapFree(GetProcessHeap(), 0, t);
  446. }
  447. void dbg_set_option(const char* option, const char* val)
  448. {
  449. if (!strcasecmp(option, "module_load_mismatched"))
  450. {
  451. DWORD opt = SymGetOptions();
  452. if (!val)
  453. dbg_printf("Option: module_load_mismatched %s\n", opt & SYMOPT_LOAD_ANYTHING ? "true" : "false");
  454. else if (!strcasecmp(val, "true")) opt |= SYMOPT_LOAD_ANYTHING;
  455. else if (!strcasecmp(val, "false")) opt &= ~SYMOPT_LOAD_ANYTHING;
  456. else
  457. {
  458. dbg_printf("Syntax: module_load_mismatched [true|false]\n");
  459. return;
  460. }
  461. SymSetOptions(opt);
  462. }
  463. else if (!strcasecmp(option, "symbol_picker"))
  464. {
  465. if (!val)
  466. dbg_printf("Option: symbol_picker %s\n",
  467. symbol_current_picker == symbol_picker_interactive ? "interactive" : "scoped");
  468. else if (!strcasecmp(val, "interactive"))
  469. symbol_current_picker = symbol_picker_interactive;
  470. else if (!strcasecmp(val, "scoped"))
  471. symbol_current_picker = symbol_picker_scoped;
  472. else
  473. {
  474. dbg_printf("Syntax: symbol_picker [interactive|scoped]\n");
  475. return;
  476. }
  477. }
  478. else dbg_printf("Unknown option '%s'\n", option);
  479. }
  480. BOOL dbg_interrupt_debuggee(void)
  481. {
  482. struct dbg_process* p;
  483. if (list_empty(&dbg_process_list)) return FALSE;
  484. /* FIXME: since we likely have a single process, signal the first process
  485. * in list
  486. */
  487. p = LIST_ENTRY(list_head(&dbg_process_list), struct dbg_process, entry);
  488. if (list_next(&dbg_process_list, &p->entry)) dbg_printf("Ctrl-C: only stopping the first process\n");
  489. else dbg_printf("Ctrl-C: stopping debuggee\n");
  490. if (p->event_on_first_exception)
  491. {
  492. SetEvent(p->event_on_first_exception);
  493. CloseHandle(p->event_on_first_exception);
  494. p->event_on_first_exception = NULL;
  495. }
  496. return DebugBreakProcess(p->handle);
  497. }
  498. static BOOL WINAPI ctrl_c_handler(DWORD dwCtrlType)
  499. {
  500. if (dwCtrlType == CTRL_C_EVENT)
  501. {
  502. return dbg_interrupt_debuggee();
  503. }
  504. return FALSE;
  505. }
  506. void dbg_init_console(void)
  507. {
  508. /* set the output handle */
  509. dbg_houtput = GetStdHandle(STD_OUTPUT_HANDLE);
  510. /* set our control-C handler */
  511. SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
  512. /* set our own title */
  513. SetConsoleTitleA("Wine Debugger");
  514. }
  515. static int dbg_winedbg_usage(BOOL advanced)
  516. {
  517. if (advanced)
  518. {
  519. dbg_printf("Usage:\n"
  520. " winedbg <cmdline> launch process <cmdline> (as if you were starting\n"
  521. " it with wine) and run WineDbg on it\n"
  522. " winedbg <num> attach to running process of wpid <num> and run\n"
  523. " WineDbg on it\n"
  524. " winedbg --gdb <cmdline> launch process <cmdline> (as if you were starting\n"
  525. " wine) and run gdb (proxied) on it\n"
  526. " winedbg --gdb <num> attach to running process of wpid <num> and run\n"
  527. " gdb (proxied) on it\n"
  528. " winedbg <file.mdmp> reload the minidump <file.mdmp> into memory and run\n"
  529. " WineDbg on it\n"
  530. " winedbg --help prints advanced options\n");
  531. }
  532. else
  533. dbg_printf("Usage:\n\twinedbg [ [ --gdb ] [ <prog-name> [ <prog-args> ] | <num> | <file.mdmp> | --help ]\n");
  534. return 0;
  535. }
  536. void dbg_start_interactive(HANDLE hFile)
  537. {
  538. struct dbg_process* p;
  539. struct dbg_process* p2;
  540. if (dbg_curr_process)
  541. {
  542. dbg_printf("WineDbg starting on pid %04lx\n", dbg_curr_pid);
  543. if (dbg_curr_process->active_debuggee) dbg_active_wait_for_first_exception();
  544. }
  545. dbg_interactiveP = TRUE;
  546. parser_handle(hFile);
  547. LIST_FOR_EACH_ENTRY_SAFE(p, p2, &dbg_process_list, struct dbg_process, entry)
  548. p->process_io->close_process(p, FALSE);
  549. dbg_save_internal_vars();
  550. }
  551. static LONG CALLBACK top_filter( EXCEPTION_POINTERS *ptr )
  552. {
  553. dbg_printf( "winedbg: Internal crash at %p\n", ptr->ExceptionRecord->ExceptionAddress );
  554. return EXCEPTION_EXECUTE_HANDLER;
  555. }
  556. static void restart_if_wow64(void)
  557. {
  558. BOOL is_wow64;
  559. if (IsWow64Process( GetCurrentProcess(), &is_wow64 ) && is_wow64)
  560. {
  561. STARTUPINFOW si;
  562. PROCESS_INFORMATION pi;
  563. WCHAR filename[MAX_PATH];
  564. void *redir;
  565. DWORD exit_code;
  566. memset( &si, 0, sizeof(si) );
  567. si.cb = sizeof(si);
  568. GetModuleFileNameW( 0, filename, MAX_PATH );
  569. Wow64DisableWow64FsRedirection( &redir );
  570. if (CreateProcessW( filename, GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
  571. {
  572. WINE_TRACE( "restarting %s\n", wine_dbgstr_w(filename) );
  573. SetConsoleCtrlHandler( NULL, TRUE ); /* Ignore ^C */
  574. WaitForSingleObject( pi.hProcess, INFINITE );
  575. GetExitCodeProcess( pi.hProcess, &exit_code );
  576. ExitProcess( exit_code );
  577. }
  578. else WINE_ERR( "failed to restart 64-bit %s, err %d\n", wine_dbgstr_w(filename), GetLastError() );
  579. Wow64RevertWow64FsRedirection( redir );
  580. }
  581. }
  582. int main(int argc, char** argv)
  583. {
  584. int retv = 0;
  585. HANDLE hFile = INVALID_HANDLE_VALUE;
  586. enum dbg_start ds;
  587. /* Initialize the output */
  588. dbg_houtput = GetStdHandle(STD_OUTPUT_HANDLE);
  589. SetUnhandledExceptionFilter( top_filter );
  590. /* Initialize internal vars */
  591. if (!dbg_load_internal_vars()) return -1;
  592. /* as we don't care about exec name */
  593. argc--; argv++;
  594. if (argc && !strcmp(argv[0], "--help"))
  595. return dbg_winedbg_usage(TRUE);
  596. if (argc && !strcmp(argv[0], "--gdb"))
  597. {
  598. restart_if_wow64();
  599. retv = gdb_main(argc, argv);
  600. if (retv == -1) dbg_winedbg_usage(FALSE);
  601. return retv;
  602. }
  603. dbg_init_console();
  604. SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME)) |
  605. SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS);
  606. if (argc && !strcmp(argv[0], "--auto"))
  607. {
  608. switch (dbg_active_auto(argc, argv))
  609. {
  610. case start_ok: return 0;
  611. case start_error_parse: return dbg_winedbg_usage(FALSE);
  612. case start_error_init: return -1;
  613. }
  614. }
  615. if (argc && !strcmp(argv[0], "--minidump"))
  616. {
  617. switch (dbg_active_minidump(argc, argv))
  618. {
  619. case start_ok: return 0;
  620. case start_error_parse: return dbg_winedbg_usage(FALSE);
  621. case start_error_init: return -1;
  622. }
  623. }
  624. /* parse options */
  625. while (argc > 0 && argv[0][0] == '-')
  626. {
  627. if (!strcmp(argv[0], "--command"))
  628. {
  629. argc--; argv++;
  630. hFile = parser_generate_command_file(argv[0], NULL);
  631. if (hFile == INVALID_HANDLE_VALUE)
  632. {
  633. dbg_printf("Couldn't open temp file (%u)\n", GetLastError());
  634. return 1;
  635. }
  636. argc--; argv++;
  637. continue;
  638. }
  639. if (!strcmp(argv[0], "--file"))
  640. {
  641. argc--; argv++;
  642. hFile = CreateFileA(argv[0], GENERIC_READ|DELETE, 0,
  643. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  644. if (hFile == INVALID_HANDLE_VALUE)
  645. {
  646. dbg_printf("Couldn't open file %s (%u)\n", argv[0], GetLastError());
  647. return 1;
  648. }
  649. argc--; argv++;
  650. continue;
  651. }
  652. if (!strcmp(argv[0], "--"))
  653. {
  654. argc--; argv++;
  655. break;
  656. }
  657. return dbg_winedbg_usage(FALSE);
  658. }
  659. if (!argc) ds = start_ok;
  660. else if ((ds = dbg_active_attach(argc, argv)) == start_error_parse &&
  661. (ds = minidump_reload(argc, argv)) == start_error_parse)
  662. ds = dbg_active_launch(argc, argv);
  663. switch (ds)
  664. {
  665. case start_ok: break;
  666. case start_error_parse: return dbg_winedbg_usage(FALSE);
  667. case start_error_init: return -1;
  668. }
  669. restart_if_wow64();
  670. dbg_start_interactive(hFile);
  671. return 0;
  672. }