- added support for multi-thread in GDB remote read/write register(s)

commands
- by default, internal errors are now verbose
This commit is contained in:
Eric Pouech 2003-04-19 21:27:47 +00:00 committed by Alexandre Julliard
parent b650372b86
commit 5052e072e3
1 changed files with 115 additions and 80 deletions

View File

@ -3,7 +3,7 @@
* This allows to debug Wine (and any "emulated" program) under * This allows to debug Wine (and any "emulated" program) under
* Linux using GDB * Linux using GDB
* *
* Copyright (c) Eric Pouech 2002 * Copyright (c) Eric Pouech 2002-2003
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -58,6 +58,7 @@
#define GDBPXY_TRC_COMMAND_ERROR 0x08 #define GDBPXY_TRC_COMMAND_ERROR 0x08
#define GDBPXY_TRC_WIN32_EVENT 0x10 #define GDBPXY_TRC_WIN32_EVENT 0x10
#define GDBPXY_TRC_WIN32_ERROR 0x20 #define GDBPXY_TRC_WIN32_ERROR 0x20
#define GDBPXY_TRC_COMMAND_FIXME 0x80
struct gdb_ctx_Xpoint struct gdb_ctx_Xpoint
{ {
@ -83,8 +84,8 @@ struct gdb_context
int out_len; int out_len;
int out_curr_packet; int out_curr_packet;
/* generic GDB thread information */ /* generic GDB thread information */
unsigned exec_thread; /* thread used in step & continue */ DBG_THREAD* exec_thread; /* thread used in step & continue */
unsigned other_thread; /* thread to be used in any other operation */ DBG_THREAD* other_thread; /* thread to be used in any other operation */
unsigned trace; unsigned trace;
/* current Win32 trap env */ /* current Win32 trap env */
unsigned last_sig; unsigned last_sig;
@ -262,10 +263,10 @@ static size_t cpu_register_map[] = {
static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0])); static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0]));
static inline unsigned long* cpu_register(struct gdb_context* gdbctx, unsigned idx) static inline unsigned long* cpu_register(const CONTEXT* ctx, unsigned idx)
{ {
assert(idx < cpu_num_regs); assert(idx < cpu_num_regs);
return (unsigned long*)((char*)&gdbctx->context + cpu_register_map[idx]); return (unsigned long*)((char*)ctx + cpu_register_map[idx]);
} }
static inline BOOL cpu_enter_stepping(struct gdb_context* gdbctx) static inline BOOL cpu_enter_stepping(struct gdb_context* gdbctx)
@ -496,6 +497,26 @@ static inline BOOL cpu_remove_Xpoint(struct gdb_context* gdbctx,
* =============================================== * * =============================================== *
*/ */
static BOOL fetch_context(struct gdb_context* gdbctx, HANDLE h, CONTEXT* ctx)
{
ctx->ContextFlags = CONTEXT_CONTROL
| CONTEXT_INTEGER
#ifdef CONTEXT_SEGMENTS
| CONTEXT_SEGMENTS
#endif
#ifdef CONTEXT_DEBUG_REGISTERS
| CONTEXT_DEBUG_REGISTERS
#endif
;
if (!GetThreadContext(h, ctx))
{
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
fprintf(stderr, "Can't get thread's context\n");
return FALSE;
}
return TRUE;
}
static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc) static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc)
{ {
EXCEPTION_RECORD* rec = &exc->ExceptionRecord; EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
@ -550,7 +571,7 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e
break; break;
default: default:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT) if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "unhandled exception code %08lx\n", rec->ExceptionCode); fprintf(stderr, "Unhandled exception code %08lx\n", rec->ExceptionCode);
gdbctx->last_sig = SIGABRT; gdbctx->last_sig = SIGABRT;
ret = TRUE; ret = TRUE;
break; break;
@ -659,22 +680,10 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
de->dwProcessId, de->dwThreadId, de->dwProcessId, de->dwThreadId,
de->u.Exception.ExceptionRecord.ExceptionCode); de->u.Exception.ExceptionRecord.ExceptionCode);
gdbctx->context.ContextFlags = CONTEXT_CONTROL if (fetch_context(gdbctx, DEBUG_CurrThread->handle, &gdbctx->context))
| CONTEXT_INTEGER
#ifdef CONTEXT_SEGMENTS
| CONTEXT_SEGMENTS
#endif
#ifdef CONTEXT_DEBUG_REGISTERS
| CONTEXT_DEBUG_REGISTERS
#endif
;
if (!GetThreadContext(DEBUG_CurrThread->handle, &gdbctx->context))
{ {
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
fprintf(stderr, "Can't get thread's context\n");
break;
} }
gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception);
break; break;
case CREATE_THREAD_DEBUG_EVENT: case CREATE_THREAD_DEBUG_EVENT:
@ -695,6 +704,8 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode); de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
assert(DEBUG_CurrThread); assert(DEBUG_CurrThread);
if (DEBUG_CurrThread == gdbctx->exec_thread) gdbctx->exec_thread = NULL;
if (DEBUG_CurrThread == gdbctx->other_thread) gdbctx->other_thread = NULL;
DEBUG_DelThread(DEBUG_CurrThread); DEBUG_DelThread(DEBUG_CurrThread);
break; break;
@ -741,14 +752,14 @@ static void resume_debuggee(struct gdb_context* gdbctx, unsigned long cont)
{ {
if (!SetThreadContext(DEBUG_CurrThread->handle, &gdbctx->context)) if (!SetThreadContext(DEBUG_CurrThread->handle, &gdbctx->context))
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
fprintf(stderr, "cannot set ctx on %lu\n", DEBUG_CurrThread->tid); fprintf(stderr, "Cannot set context on thread %lu\n", DEBUG_CurrThread->tid);
if (!ContinueDebugEvent(gdbctx->process->pid, DEBUG_CurrThread->tid, cont)) if (!ContinueDebugEvent(gdbctx->process->pid, DEBUG_CurrThread->tid, cont))
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
fprintf(stderr, "cannot continue on %lu (%lu)\n", fprintf(stderr, "Cannot continue on %lu (%lu)\n",
DEBUG_CurrThread->tid, cont); DEBUG_CurrThread->tid, cont);
} }
else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
fprintf(stderr, "cannot find last thread (%lu)\n", DEBUG_CurrThread->tid); fprintf(stderr, "Cannot find last thread (%lu)\n", DEBUG_CurrThread->tid);
} }
static void wait_for_debuggee(struct gdb_context* gdbctx) static void wait_for_debuggee(struct gdb_context* gdbctx)
@ -997,7 +1008,7 @@ static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
*/ */
packet_reply_val(gdbctx, i, 1); packet_reply_val(gdbctx, i, 1);
packet_reply_catc(gdbctx, ':'); packet_reply_catc(gdbctx, ':');
packet_reply_hex_to(gdbctx, cpu_register(gdbctx, i), 4); packet_reply_hex_to(gdbctx, cpu_register(&gdbctx->context, i), 4);
packet_reply_catc(gdbctx, ';'); packet_reply_catc(gdbctx, ';');
} }
} }
@ -1033,10 +1044,10 @@ static enum packet_return packet_continue(struct gdb_context* gdbctx)
{ {
/* FIXME: add support for address in packet */ /* FIXME: add support for address in packet */
assert(gdbctx->in_packet_len == 0); assert(gdbctx->in_packet_len == 0);
if (DEBUG_CurrThread->tid != gdbctx->exec_thread && gdbctx->exec_thread) if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
fprintf(stderr, "NIY: cont on %u, while last thd is %lu\n", fprintf(stderr, "NIY: cont on %lu, while last thread is %lu\n",
gdbctx->exec_thread, DEBUG_CurrThread->tid); gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
resume_debuggee(gdbctx, DBG_CONTINUE); resume_debuggee(gdbctx, DBG_CONTINUE);
wait_for_debuggee(gdbctx); wait_for_debuggee(gdbctx);
return packet_reply_status(gdbctx); return packet_reply_status(gdbctx);
@ -1048,10 +1059,10 @@ static enum packet_return packet_continue_signal(struct gdb_context* gdbctx)
/* FIXME: add support for address in packet */ /* FIXME: add support for address in packet */
assert(gdbctx->in_packet_len == 2); assert(gdbctx->in_packet_len == 2);
if (DEBUG_CurrThread->tid != gdbctx->exec_thread && gdbctx->exec_thread) if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
fprintf(stderr, "NIY: cont/sig on %u, while last thd is %lu\n", fprintf(stderr, "NIY: cont/sig on %lu, while last thread is %lu\n",
gdbctx->exec_thread, DEBUG_CurrThread->tid); gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
hex_from(&sig, gdbctx->in_packet, 1); hex_from(&sig, gdbctx->in_packet, 1);
/* cannot change signals on the fly */ /* cannot change signals on the fly */
if (gdbctx->trace & GDBPXY_TRC_COMMAND) if (gdbctx->trace & GDBPXY_TRC_COMMAND)
@ -1072,20 +1083,22 @@ static enum packet_return packet_detach(struct gdb_context* gdbctx)
static enum packet_return packet_read_registers(struct gdb_context* gdbctx) static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
{ {
int i; int i;
CONTEXT ctx;
CONTEXT* pctx = &gdbctx->context;
assert(gdbctx->in_trap); assert(gdbctx->in_trap);
if (DEBUG_CurrThread->tid != gdbctx->other_thread && gdbctx->other_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "NIY: read regs on %u, while last thd is %lu\n",
gdbctx->other_thread, DEBUG_CurrThread->tid);
packet_reply_open(gdbctx); if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
for (i = 0; i < cpu_num_regs; i++)
{ {
packet_reply_hex_to(gdbctx, cpu_register(gdbctx, i), 4); if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
return packet_error;
} }
packet_reply_open(gdbctx);
for (i = 0; i < cpu_num_regs; i++)
{
packet_reply_hex_to(gdbctx, cpu_register(pctx, i), 4);
}
packet_reply_close(gdbctx); packet_reply_close(gdbctx);
return packet_done; return packet_done;
} }
@ -1093,15 +1106,25 @@ static enum packet_return packet_read_registers(struct gdb_context* gdbctx)
static enum packet_return packet_write_registers(struct gdb_context* gdbctx) static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
{ {
unsigned i; unsigned i;
CONTEXT ctx;
CONTEXT* pctx = &gdbctx->context;
assert(gdbctx->in_trap); assert(gdbctx->in_trap);
if (DEBUG_CurrThread->tid != gdbctx->other_thread && gdbctx->other_thread) if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) {
fprintf(stderr, "NIY: write regs on %u, while last thd is %lu\n", if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
gdbctx->other_thread, DEBUG_CurrThread->tid); return packet_error;
}
if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error; if (gdbctx->in_packet_len < cpu_num_regs * 2) return packet_error;
for (i = 0; i < cpu_num_regs; i++) for (i = 0; i < cpu_num_regs; i++)
hex_from(cpu_register(gdbctx, i), &gdbctx->in_packet[8 * i], 4); hex_from(cpu_register(pctx, i), &gdbctx->in_packet[8 * i], 4);
if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
{
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
fprintf(stderr, "Cannot set context on thread %lu\n", gdbctx->other_thread->tid);
return packet_error;
}
return packet_ok; return packet_ok;
} }
@ -1140,9 +1163,9 @@ static enum packet_return packet_thread(struct gdb_context* gdbctx)
return packet_error; return packet_error;
} }
if (gdbctx->in_packet[0] == 'c') if (gdbctx->in_packet[0] == 'c')
gdbctx->exec_thread = thread; gdbctx->exec_thread = DEBUG_GetThread(gdbctx->process, thread);
else else
gdbctx->other_thread = thread; gdbctx->other_thread = DEBUG_GetThread(gdbctx->process, thread);
return packet_ok; return packet_ok;
default: default:
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
@ -1162,7 +1185,7 @@ static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
/* FIXME:check in_packet_len for reading %p,%x */ /* FIXME:check in_packet_len for reading %p,%x */
if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error; if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error;
if (gdbctx->trace & GDBPXY_TRC_COMMAND) if (gdbctx->trace & GDBPXY_TRC_COMMAND)
fprintf(stderr, "read mem at %p for %u bytes\n", addr, len); fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
for (nread = 0; nread < len > 0; nread += r, addr += r) for (nread = 0; nread < len > 0; nread += r, addr += r)
{ {
blk_len = min(sizeof(buffer), len - nread); blk_len = min(sizeof(buffer), len - nread);
@ -1194,7 +1217,7 @@ static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
if (ptr == NULL) if (ptr == NULL)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "cannot find ':' in %*.*s\n", fprintf(stderr, "Cannot find ':' in %*.*s\n",
gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet); gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
return packet_error; return packet_error;
} }
@ -1203,18 +1226,18 @@ static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "cannot scan addr,len in %s\n", gdbctx->in_packet); fprintf(stderr, "Cannot scan addr,len in %s\n", gdbctx->in_packet);
return packet_error; return packet_error;
} }
if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len) if (ptr - gdbctx->in_packet + len * 2 != gdbctx->in_packet_len)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "wrong sizes %u <> %u\n", fprintf(stderr, "Wrong sizes %u <> %u\n",
ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len); ptr - gdbctx->in_packet + len * 2, gdbctx->in_packet_len);
return packet_error; return packet_error;
} }
if (gdbctx->trace & GDBPXY_TRC_COMMAND) if (gdbctx->trace & GDBPXY_TRC_COMMAND)
fprintf(stderr, "write %u bytes at %p\n", len, addr); fprintf(stderr, "Write %u bytes at %p\n", len, addr);
while (len > 0) while (len > 0)
{ {
blk_len = min(sizeof(buffer), len); blk_len = min(sizeof(buffer), len);
@ -1238,12 +1261,10 @@ static enum packet_return packet_write_register(struct gdb_context* gdbctx)
unsigned reg; unsigned reg;
char* ptr; char* ptr;
char* end; char* end;
CONTEXT ctx;
CONTEXT* pctx = &gdbctx->context;
assert(gdbctx->in_trap); assert(gdbctx->in_trap);
if (DEBUG_CurrThread->tid != gdbctx->other_thread && gdbctx->other_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "NIY: read reg on %u, while last thd is %lu\n",
gdbctx->other_thread, DEBUG_CurrThread->tid);
ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len); ptr = memchr(gdbctx->in_packet, '=', gdbctx->in_packet_len);
*ptr++ = '\0'; *ptr++ = '\0';
@ -1251,7 +1272,7 @@ static enum packet_return packet_write_register(struct gdb_context* gdbctx)
if (end == NULL || reg > cpu_num_regs) if (end == NULL || reg > cpu_num_regs)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "invalid register index %s\n", gdbctx->in_packet); fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet);
/* FIXME: if just the reg is above cpu_num_regs, don't tell gdb /* FIXME: if just the reg is above cpu_num_regs, don't tell gdb
* it wouldn't matter too much, and it fakes our support for all regs * it wouldn't matter too much, and it fakes our support for all regs
*/ */
@ -1260,7 +1281,7 @@ static enum packet_return packet_write_register(struct gdb_context* gdbctx)
if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len) if (ptr + 8 - gdbctx->in_packet != gdbctx->in_packet_len)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "wrong sizes %u <> %u\n", fprintf(stderr, "Wrong sizes %u <> %u\n",
ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len); ptr + 8 - gdbctx->in_packet, gdbctx->in_packet_len);
return packet_error; return packet_error;
} }
@ -1268,7 +1289,21 @@ static enum packet_return packet_write_register(struct gdb_context* gdbctx)
fprintf(stderr, "Writing reg %u <= %*.*s\n", fprintf(stderr, "Writing reg %u <= %*.*s\n",
reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet), reg, gdbctx->in_packet_len - (ptr - gdbctx->in_packet),
gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr); gdbctx->in_packet_len - (ptr - gdbctx->in_packet), ptr);
hex_from(cpu_register(gdbctx, reg), ptr, 4);
if (DEBUG_CurrThread != gdbctx->other_thread && gdbctx->other_thread)
{
if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
return packet_error;
}
hex_from(cpu_register(pctx, reg), ptr, 4);
if (pctx != &gdbctx->context && !SetThreadContext(gdbctx->other_thread->handle, pctx))
{
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR)
fprintf(stderr, "Cannot set context for thread %lu\n", gdbctx->other_thread->tid);
return packet_error;
}
return packet_ok; return packet_ok;
} }
@ -1646,10 +1681,10 @@ static enum packet_return packet_step(struct gdb_context* gdbctx)
{ {
/* FIXME: add support for address in packet */ /* FIXME: add support for address in packet */
assert(gdbctx->in_packet_len == 0); assert(gdbctx->in_packet_len == 0);
if (DEBUG_CurrThread->tid != gdbctx->exec_thread && gdbctx->exec_thread) if (DEBUG_CurrThread != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME)
fprintf(stderr, "NIY: step on %u, while last thd is %lu\n", fprintf(stderr, "NIY: step on %lu, while last thread is %lu\n",
gdbctx->exec_thread, DEBUG_CurrThread->tid); gdbctx->exec_thread->tid, DEBUG_CurrThread->tid);
if (!cpu_enter_stepping(gdbctx)) return packet_error; if (!cpu_enter_stepping(gdbctx)) return packet_error;
resume_debuggee(gdbctx, DBG_CONTINUE); resume_debuggee(gdbctx, DBG_CONTINUE);
wait_for_debuggee(gdbctx); wait_for_debuggee(gdbctx);
@ -1666,7 +1701,7 @@ static enum packet_return packet_step_signal(struct gdb_context* gdbctx)
assert(gdbctx->in_packet_len == 2); assert(gdbctx->in_packet_len == 2);
if (DEBUG_CurrThread->tid != gdbctx->exec_thread && gdbctx->exec_thread) if (DEBUG_CurrThread->tid != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "NIY: step/sig on %u, while last thd is %u\n", fprintf(stderr, "NIY: step/sig on %u, while last thread is %u\n",
gdbctx->exec_thread, DEBUG_CurrThread->tid); gdbctx->exec_thread, DEBUG_CurrThread->tid);
hex_from(&sig, gdbctx->in_packet, 1); hex_from(&sig, gdbctx->in_packet, 1);
/* cannot change signals on the fly */ /* cannot change signals on the fly */
@ -1705,7 +1740,7 @@ static enum packet_return packet_remove_breakpoint(struct gdb_context* gdbctx)
sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2) sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
return packet_error; return packet_error;
if (gdbctx->trace & GDBPXY_TRC_COMMAND) if (gdbctx->trace & GDBPXY_TRC_COMMAND)
fprintf(stderr, "remove bp %p[%u] typ=%c\n", fprintf(stderr, "Remove bp %p[%u] typ=%c\n",
addr, len, gdbctx->in_packet[0]); addr, len, gdbctx->in_packet[0]);
for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--) for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
{ {
@ -1735,7 +1770,7 @@ static enum packet_return packet_set_breakpoint(struct gdb_context* gdbctx)
sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2) sscanf(gdbctx->in_packet + 2, "%p,%x", &addr, &len) != 2)
return packet_error; return packet_error;
if (gdbctx->trace & GDBPXY_TRC_COMMAND) if (gdbctx->trace & GDBPXY_TRC_COMMAND)
fprintf(stderr, "set bp %p[%u] typ=%c\n", fprintf(stderr, "Set bp %p[%u] typ=%c\n",
addr, len, gdbctx->in_packet[0]); addr, len, gdbctx->in_packet[0]);
/* because of packet command handling, this should be made idempotent */ /* because of packet command handling, this should be made idempotent */
for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--) for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
@ -1810,7 +1845,7 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
while ((ret & packet_last_f) == 0) while ((ret & packet_last_f) == 0)
{ {
if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)) if (gdbctx->in_len && (gdbctx->trace & GDBPXY_TRC_LOWLEVEL))
fprintf(stderr, "in-buf: %*.*s\n", fprintf(stderr, "In-buf: %*.*s\n",
gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf); gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len); ptr = memchr(gdbctx->in_buf, '$', gdbctx->in_len);
if (ptr == NULL) return FALSE; if (ptr == NULL) return FALSE;
@ -1818,7 +1853,7 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
{ {
int glen = ptr - gdbctx->in_buf; /* garbage len */ int glen = ptr - gdbctx->in_buf; /* garbage len */
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "removing garbage: %*.*s\n", fprintf(stderr, "Removing garbage: %*.*s\n",
glen, glen, gdbctx->in_buf); glen, glen, gdbctx->in_buf);
gdbctx->in_len -= glen; gdbctx->in_len -= glen;
memmove(gdbctx->in_buf, ptr, gdbctx->in_len); memmove(gdbctx->in_buf, ptr, gdbctx->in_len);
@ -1847,7 +1882,7 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
} }
if (i == sizeof(packet_entries)/sizeof(packet_entries[0])) if (i == sizeof(packet_entries)/sizeof(packet_entries[0]))
{ {
if (gdbctx->trace & GDBPXY_TRC_PACKET) if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "Unknown packet request %*.*s\n", fprintf(stderr, "Unknown packet request %*.*s\n",
plen, plen, &gdbctx->in_buf[1]); plen, plen, &gdbctx->in_buf[1]);
} }
@ -1869,7 +1904,7 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
case packet_done: break; case packet_done: break;
} }
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "reply-full: %*.*s\n", fprintf(stderr, "Reply-full: %*.*s\n",
gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf); gdbctx->out_len, gdbctx->out_len, gdbctx->out_buf);
i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len); i = write(gdbctx->sock, gdbctx->out_buf, gdbctx->out_len);
assert(i == gdbctx->out_len); assert(i == gdbctx->out_len);
@ -1889,17 +1924,17 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
* - one managing the packets for gdb * - one managing the packets for gdb
* - the second one managing the commands... * - the second one managing the commands...
* This would allow us also the reply with the '+' character (Ack of * This would allow us also the reply with the '+' character (Ack of
* the command) way sooner than what we do know * the command) way sooner than what we do now
*/ */
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "dropping packet, I was too slow to respond\n"); fprintf(stderr, "Dropping packet, I was too slow to respond\n");
} }
} }
else else
{ {
write(gdbctx->sock, "+", 1); write(gdbctx->sock, "+", 1);
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum); fprintf(stderr, "Dropping packet, invalid checksum %d <> %d\n", in_cksum, loc_cksum);
} }
gdbctx->in_len -= plen + 4; gdbctx->in_len -= plen + 4;
memmove(gdbctx->in_buf, end + 3, gdbctx->in_len); memmove(gdbctx->in_buf, end + 3, gdbctx->in_len);
@ -1958,7 +1993,7 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
ptr = getenv("WINELOADER"); ptr = getenv("WINELOADER");
strcpy(wine_path, ptr ? ptr : "wine"); strcpy(wine_path, ptr ? ptr : "wine");
fprintf(stderr, "using wine_path: %s\n", wine_path); fprintf(stderr, "Using wine_path: %s\n", wine_path);
read_elf_info(wine_path, gdbctx->wine_segs); read_elf_info(wine_path, gdbctx->wine_segs);
/* step 3: fire up gdb (if requested) */ /* step 3: fire up gdb (if requested) */
@ -1987,7 +2022,7 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
if ((f = fdopen(fd, "w+")) == NULL) return FALSE; if ((f = fdopen(fd, "w+")) == NULL) return FALSE;
fprintf(f, "file %s\n", wine_path); fprintf(f, "file %s\n", wine_path);
fprintf(f, "target remote localhost:%d\n", ntohs(s_addrs.sin_port)); fprintf(f, "target remote localhost:%d\n", ntohs(s_addrs.sin_port));
fprintf(f, "monitor trace=0\n"); fprintf(f, "monitor trace=%d\n", GDBPXY_TRC_COMMAND_FIXME);
fprintf(f, "set prompt Wine-gdb>\\ \n"); fprintf(f, "set prompt Wine-gdb>\\ \n");
/* gdb 5.1 seems to require it, won't hurt anyway */ /* gdb 5.1 seems to require it, won't hurt anyway */
fprintf(f, "sharedlibrary\n"); fprintf(f, "sharedlibrary\n");
@ -2031,11 +2066,11 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
break; break;
case 0: case 0:
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "poll for cnx failed (timeout)\n"); fprintf(stderr, "Poll for cnx failed (timeout)\n");
return FALSE; return FALSE;
case -1: case -1:
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "poll for cnx failed (error)\n"); fprintf(stderr, "Poll for cnx failed (error)\n");
return FALSE; return FALSE;
default: default:
assert(0); assert(0);
@ -2059,10 +2094,10 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags)
gdbctx->out_len = 0; gdbctx->out_len = 0;
gdbctx->out_curr_packet = -1; gdbctx->out_curr_packet = -1;
gdbctx->exec_thread = gdbctx->other_thread = 0; gdbctx->exec_thread = gdbctx->other_thread = NULL;
gdbctx->last_sig = 0; gdbctx->last_sig = 0;
gdbctx->in_trap = FALSE; gdbctx->in_trap = FALSE;
gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_WIN32_EVENT; gdbctx->trace = /*GDBPXY_TRC_PACKET | GDBPXY_TRC_COMMAND |*/ GDBPXY_TRC_COMMAND_ERROR | GDBPXY_TRC_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
gdbctx->process = NULL; gdbctx->process = NULL;
for (i = 0; i < NUM_XPOINT; i++) for (i = 0; i < NUM_XPOINT; i++)
gdbctx->Xpoints[i].type = -1; gdbctx->Xpoints[i].type = -1;
@ -2124,7 +2159,7 @@ BOOL DEBUG_GdbRemote(unsigned flags)
break; break;
case -1: case -1:
if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL) if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "poll failed\n"); fprintf(stderr, "Poll failed\n");
doLoop = FALSE; doLoop = FALSE;
break; break;
} }