Add a --command option to winedbg, add an "all" option to the backtrace command
Mike Hearn
mike at navi.cx
Sun Jun 20 16:31:56 CDT 2004
This does what my previous patches did but in a more generic way. Now you can pass any
single command as an argument to winedbg.
Mike Hearn <mike at navi.cx>
Add a --command option to winedbg, add an "all" option to the backtrace command
Index: programs/winedbg/dbg.y
===================================================================
RCS file: /home/wine/wine/programs/winedbg/dbg.y,v
retrieving revision 1.14
diff -u -p -r1.14 dbg.y
--- programs/winedbg/dbg.y 4 Jun 2004 00:59:16 -0000 1.14
+++ programs/winedbg/dbg.y 20 Jun 2004 21:31:27 -0000
@@ -47,7 +47,7 @@ int yyerror(const char*);
struct type_expr_t type;
}
-%token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tUP tDOWN
+%token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tALL tINFO tUP tDOWN
%token tENABLE tDISABLE tBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM tABORT tVM86
%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tWND tQUEUE tLOCAL tEXCEPTION
%token tPROCESS tTHREAD tMODREF tEOL tEOF
@@ -119,6 +119,7 @@ command:
| tABORT { abort(); }
| tBACKTRACE { stack_backtrace(dbg_curr_tid, TRUE); }
| tBACKTRACE tNUM { stack_backtrace($2, TRUE); }
+ | tBACKTRACE tALL { stack_backtrace(-1, TRUE); }
| tUP { stack_set_frame(dbg_curr_frame + 1); }
| tUP tNUM { stack_set_frame(dbg_curr_frame + $2); }
| tDOWN { stack_set_frame(dbg_curr_frame - 1); }
@@ -273,8 +274,9 @@ maintenance_command:
;
noprocess_state:
- tNOPROCESS {} /* <CR> shall not barf anything */
- | tNOPROCESS tSTRING { dbg_printf("No process loaded, cannot execute '%s'\n", $2); }
+ tNOPROCESS {} /* <CR> shall not barf anything */
+ | tNOPROCESS tBACKTRACE tALL { stack_backtrace(-1, TRUE); } /* can backtrace all threads with no attached process */
+ | tNOPROCESS tSTRING { dbg_printf("No process loaded, cannot execute '%s'\n", $2); }
;
type_expr:
@@ -449,11 +451,20 @@ 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;
size_t len;
+
+ if (arg_command) {
+ *line = arg_command;
+ arg_command = "quit\n"; /* we only run one command before exiting */
+ return 1;
+ }
/* as of today, console handles can be file handles... so better use file APIs rather than
* console's
@@ -501,7 +512,7 @@ int input_read_line(const char* pfx, cha
assert(line);
line[0] = '\n';
line[1] = '\0';
-
+
input_fetch_entire_line(pfx, &line, &len, FALSE);
len = strlen(line);
/* remove trailing \n */
Index: programs/winedbg/debug.l
===================================================================
RCS file: /home/wine/wine/programs/winedbg/debug.l,v
retrieving revision 1.9
diff -u -p -r1.9 debug.l
--- programs/winedbg/debug.l 4 Jun 2004 00:59:16 -0000 1.9
+++ programs/winedbg/debug.l 20 Jun 2004 21:31:27 -0000
@@ -143,8 +143,8 @@ STRING \"[^\n"]+\"
<INITIAL>x { BEGIN(FORMAT_EXPECTED); return tEXAM; }
<INITIAL,NOPROCESS>help|hel|he|"?" { BEGIN(HELP_CMD); return tHELP; }
-<INITIAL>backtrace|backtrac|backtra|backt|back|bac|ba|bt { BEGIN(NOCMD); return tBACKTRACE; }
-<INITIAL>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; }
+<INITIAL,NOPROCESS>backtrace|backtrac|backtra|backt|back|bac|ba|bt { BEGIN(NOCMD); return tBACKTRACE; }
+<INITIAL,NOPROCESS>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; }
<INITIAL>cont|con|co|c { BEGIN(NOCMD); return tCONT; }
<INITIAL>pass|pas|pa { BEGIN(NOCMD); return tPASS; }
@@ -200,6 +200,9 @@ signed { return tSIGNED; }
struct { return tSTRUCT; }
union { return tUNION; }
enum { return tENUM; }
+
+
+all { return tALL; }
{IDENTIFIER} { yylval.string = lexeme_alloc(yytext); return tIDENTIFIER; }
"$"{IDENTIFIER} { yylval.string = lexeme_alloc(yytext+1); return tINTVAR; }
Index: programs/winedbg/stack.c
===================================================================
RCS file: /home/wine/wine/programs/winedbg/stack.c,v
retrieving revision 1.3
diff -u -p -r1.3 stack.c
--- programs/winedbg/stack.c 4 Jun 2004 00:59:16 -0000 1.3
+++ programs/winedbg/stack.c 20 Jun 2004 21:31:27 -0000
@@ -28,6 +28,7 @@
#include "stackframe.h"
#include "winbase.h"
#include "wine/debug.h"
+#include "tlhelp32.h"
WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
@@ -103,6 +104,48 @@ void stack_backtrace(DWORD tid, BOOL noi
struct dbg_thread* thread;
unsigned nf;
+ if (tid == -1) /* backtrace every thread in every process except the debugger itself, invoking via "bt all" */
+ {
+ 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)) {
+ CloseHandle(snapshot);
+ return;
+ }
+
+ do {
+ if (entry.th32OwnerProcessID == GetCurrentProcessId()) continue;
+ if (dbg_curr_process) dbg_detach_debuggee();
+
+ dbg_printf("\n");
+ if (!dbg_attach_debuggee(entry.th32OwnerProcessID, FALSE, TRUE)) {
+ dbg_printf("\nwarning: could not attach to 0x%lx\n", entry.th32OwnerProcessID);
+ continue;
+ }
+
+ dbg_printf("Backtracing for thread 0x%lx in process 0x%lx (%s):\n", entry.th32ThreadID, dbg_curr_pid, dbg_curr_process->imageName);
+
+ stack_backtrace(entry.th32ThreadID, TRUE);
+ } while (Thread32Next(snapshot, &entry));
+
+ if (dbg_curr_process) dbg_detach_debuggee();
+ CloseHandle(snapshot);
+ return;
+ }
+
+ if (!dbg_curr_process) {
+ dbg_printf("You must be attached to a process to run this command.\n");
+ return;
+ }
+
if (tid == dbg_curr_tid)
{
ctx = dbg_context; /* as StackWalk may modify it... */
Index: programs/winedbg/winedbg.c
===================================================================
RCS file: /home/wine/wine/programs/winedbg/winedbg.c,v
retrieving revision 1.20
diff -u -p -r1.20 winedbg.c
--- programs/winedbg/winedbg.c 4 Jun 2004 00:59:16 -0000 1.20
+++ programs/winedbg/winedbg.c 20 Jun 2004 21:31:27 -0000
@@ -398,6 +398,7 @@ BOOL dbg_attach_debuggee(DWORD pid, BOOL
{
DEBUG_EVENT de;
+
if (!(dbg_curr_process = dbg_add_process(pid, 0, NULL))) return FALSE;
if (!DebugActiveProcess(pid))
@@ -408,6 +409,7 @@ BOOL dbg_attach_debuggee(DWORD pid, BOOL
}
dbg_curr_process->continue_on_first_exception = cofe;
+
if (wfe) /* shall we proceed all debug events until we get an exception ? */
{
dbg_interactiveP = FALSE;
@@ -417,6 +419,8 @@ BOOL dbg_attach_debuggee(DWORD pid, BOOL
}
if (dbg_curr_process) dbg_interactiveP = TRUE;
}
+
+
return TRUE;
}
@@ -707,9 +711,11 @@ static unsigned dbg_handle_debug_event(D
char buffer[256];
DWORD cont = DBG_CONTINUE;
+
dbg_curr_pid = de->dwProcessId;
dbg_curr_tid = de->dwThreadId;
+
if ((dbg_curr_process = dbg_get_process(de->dwProcessId)) != NULL)
dbg_curr_thread = dbg_get_thread(dbg_curr_process, de->dwThreadId);
else
@@ -768,6 +774,7 @@ static unsigned dbg_handle_debug_event(D
WINE_ERR("Couldn't create process\n");
break;
}
+
if (!SymInitialize(dbg_curr_process->handle, NULL, TRUE))
dbg_printf("Couldn't initiate DbgHelp\n");
@@ -784,6 +791,7 @@ static unsigned dbg_handle_debug_event(D
WINE_ERR("Couldn't create thread\n");
break;
}
+
dbg_init_current_process();
dbg_init_current_thread(de->u.CreateProcessInfo.lpStartAddress);
break;
@@ -1102,6 +1110,16 @@ int main(int argc, char** argv)
/* parse options */
while (argc > 1 && argv[1][0] == '-')
{
+ if (!strcmp(argv[1], "--command"))
+ {
+ extern char *arg_command;
+ argc--; argv++;
+ arg_command = HeapAlloc(GetProcessHeap(), 0, strlen(argv[1])+2);
+ strcpy(arg_command, argv[1]);
+ strcat(arg_command, "\n");
+ argc--; argv++;
+ continue;
+ }
if (!strcmp(argv[1], "--auto"))
{
if (dbg_action_mode != none_mode) return dbg_winedbg_usage();
More information about the wine-patches
mailing list