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@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);