diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 90b0c88479b..4bcb9a915b1 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -452,24 +452,12 @@ static void stripwhite(char *string) static HANDLE dbg_parser_input; static HANDLE dbg_parser_output; -/* command passed in the command line arguments */ -char *arg_command = NULL; - int input_fetch_entire_line(const char* pfx, char** line, size_t* alloc, BOOL check_nl) { char buf_line[256]; DWORD nread, nwritten; size_t len; - if (arg_command) { - /* we only run one command before exiting */ - const char q[] = "quit\n"; - *line = arg_command; - arg_command = HeapAlloc(GetProcessHeap(), 0, sizeof q); - lstrcpyA(arg_command, q); - return 1; - } - /* as of today, console handles can be file handles... so better use file APIs rather than * console's */ @@ -529,11 +517,11 @@ int input_read_line(const char* pfx, char* buf, int size) } /*********************************************************************** - * parser + * parser_handle * * Debugger command line parser */ -void parser(const char* filename) +void parser_handle(HANDLE input) { BOOL ret_ok; HANDLE in_copy = dbg_parser_input; @@ -545,12 +533,10 @@ void parser(const char* filename) ret_ok = FALSE; - if (filename) + if (input != INVALID_HANDLE_VALUE) { - HANDLE h = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0L, 0); - if (h == INVALID_HANDLE_VALUE) return; - dbg_parser_output = 0; - dbg_parser_input = h; + dbg_parser_output = INVALID_HANDLE_VALUE; + dbg_parser_input = input; } else { @@ -573,11 +559,20 @@ void parser(const char* filename) lexeme_flush(); } while (!ret_ok); - if (filename) CloseHandle(dbg_parser_input); dbg_parser_input = in_copy; dbg_parser_output = out_copy; } +void parser(const char* filename) +{ + HANDLE h = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0L, 0); + if (h != INVALID_HANDLE_VALUE) + { + parser_handle(h); + CloseHandle(h); + } +} + int yyerror(const char* s) { dbg_printf("%s\n", s); diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 64fc111c109..6c908fdf302 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -122,8 +122,6 @@ enum dbg_exec_mode #endif }; -extern char *arg_command; - struct dbg_breakpoint { ADDRESS addr; @@ -268,6 +266,7 @@ extern int break_add_condition(int bpnum, struct expr* exp); /* dbg.y */ extern void parser(const char*); +extern void parser_handle(HANDLE); extern int input_read_line(const char* pfx, char* buffer, int size); extern int input_fetch_entire_line(const char* pfx, char** line, size_t* alloc, BOOL check_nl); diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index 072d18423f4..d48fde63c34 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -69,6 +69,18 @@ * we have a multi-thread debuggee). complete fix must include storing all * thread's step-over bp in process-wide bp array, and not to handle bp * when we have the wrong thread running into that bp + * + code in CREATE_PROCESS debug event doesn't work on Windows, as we cannot + * get the name of the main module this way. We should rewrite all this code + * and store in struct dbg_process as early as possible (before process + * creation or attachment), the name of the main module + * - global: + * + define a better way to enable the wine extensions (either DBG SDK function + * in dbghelp, or TLS variable, or environment variable or ...) + * + audit all files to ensure that we check all potential return values from + * every function call to catch the errors + * + BTW check also whether the exception mechanism is the best way to return + * errors (or find a proper fix for MinGW port) + * + use Wine standard list mechanism for all list handling */ WINE_DEFAULT_DEBUG_CHANNEL(winedbg); @@ -1038,7 +1050,7 @@ void dbg_wait_next_exception(DWORD cont, int count, int mode) dbg_curr_thread->exec_count); } -static unsigned dbg_main_loop(void) +static unsigned dbg_main_loop(HANDLE hFile) { DEBUG_EVENT de; @@ -1061,7 +1073,7 @@ static unsigned dbg_main_loop(void) break; default: dbg_interactiveP = TRUE; - parser(NULL); + parser_handle(hFile); } dbg_printf("WineDbg terminated on pid 0x%lx\n", dbg_curr_pid); @@ -1170,7 +1182,7 @@ static void dbg_init_console(void) static int dbg_winedbg_usage(void) { - dbg_printf("Usage: winedbg [--command cmd|--auto] [--gdb [--no-start] [--with-xterm]] cmdline\n"); + dbg_printf("Usage: winedbg [--command cmd|--file file|--auto] [--gdb [--no-start] [--with-xterm]] cmdline\n"); return 1; } @@ -1189,6 +1201,7 @@ int main(int argc, char** argv) { DWORD retv = 0; unsigned gdb_flags = 0; + HANDLE hFile = INVALID_HANDLE_VALUE; #ifdef __i386__ be_cpu = &be_i386; @@ -1210,10 +1223,36 @@ int main(int argc, char** argv) { if (!strcmp(argv[1], "--command")) { + char path[MAX_PATH], file[MAX_PATH]; + DWORD w; + + GetTempPath(sizeof(path), path); + GetTempFileName(path, "WD", 0, file); argc--; argv++; - arg_command = HeapAlloc(GetProcessHeap(), 0, strlen(argv[1])+2); - strcpy(arg_command, argv[1]); - strcat(arg_command, "\n"); + hFile = CreateFileA(file, GENERIC_READ|GENERIC_WRITE|DELETE, FILE_SHARE_DELETE, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0); + if (hFile == INVALID_HANDLE_VALUE) + { + dbg_printf("Couldn't open temp file %s (%lu)\n", file, GetLastError()); + return 1; + } + WriteFile(hFile, argv[1], strlen(argv[1]), &w, 0); + WriteFile(hFile, "\nquit\n", 6, &w, 0); + SetFilePointer(hFile, 0, NULL, FILE_BEGIN); + + argc--; argv++; + continue; + } + if (!strcmp(argv[1], "--file")) + { + argc--; argv++; + hFile = CreateFileA(argv[1], GENERIC_READ|DELETE, 0, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hFile == INVALID_HANDLE_VALUE) + { + dbg_printf("Couldn't open file %s (%lu)\n", argv[1], GetLastError()); + return 1; + } argc--; argv++; continue; } @@ -1258,7 +1297,7 @@ int main(int argc, char** argv) dbg_curr_pid = strtol(argv[1], &ptr, 10); if (dbg_curr_pid == 0 || ptr != argv[1] + strlen(argv[1]) || - !dbg_attach_debuggee(dbg_curr_pid, dbg_action_mode != gdb_mode, FALSE)) + !dbg_attach_debuggee(dbg_curr_pid, FALSE, FALSE)) dbg_curr_pid = 0; } @@ -1322,7 +1361,7 @@ int main(int argc, char** argv) SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME)) | SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS); - retv = dbg_main_loop(); + retv = dbg_main_loop(hFile); /* don't save modified variables in auto mode */ if (dbg_action_mode != automatic_mode) dbg_save_internal_vars(); diff --git a/programs/winedbg/winedbg.man.in b/programs/winedbg/winedbg.man.in index 916749603d9..9934547837c 100644 --- a/programs/winedbg/winedbg.man.in +++ b/programs/winedbg/winedbg.man.in @@ -3,7 +3,9 @@ .SH NAME winedbg \- Wine's debugger .SH SYNOPSIS -.BR "winedbg " [ " --auto" " |" +.BR "winedbg [" +.RI "[ " " options " "]" +.BR "| --auto |" .BI "--gdb" .RI "[" " options " "] ] [" .BI "program name" @@ -42,7 +44,19 @@ the front end for command handling, and \fBwinedbg\fR will proxy all debugging requests from \fBgdb\fR to the Win32 APIs. .SH OPTIONS -Only the \fBgdb\fR proxy mode allows some options: +When in \fBdefault\fR mode, the following options are available: +.PP +.IP \fI--command\ \fR +\fBwinedbg\fR will execute the command as if it was keyed on +winedbg's command line, and then will exit. This can be handy for +getting the pid of running processes (winedbg --command "info proc"). +.IP \fI--file\ \fR +\fBwinedbg\fR will execute the list of commands contained in file + as if they were keyed on winedbg's command line, and then +will exit. +.PP + +When in \fBgdb\fR proxy mode, the following options are available: .PP .IP \fI--no-start\fR \fBgdb\fR will not be automatically started. Relevant information for starting \fBgdb\fR are printed on @@ -52,18 +66,18 @@ some graphical front-ends, like \fBddd\fR or \fBkgbd\fR. This will run \fBgdb\fR in its own xterm instead of using the current Unix console for textual display. .PP -The rest of the command line, when passed, is used to identify which -programs, if any, has to debugged: +In all modes, the rest of the command line, when passed, is used to +identify which programs, if any, has to debugged: .IP \fBprogram\ name\fR This is the name of an executable to start for a debugging session. \fBwinedbg\fR will actually create a process with this executable. If \fBprograms arguments\fR are also given, they will be used as arguments for creating the process to be debugged. .IP \fBpid\fR -\fBgdb\fR will attach to the process which pid is \fBpid\fR (pids +\fBwinedbg\fR will attach to the process which pid is \fBpid\fR (pids refer to Win32 pids, not Unix pids). Use the \fIinfo proc\fR \fBwinedbg\fR command to list running processes and their Win32 pids. -.IP \fBdefaut\fR +.IP \fBdefault\fR If nothing is specified, you will enter the debugger without any run nor attached process. You'll have to do the job yourself.