/****************************************************************** * backtrace_all * * Do a backtrace on every running thread in the system (except the debugger) * (preserves current process information) */ static void backtrace_all(void) { struct dbg_process* process = dbg_curr_process; struct dbg_thread* thread = dbg_curr_thread; CONTEXT ctx = dbg_context; DWORD cpid = dbg_curr_pid; THREADENTRY32 entry; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (snapshot == INVALID_HANDLE_VALUE) { dbg_printf("Unable to create toolhelp snapshot\n"); return; } entry.dwSize = sizeof(entry); if (Thread32First(snapshot, &entry)) { do { if (entry.th32OwnerProcessID == GetCurrentProcessId()) continue; if (dbg_curr_process && dbg_curr_pid != entry.th32OwnerProcessID && cpid != dbg_curr_pid) dbg_curr_process->process_io->close_process(dbg_curr_process, FALSE); if (entry.th32OwnerProcessID == cpid) { dbg_curr_process = process; dbg_curr_pid = cpid; } else if (entry.th32OwnerProcessID != dbg_curr_pid) { if (!dbg_attach_debuggee(entry.th32OwnerProcessID, FALSE)) { dbg_printf("\nwarning: could not attach to %04x\n", entry.th32OwnerProcessID); continue; } dbg_curr_pid = dbg_curr_process->pid; dbg_active_wait_for_first_exception(); } dbg_printf("\nBacktracing for thread %04x in process %04lx (%s):\n", entry.th32ThreadID, dbg_curr_pid, dbg_W2A(dbg_curr_process->imageName, -1)); backtrace_tid(dbg_curr_process, entry.th32ThreadID); } while (Thread32Next(snapshot, &entry)); if (dbg_curr_process && cpid != dbg_curr_pid) dbg_curr_process->process_io->close_process(dbg_curr_process, FALSE); } CloseHandle(snapshot); dbg_curr_process = process; dbg_curr_pid = cpid; dbg_curr_thread = thread; dbg_curr_tid = thread ? thread->tid : 0; dbg_context = ctx; }
void dbg_start_interactive(HANDLE hFile) { struct dbg_process* p; struct dbg_process* p2; if (dbg_curr_process) { dbg_printf("WineDbg starting on pid %04lx\n", dbg_curr_pid); if (dbg_curr_process->active_debuggee) dbg_active_wait_for_first_exception(); } dbg_interactiveP = TRUE; parser_handle(hFile); LIST_FOR_EACH_ENTRY_SAFE(p, p2, &dbg_process_list, struct dbg_process, entry) p->process_io->close_process(p, FALSE); dbg_save_internal_vars(); }
void dbg_run_debuggee(const char* args) { if (args) { WINE_FIXME("Re-running current program with %s as args is broken\n", args); return; } else { if (!dbg_last_cmd_line) { dbg_printf("Cannot find previously used command line.\n"); return; } dbg_start_debuggee(dbg_last_cmd_line); dbg_active_wait_for_first_exception(); source_list_from_addr(NULL, 0); } }
/****************************************************************** * dbg_active_auto * * Starts (<pid> or <pid> <evt>) in automatic mode */ enum dbg_start dbg_active_auto(int argc, char* argv[]) { HANDLE hFile; enum dbg_start ds = start_error_parse; if (!strcmp(argv[0], "--auto")) { /* auto mode */ argc--; argv++; ds = dbg_active_attach(argc, argv); if (ds != start_ok) return ds; hFile = parser_generate_command_file("echo Modules:", "info share", "echo Threads:", "info threads", "backtrace", "detach", NULL); } else if (!strcmp(argv[0], "--minidump")) { const char* file = NULL; char tmp[8 + 1 + MAX_PATH]; /* minidump <file> */ argc--; argv++; /* hard stuff now ; we can get things like: * --minidump <pid> 1 arg * --minidump <pid> <evt> 2 args * --minidump <file> <pid> 2 args * --minidump <file> <pid> <evt> 3 args */ switch (argc) { case 1: ds = dbg_active_attach(argc, argv); break; case 2: if ((ds = dbg_active_attach(argc, argv)) != start_ok) { file = argv[0]; ds = dbg_active_attach(argc - 1, argv + 1); } break; case 3: file = argv[0]; ds = dbg_active_attach(argc - 1, argv + 1); break; default: return start_error_parse; } if (ds != start_ok) return ds; memcpy(tmp, "minidump \"", 10); if (!file) { char path[MAX_PATH]; GetTempPath(sizeof(path), path); GetTempFileName(path, "WD", 0, tmp + 10); } else strcpy(tmp + 10, file); strcat(tmp, "\""); if (!file) { /* FIXME: should generate unix name as well */ dbg_printf("Capturing program state in %s\n", tmp + 9); } hFile = parser_generate_command_file(tmp, "detach", NULL); } else return start_error_parse; if (hFile == INVALID_HANDLE_VALUE) return start_error_parse; if (dbg_curr_process->active_debuggee) dbg_active_wait_for_first_exception(); dbg_interactiveP = TRUE; parser_handle(hFile); return start_ok; }
int main(int argc, char** argv) { int retv = 0; HANDLE hFile = INVALID_HANDLE_VALUE; enum dbg_start ds; #ifdef __i386__ be_cpu = &be_i386; #elif __powerpc__ be_cpu = &be_ppc; #elif __ALPHA__ be_cpu = &be_alpha; #elif __x86_64__ be_cpu = &be_x86_64; #else # error CPU unknown #endif /* Initialize the output */ dbg_houtput = GetStdHandle(STD_OUTPUT_HANDLE); /* Initialize internal vars */ if (!dbg_load_internal_vars()) return -1; /* as we don't care about exec name */ argc--; argv++; if (argc && !strcmp(argv[0], "--help")) return dbg_winedbg_usage(TRUE); if (argc && !strcmp(argv[0], "--gdb")) { retv = gdb_main(argc, argv); if (retv == -1) dbg_winedbg_usage(FALSE); return retv; } dbg_init_console(); SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME)) | SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS); if (argc && (!strcmp(argv[0], "--auto") || !strcmp(argv[0], "--minidump"))) { /* force some internal variables */ DBG_IVAR(BreakOnDllLoad) = 0; dbg_houtput = GetStdHandle(STD_ERROR_HANDLE); switch (dbg_active_auto(argc, argv)) { case start_ok: return 0; case start_error_parse: return dbg_winedbg_usage(FALSE); case start_error_init: return -1; } } /* parse options */ while (argc > 0 && argv[0][0] == '-') { if (!strcmp(argv[0], "--command")) { argc--; argv++; hFile = parser_generate_command_file(argv[0], NULL); if (hFile == INVALID_HANDLE_VALUE) { dbg_printf("Couldn't open temp file (%u)\n", GetLastError()); return 1; } argc--; argv++; continue; } if (!strcmp(argv[0], "--file")) { argc--; argv++; hFile = CreateFileA(argv[0], GENERIC_READ|DELETE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { dbg_printf("Couldn't open file %s (%u)\n", argv[0], GetLastError()); return 1; } argc--; argv++; continue; } if (!strcmp(argv[0], "--")) { argc--; argv++; break; } return dbg_winedbg_usage(FALSE); } if (!argc) ds = start_ok; else if ((ds = dbg_active_attach(argc, argv)) == start_error_parse && (ds = minidump_reload(argc, argv)) == start_error_parse) ds = dbg_active_launch(argc, argv); switch (ds) { case start_ok: break; case start_error_parse: return dbg_winedbg_usage(FALSE); case start_error_init: return -1; } if (dbg_curr_process) { dbg_printf("WineDbg starting on pid %04x\n", dbg_curr_pid); if (dbg_curr_process->active_debuggee) dbg_active_wait_for_first_exception(); } dbg_interactiveP = TRUE; parser_handle(hFile); while (dbg_process_list) dbg_process_list->process_io->close_process(dbg_process_list, FALSE); dbg_save_internal_vars(); return 0; }