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