[PATCH 13/15] winedbg: Rewrite and simplify vCont request handler.
Rémi Bernon
rbernon at codeweavers.com
Mon Jan 27 06:07:16 CST 2020
There was some overcomplicated logic, we only need to iterate over the
actions and apply them on the matching threads that didn't match yet.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
programs/winedbg/debugger.h | 1 +
programs/winedbg/gdbproxy.c | 180 ++++++++----------------------------
programs/winedbg/winedbg.c | 1 +
3 files changed, 40 insertions(+), 142 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index 40d93d669c8..ddac129bab5 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -207,6 +207,7 @@ struct dbg_thread
}* frames;
int num_frames;
int curr_frame;
+ BOOL suspended;
};
struct dbg_delayed_bp
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index d0e0cfb3428..eb550bdfe41 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -638,12 +638,12 @@ static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
}
-static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsigned int threadid)
+static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, struct dbg_thread* thread)
{
-
if (dbg_curr_thread)
{
- if(dbg_curr_thread->tid == threadid){
+ if (dbg_curr_thread->tid == thread->tid)
+ {
/* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */
if (!gdbctx->process->be_cpu->set_context(dbg_curr_thread->handle, &gdbctx->context))
ERR("Failed to set context for thread %04x, error %u\n",
@@ -1038,39 +1038,14 @@ static enum packet_return packet_continue(struct gdb_context* gdbctx)
static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
{
- int i;
- int defaultAction = -1; /* magic non action */
- unsigned char sig;
- int actions =0;
- int actionIndex[20]; /* allow for up to 20 actions */
- int threadIndex[20];
- int threadCount = 0;
- unsigned int threadIDs[100]; /* TODO: Should make this dynamic */
- unsigned int threadID = 0;
- struct dbg_thread* thd;
-
- /* OK we have vCont followed by..
- * ? for query
- * c for packet_continue
- * Csig for packet_continue_signal
- * s for step
- * Ssig for step signal
- * and then an optional thread ID at the end..
- * *******************************************/
+ char *buf = gdbctx->in_packet, *end = gdbctx->in_packet + gdbctx->in_packet_len;
+ struct dbg_process *proc = gdbctx->process;
+ struct dbg_thread *thrd;
- /* Query */
if (gdbctx->in_packet[4] == '?')
{
- /*
- Reply:
- `vCont[;action]...'
- The vCont packet is supported. Each action is a supported command in the vCont packet.
- `'
- The vCont packet is not supported. (this didn't seem to be obeyed!)
- */
packet_reply_open(gdbctx);
packet_reply_add(gdbctx, "vCont");
- /* add all the supported actions to the reply (all of them for now) */
packet_reply_add(gdbctx, ";c");
packet_reply_add(gdbctx, ";C");
packet_reply_add(gdbctx, ";s");
@@ -1079,138 +1054,59 @@ static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
return packet_done;
}
- /* go through the packet and identify where all the actions start at */
- for (i = 4; i < gdbctx->in_packet_len - 1; i++)
- {
- if (gdbctx->in_packet[i] == ';')
- {
- threadIndex[actions] = 0;
- actionIndex[actions++] = i;
- }
- else if (gdbctx->in_packet[i] == ':')
- {
- threadIndex[actions - 1] = i;
- }
- }
+ LIST_FOR_EACH_ENTRY(thrd, &proc->threads, struct dbg_thread, entry)
+ thrd->suspended = TRUE;
- /* now look up the default action */
- for (i = 0 ; i < actions; i++)
+ while (buf < end && (buf = memchr(buf + 1, ';', end - buf - 1)))
{
- if (threadIndex[i] == 0)
- {
- if (defaultAction != -1)
- {
- fprintf(stderr,"Too many default actions specified\n");
- return packet_error;
- }
- defaultAction = i;
- }
- }
-
- /* Now, I have this default action thing that needs to be applied to all non counted threads */
+ int tid = -1, sig = 0;
+ int action, n;
- /* go through all the threads and stick their ids in the to be done list. */
- LIST_FOR_EACH_ENTRY(thd, &gdbctx->process->threads, struct dbg_thread, entry)
- {
- threadIDs[threadCount++] = thd->tid;
- /* check to see if we have more threads than I counted on, and tell the user what to do
- * (they're running winedbg, so I'm sure they can fix the problem from the error message!) */
- if (threadCount == 100)
+ switch ((action = buf[1]))
{
- fprintf(stderr, "Wow, that's a lot of threads, change threadIDs in wine/programs/winedbg/gdbproxy.c to be higher\n");
+ default:
+ return packet_error;
+ case 'c':
+ case 's':
+ buf += 2;
+ break;
+ case 'C':
+ case 'S':
+ if (snscanf(buf, end - buf, ";%*c%2x", &sig) <= 0 ||
+ sig != gdbctx->last_sig)
+ return packet_error;
+ buf += 4;
break;
}
- }
- /* Ok, now we have... actionIndex full of actions and we know what threads there are, so all
- * that remains is to apply the actions to the threads and the default action to any threads
- * left */
- if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
- FIXME("Can't continue thread %04x while on thread %04x\n",
- gdbctx->exec_thread->tid, dbg_curr_thread->tid);
+ if (buf > end)
+ return packet_error;
+ if (buf < end && *buf == ':' && (n = snscanf(buf, end - buf, ":%x", &tid)) <= 0)
+ return packet_error;
- /* deal with the threaded stuff first */
- for (i = 0; i < actions ; i++)
- {
- if (threadIndex[i] != 0)
+ LIST_FOR_EACH_ENTRY(thrd, &proc->threads, struct dbg_thread, entry)
{
- int j, idLength = 0;
- if (i < actions - 1)
- {
- idLength = (actionIndex[i+1] - threadIndex[i]) - 1;
- }
- else
- {
- idLength = (gdbctx->in_packet_len - threadIndex[i]) - 1;
- }
+ if (tid != -1 && thrd->tid != tid) continue;
+ if (!thrd->suspended) continue;
+ thrd->suspended = FALSE;
- threadID = hex_to_int(gdbctx->in_packet + threadIndex[i] + 1 , idLength);
- /* process the action */
- switch (gdbctx->in_packet[actionIndex[i] + 1])
+ switch (action)
{
case 's': /* step */
gdbctx->process->be_cpu->single_step(&gdbctx->context, TRUE);
- /* fall through*/
+ /* fall through */
case 'c': /* continue */
- resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
+ resume_debuggee_thread(gdbctx, DBG_CONTINUE, thrd);
break;
- case 'S': /* step Sig, */
+ case 'S':
gdbctx->process->be_cpu->single_step(&gdbctx->context, TRUE);
/* fall through */
case 'C': /* continue sig */
- hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
- /* cannot change signals on the fly */
- TRACE("sigs: %u %u\n", sig, gdbctx->last_sig);
- if (sig != gdbctx->last_sig)
- return packet_error;
- resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
+ resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, thrd);
break;
}
- for (j = 0 ; j < threadCount; j++)
- {
- if (threadIDs[j] == threadID)
- {
- threadIDs[j] = 0;
- break;
- }
- }
- }
- } /* for i=0 ; i< actions */
-
- /* now we have manage the default action */
- if (defaultAction >= 0)
- {
- for (i = 0 ; i< threadCount; i++)
- {
- /* check to see if we've already done something to the thread*/
- if (threadIDs[i] != 0)
- {
- /* if not apply the default action*/
- threadID = threadIDs[i];
- /* process the action (yes this is almost identical to the one above!) */
- switch (gdbctx->in_packet[actionIndex[defaultAction] + 1])
- {
- case 's': /* step */
- gdbctx->process->be_cpu->single_step(&gdbctx->context, TRUE);
- /* fall through */
- case 'c': /* continue */
- resume_debuggee_thread(gdbctx, DBG_CONTINUE, threadID);
- break;
- case 'S':
- gdbctx->process->be_cpu->single_step(&gdbctx->context, TRUE);
- /* fall through */
- case 'C': /* continue sig */
- hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
- /* cannot change signals on the fly */
- TRACE("sigs: %u %u\n", sig, gdbctx->last_sig);
- if (sig != gdbctx->last_sig)
- return packet_error;
- resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
- break;
- }
- }
}
- } /* if(defaultAction >=0) */
+ }
wait_for_debuggee(gdbctx);
if (gdbctx->process)
diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c
index 5dee3b7e5ab..19f30f04e5d 100644
--- a/programs/winedbg/winedbg.c
+++ b/programs/winedbg/winedbg.c
@@ -500,6 +500,7 @@ struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid,
t->num_frames = 0;
t->curr_frame = -1;
t->addr_mode = AddrModeFlat;
+ t->suspended = FALSE;
snprintf(t->name, sizeof(t->name), "%04x", tid);
--
2.25.0
More information about the wine-devel
mailing list