[PATCH] winedbg: allow changing the current thread

Damjan Jovanovic damjan.jov at gmail.com
Sat Nov 16 05:39:30 CST 2019


One thing winedbg has always lacked in the ability
to change the current thread, making commands like
"info locals" unusable, since they apply to the current
stack frame, set by "frame N", which applies to the
current thread, which cannot be changed.

This patch implements that feature. It adds a new
winedbg command, "thread N", which changes the
current thread to the thread whose TID is N.

Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
---
 programs/winedbg/dbg.y          |  1 +
 programs/winedbg/debug.l        |  1 +
 programs/winedbg/debugger.h     |  1 +
 programs/winedbg/info.c         |  2 +-
 programs/winedbg/tgt_active.c   | 23 +++++++++++++++++++++++
 programs/winedbg/winedbg.man.in |  3 +++
 6 files changed, 30 insertions(+), 1 deletion(-)
-------------- next part --------------
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y
index 126eef2239..ac76b5baf8 100644
--- a/programs/winedbg/dbg.y
+++ b/programs/winedbg/dbg.y
@@ -139,6 +139,7 @@ command:
     | tWHATIS expr_lvalue       { dbg_printf("type = "); types_print_type(&$2.type, FALSE); dbg_printf("\n"); }
     | tATTACH tNUM     		{ dbg_attach_debuggee($2); dbg_active_wait_for_first_exception(); }
     | tDETACH                   { dbg_curr_process->process_io->close_process(dbg_curr_process, FALSE); }
+    | tTHREAD tNUM              { dbg_set_curr_thread($2); }
     | tKILL                     { dbg_curr_process->process_io->close_process(dbg_curr_process, TRUE); }
     | tMINIDUMP pathname        { minidump_write($2, (dbg_curr_thread && dbg_curr_thread->in_exception) ? &dbg_curr_thread->excpt_record : NULL);}
     | tECHO tSTRING             { dbg_printf("%s\n", $2); }
diff --git a/programs/winedbg/debug.l b/programs/winedbg/debug.l
index ef7a2eb42b..79cb8ccd3a 100644
--- a/programs/winedbg/debug.l
+++ b/programs/winedbg/debug.l
@@ -187,6 +187,7 @@ STRING     \"[^\n"]+\"
 <INFO_CMD,BD_CMD>display|displa|displ|disp|dis|di|d	{ BEGIN(NOCMD); return tDISPLAY; }
 <INITIAL>undisplay|undispla|undispl|undisp|undis|undi|und	{ BEGIN(NOCMD); return tUNDISPLAY; }
 <INITIAL>delete|delet|dele|del		{ BEGIN(BD_CMD); return tDELETE; }
+<INITIAL>thread|threa|thre|thr|th	{ BEGIN(NOCMD); return tTHREAD; }
 <INITIAL,NOPROCESS>quit|qui|qu|q	{ BEGIN(NOCMD); return tQUIT; }
 <INITIAL>set|se				{ BEGIN(NOCMD); return tSET; }
 <INITIAL>x				{ BEGIN(FORMAT_EXPECTED); return tEXAM; }
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index d8d7a699fb..40d93d669c 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -427,6 +427,7 @@ extern enum sym_get_lval symbol_picker_scoped(const char* name, const struct sgv
 extern void             dbg_run_debuggee(const char* args);
 extern void             dbg_wait_next_exception(DWORD cont, int count, int mode);
 extern enum dbg_start   dbg_active_attach(int argc, char* argv[]);
+extern BOOL             dbg_set_curr_thread(DWORD tid);
 extern enum dbg_start   dbg_active_launch(int argc, char* argv[]);
 extern enum dbg_start   dbg_active_auto(int argc, char* argv[]);
 extern enum dbg_start   dbg_active_minidump(int argc, char* argv[]);
diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c
index bf5ba4f6e3..123cbc934e 100644
--- a/programs/winedbg/info.c
+++ b/programs/winedbg/info.c
@@ -66,7 +66,7 @@ void print_help(void)
             "  show dir                               dir <path>",
             "  set <reg> = <expr>                     set *<addr> = <expr>",
             "  pass                                   whatis",
-            "  info (see 'help info' for options)",
+            "  info (see 'help info' for options)     thread <tid>",
 
             "The 'x' command accepts repeat counts and formats (including 'i') in the",
             "same way that gdb does.\n",
diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c
index 71e0bc1944..2b38ce95de 100644
--- a/programs/winedbg/tgt_active.c
+++ b/programs/winedbg/tgt_active.c
@@ -98,6 +98,29 @@ static unsigned dbg_fetch_context(void)
     return TRUE;
 }
 
+BOOL dbg_set_curr_thread(DWORD tid)
+{
+    struct dbg_thread* thread;
+
+    if (!dbg_curr_process)
+    {
+        dbg_printf("No process loaded\n");
+        return FALSE;
+    }
+
+    thread = dbg_get_thread(dbg_curr_process, tid);
+    if (thread)
+    {
+        dbg_curr_thread = thread;
+        dbg_fetch_context();
+        stack_fetch_frames(&dbg_context);
+        dbg_curr_tid = tid;
+        return TRUE;
+    }
+    dbg_printf("No such thread\n");
+    return thread != NULL;
+}
+
 /***********************************************************************
  *              dbg_exception_prolog
  *
diff --git a/programs/winedbg/winedbg.man.in b/programs/winedbg/winedbg.man.in
index 6f38bc07b9..6ed8d4474c 100644
--- a/programs/winedbg/winedbg.man.in
+++ b/programs/winedbg/winedbg.man.in
@@ -116,6 +116,9 @@ IDs can be obtained using the \fBinfo\ process\fR command.  Note the
 .IP 
 .IP \fBdetach\fR
 Detach from a Wine-process.
+.IP \fBthread\ \fIN\fR
+Change the current thread to \fIN\fR (its Windows TID, numeric or hexadecimal).
+.IP
 .PP
 \fIHelp commands\fR
 .IP \fBhelp\fR


More information about the wine-devel mailing list