winedbg/gdbproxy: Use the WINEDEBUG interface for debugging winedbg.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2018-07-30 14:47:53 -05:00 committed by Alexandre Julliard
parent 2a28db37ab
commit 6159431cd7
1 changed files with 99 additions and 225 deletions

View File

@ -63,14 +63,9 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "tlhelp32.h" #include "tlhelp32.h"
#include "wine/debug.h"
#define GDBPXY_TRC_LOWLEVEL 0x01 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
#define GDBPXY_TRC_PACKET 0x02
#define GDBPXY_TRC_COMMAND 0x04
#define GDBPXY_TRC_COMMAND_ERROR 0x08
#define GDBPXY_TRC_WIN32_EVENT 0x10
#define GDBPXY_TRC_WIN32_ERROR 0x20
#define GDBPXY_TRC_COMMAND_FIXME 0x80
struct gdb_context struct gdb_context
{ {
@ -91,7 +86,6 @@ struct gdb_context
/* generic GDB thread information */ /* generic GDB thread information */
struct dbg_thread* exec_thread; /* thread used in step & continue */ struct dbg_thread* exec_thread; /* thread used in step & continue */
struct dbg_thread* other_thread; /* thread to be used in any other operation */ struct dbg_thread* other_thread; /* thread to be used in any other operation */
unsigned trace;
/* current Win32 trap env */ /* current Win32 trap env */
unsigned last_sig; unsigned last_sig;
BOOL in_trap; BOOL in_trap;
@ -234,7 +228,7 @@ static inline DWORD64 cpu_register(struct gdb_context *gdbctx,
case 4: return *(DWORD*)cpu_register_ptr(gdbctx, ctx, idx); case 4: return *(DWORD*)cpu_register_ptr(gdbctx, ctx, idx);
case 8: return *(DWORD64*)cpu_register_ptr(gdbctx, ctx, idx); case 8: return *(DWORD64*)cpu_register_ptr(gdbctx, ctx, idx);
default: default:
fprintf(stderr, "got unexpected size: %u\n", ERR("got unexpected size: %u\n",
(unsigned)gdbctx->process->be_cpu->gdb_register_map[idx].ctx_length); (unsigned)gdbctx->process->be_cpu->gdb_register_map[idx].ctx_length);
assert(0); assert(0);
return 0; return 0;
@ -280,8 +274,7 @@ static BOOL fetch_context(struct gdb_context *gdbctx, HANDLE h, dbg_ctx_t *ctx)
{ {
if (!gdbctx->process->be_cpu->get_context(h, ctx)) if (!gdbctx->process->be_cpu->get_context(h, ctx))
{ {
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) ERR("Failed to get context, error %u\n", GetLastError());
fprintf(stderr, "Can't get thread's context\n");
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
@ -360,11 +353,10 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e
} }
} }
else else
fprintf(stderr, "Cannot set name of thread %04x\n", threadname->dwThreadID); ERR("Cannot set name of thread %04x\n", threadname->dwThreadID);
return DBG_CONTINUE; return DBG_CONTINUE;
} }
default: default:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode); fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode);
gdbctx->last_sig = SIGABRT; gdbctx->last_sig = SIGABRT;
ret = TRUE; ret = TRUE;
@ -394,7 +386,6 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
u.buffer, ARRAY_SIZE(u.buffer)); u.buffer, ARRAY_SIZE(u.buffer));
dbg_set_process_name(gdbctx->process, u.buffer); dbg_set_process_name(gdbctx->process, u.buffer);
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n", fprintf(stderr, "%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
de->dwProcessId, de->dwThreadId, de->dwProcessId, de->dwThreadId,
dbg_W2A(u.buffer, -1), dbg_W2A(u.buffer, -1),
@ -405,12 +396,10 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
/* de->u.CreateProcessInfo.lpStartAddress; */ /* de->u.CreateProcessInfo.lpStartAddress; */
if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE)) if (!dbg_init(gdbctx->process->handle, u.buffer, TRUE))
fprintf(stderr, "Couldn't initiate DbgHelp\n"); ERR("Couldn't initiate DbgHelp\n");
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT) fprintf(stderr, "%04x:%04x: create thread I @%p\n", de->dwProcessId,
fprintf(stderr, "%04x:%04x: create thread I @%p\n", de->dwThreadId, de->u.CreateProcessInfo.lpStartAddress);
de->dwProcessId, de->dwThreadId,
de->u.CreateProcessInfo.lpStartAddress);
assert(dbg_curr_thread == NULL); /* shouldn't be there */ assert(dbg_curr_thread == NULL); /* shouldn't be there */
dbg_add_thread(gdbctx->process, de->dwThreadId, dbg_add_thread(gdbctx->process, de->dwThreadId,
@ -424,7 +413,6 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
de->u.LoadDll.lpImageName, de->u.LoadDll.lpImageName,
de->u.LoadDll.fUnicode, de->u.LoadDll.fUnicode,
u.buffer, ARRAY_SIZE(u.buffer)); u.buffer, ARRAY_SIZE(u.buffer));
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n", fprintf(stderr, "%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
de->dwProcessId, de->dwThreadId, de->dwProcessId, de->dwThreadId,
dbg_W2A(u.buffer, -1), dbg_W2A(u.buffer, -1),
@ -436,7 +424,6 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
break; break;
case UNLOAD_DLL_DEBUG_EVENT: case UNLOAD_DLL_DEBUG_EVENT:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "%08x:%08x: unload DLL @%p\n", fprintf(stderr, "%08x:%08x: unload DLL @%p\n",
de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll); de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll);
SymUnloadModule(gdbctx->process->handle, SymUnloadModule(gdbctx->process->handle,
@ -445,10 +432,8 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
case EXCEPTION_DEBUG_EVENT: case EXCEPTION_DEBUG_EVENT:
assert(dbg_curr_thread); assert(dbg_curr_thread);
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT) fprintf(stderr, "%08x:%08x: exception code=0x%08x\n", de->dwProcessId,
fprintf(stderr, "%08x:%08x: exception code=0x%08x\n", de->dwThreadId, de->u.Exception.ExceptionRecord.ExceptionCode);
de->dwProcessId, de->dwThreadId,
de->u.Exception.ExceptionRecord.ExceptionCode);
if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context)) if (fetch_context(gdbctx, dbg_curr_thread->handle, &gdbctx->context))
{ {
@ -457,9 +442,8 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
break; break;
case CREATE_THREAD_DEBUG_EVENT: case CREATE_THREAD_DEBUG_EVENT:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT) fprintf(stderr, "%08x:%08x: create thread D @%p\n", de->dwProcessId,
fprintf(stderr, "%08x:%08x: create thread D @%p\n", de->dwThreadId, de->u.CreateThread.lpStartAddress);
de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
dbg_add_thread(gdbctx->process, dbg_add_thread(gdbctx->process,
de->dwThreadId, de->dwThreadId,
@ -468,7 +452,6 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
break; break;
case EXIT_THREAD_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "%08x:%08x: exit thread (%u)\n", fprintf(stderr, "%08x:%08x: exit thread (%u)\n",
de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode); de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
@ -479,7 +462,6 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
break; break;
case EXIT_PROCESS_DEBUG_EVENT: case EXIT_PROCESS_DEBUG_EVENT:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "%08x:%08x: exit process (%u)\n", fprintf(stderr, "%08x:%08x: exit process (%u)\n",
de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode); de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
@ -495,21 +477,17 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
memory_get_string(gdbctx->process, memory_get_string(gdbctx->process,
de->u.DebugString.lpDebugStringData, TRUE, de->u.DebugString.lpDebugStringData, TRUE,
de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA)); de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT)
fprintf(stderr, "%08x:%08x: output debug string (%s)\n", fprintf(stderr, "%08x:%08x: output debug string (%s)\n",
de->dwProcessId, de->dwThreadId, u.bufferA); de->dwProcessId, de->dwThreadId, debugstr_a(u.bufferA));
break; break;
case RIP_EVENT: case RIP_EVENT:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT) fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n", de->dwProcessId,
fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n", de->dwThreadId, de->u.RipInfo.dwError, de->u.RipInfo.dwType);
de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
de->u.RipInfo.dwType);
break; break;
default: default:
if (gdbctx->trace & GDBPXY_TRC_WIN32_EVENT) FIXME("%08x:%08x: unknown event (%u)\n",
fprintf(stderr, "%08x:%08x: unknown event (%u)\n",
de->dwProcessId, de->dwThreadId, de->dwDebugEventCode); de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
} }
} }
@ -519,15 +497,14 @@ static void resume_debuggee(struct gdb_context* gdbctx, DWORD cont)
if (dbg_curr_thread) if (dbg_curr_thread)
{ {
if (!gdbctx->process->be_cpu->set_context(dbg_curr_thread->handle, &gdbctx->context)) if (!gdbctx->process->be_cpu->set_context(dbg_curr_thread->handle, &gdbctx->context))
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) ERR("Failed to set context for thread %04x, error %u\n",
fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid); dbg_curr_thread->tid, GetLastError());
if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont)) if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) ERR("Failed to continue thread %04x, error %u\n",
fprintf(stderr, "Cannot continue on %04x (%x)\n", dbg_curr_thread->tid, GetLastError());
dbg_curr_thread->tid, cont);
} }
else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) else
fprintf(stderr, "Cannot find last thread\n"); ERR("Cannot find last thread\n");
} }
@ -539,16 +516,15 @@ static void resume_debuggee_thread(struct gdb_context* gdbctx, DWORD cont, unsig
if(dbg_curr_thread->tid == threadid){ if(dbg_curr_thread->tid == threadid){
/* Windows debug and GDB don't seem to work well here, windows only likes ContinueDebugEvent being used on the reporter of the event */ /* 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)) if (!gdbctx->process->be_cpu->set_context(dbg_curr_thread->handle, &gdbctx->context))
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) ERR("Failed to set context for thread %04x, error %u\n",
fprintf(stderr, "Cannot set context on thread %04x\n", dbg_curr_thread->tid); dbg_curr_thread->tid, GetLastError());
if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont)) if (!ContinueDebugEvent(gdbctx->process->pid, dbg_curr_thread->tid, cont))
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) ERR("Failed to continue thread %04x, error %u\n",
fprintf(stderr, "Cannot continue on %04x (%x)\n", dbg_curr_thread->tid, GetLastError());
dbg_curr_thread->tid, cont);
} }
} }
else if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) else
fprintf(stderr, "Cannot find last thread\n"); ERR("Cannot find last thread\n");
} }
static BOOL check_for_interrupt(struct gdb_context* gdbctx) static BOOL check_for_interrupt(struct gdb_context* gdbctx)
@ -564,20 +540,16 @@ static BOOL check_for_interrupt(struct gdb_context* gdbctx)
if ((ret = poll(&pollfd, 1, 0)) == 1) { if ((ret = poll(&pollfd, 1, 0)) == 1) {
ret = read(gdbctx->sock, &pkt, 1); ret = read(gdbctx->sock, &pkt, 1);
if (ret != 1) { if (ret != 1) {
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) { ERR("read failed\n");
fprintf(stderr, "read failed\n");
}
return FALSE; return FALSE;
} }
if (pkt != '\003') { if (pkt != '\003') {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) { ERR("Unexpected break packet %#02x\n", pkt);
fprintf(stderr, "Unexpected break packet (%c/0x%X)\n", pkt, pkt);
}
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} else if (ret == -1) { } else if (ret == -1) {
fprintf(stderr, "poll failed\n"); ERR("poll failed\n");
} }
return FALSE; return FALSE;
} }
@ -595,9 +567,7 @@ static void wait_for_debuggee(struct gdb_context* gdbctx)
{ {
if (check_for_interrupt(gdbctx)) { if (check_for_interrupt(gdbctx)) {
if (!DebugBreakProcess(gdbctx->process->handle)) { if (!DebugBreakProcess(gdbctx->process->handle)) {
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) { ERR("Failed to break into debugee\n");
fprintf(stderr, "Failed to break into debugee\n");
}
break; break;
} }
WaitForDebugEvent(&de, INFINITE); WaitForDebugEvent(&de, INFINITE);
@ -794,9 +764,6 @@ static void packet_reply_close(struct gdb_context* gdbctx)
packet_reply_catc(gdbctx, '#'); packet_reply_catc(gdbctx, '#');
cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen); cksum = checksum(&gdbctx->out_buf[gdbctx->out_curr_packet], plen);
packet_reply_hex_to(gdbctx, &cksum, 1); packet_reply_hex_to(gdbctx, &cksum, 1);
if (gdbctx->trace & GDBPXY_TRC_PACKET)
fprintf(stderr, "Reply : %*.*s\n",
plen, plen, &gdbctx->out_buf[gdbctx->out_curr_packet]);
gdbctx->out_curr_packet = -1; gdbctx->out_curr_packet = -1;
} }
@ -914,8 +881,7 @@ 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 (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread) if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME) FIXME("Can't continue thread %04x while on thread %04x\n",
fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
gdbctx->exec_thread->tid, dbg_curr_thread->tid); gdbctx->exec_thread->tid, dbg_curr_thread->tid);
resume_debuggee(gdbctx, DBG_CONTINUE); resume_debuggee(gdbctx, DBG_CONTINUE);
wait_for_debuggee(gdbctx); wait_for_debuggee(gdbctx);
@ -965,13 +931,6 @@ static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
return packet_done; return packet_done;
} }
/* This may not be the 'fastest' code in the world. but it should be nice and easy to debug.
(as it's run when people are debugging break points I'm sure they won't notice the extra 100 cycles anyway)
now if only gdb talked XML.... */
#if 0 /* handy for debugging */
fprintf(stderr, "no, but can we find a default packet %.*s %d\n", gdbctx->in_packet_len, gdbctx->in_packet, gdbctx->in_packet_len);
#endif
/* go through the packet and identify where all the actions start at */ /* go through the packet and identify where all the actions start at */
for (i = 4; i < gdbctx->in_packet_len - 1; i++) for (i = 4; i < gdbctx->in_packet_len - 1; i++)
{ {
@ -1019,8 +978,7 @@ static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
* that remains is to apply the actions to the threads and the default action to any threads * that remains is to apply the actions to the threads and the default action to any threads
* left */ * left */
if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread) if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME) FIXME("Can't continue thread %04x while on thread %04x\n",
fprintf(stderr, "NIY: cont on %04x, while last thread is %04x\n",
gdbctx->exec_thread->tid, dbg_curr_thread->tid); gdbctx->exec_thread->tid, dbg_curr_thread->tid);
/* deal with the threaded stuff first */ /* deal with the threaded stuff first */
@ -1054,8 +1012,7 @@ static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
case 'C': /* continue sig */ case 'C': /* continue sig */
hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1); hex_from(&sig, gdbctx->in_packet + actionIndex[i] + 2, 1);
/* cannot change signals on the fly */ /* cannot change signals on the fly */
if (gdbctx->trace & GDBPXY_TRC_COMMAND) TRACE("sigs: %u %u\n", sig, gdbctx->last_sig);
fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
if (sig != gdbctx->last_sig) if (sig != gdbctx->last_sig)
return packet_error; return packet_error;
resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID); resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
@ -1097,8 +1054,7 @@ static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx)
case 'C': /* continue sig */ case 'C': /* continue sig */
hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1); hex_from(&sig, gdbctx->in_packet + actionIndex[defaultAction] + 2, 1);
/* cannot change signals on the fly */ /* cannot change signals on the fly */
if (gdbctx->trace & GDBPXY_TRC_COMMAND) TRACE("sigs: %u %u\n", sig, gdbctx->last_sig);
fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
if (sig != gdbctx->last_sig) if (sig != gdbctx->last_sig)
return packet_error; return packet_error;
resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID); resume_debuggee_thread(gdbctx, DBG_EXCEPTION_NOT_HANDLED, threadID);
@ -1143,9 +1099,8 @@ static enum packet_return packet_verbose(struct gdb_context* gdbctx)
gdbctx->in_packet[klen] == ':' || gdbctx->in_packet[klen] == ':' ||
gdbctx->in_packet[klen] == '?') gdbctx->in_packet[klen] == '?')
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND) TRACE("Trying to process verbose packet %s\n",
fprintf(stderr, "trying to process a verbose packet %*.*s\n", debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
for (i = 0; i < ARRAY_SIZE(verbose_details); i++) for (i = 0; i < ARRAY_SIZE(verbose_details); i++)
{ {
if (klen == verbose_details[i].len && if (klen == verbose_details[i].len &&
@ -1159,9 +1114,8 @@ static enum packet_return packet_verbose(struct gdb_context* gdbctx)
} }
} }
if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME) WARN("No support for verbose packet %s\n",
fprintf(stderr, "No support for verbose packet %*.*s\n", debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
return packet_error; return packet_error;
} }
@ -1172,13 +1126,11 @@ 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 (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread) if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME) FIXME("Can't continue thread %04x while on thread %04x\n",
fprintf(stderr, "NIY: cont/sig on %04x, while last thread is %04x\n",
gdbctx->exec_thread->tid, dbg_curr_thread->tid); gdbctx->exec_thread->tid, dbg_curr_thread->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) TRACE("sigs: %u %u\n", sig, gdbctx->last_sig);
fprintf(stderr, "sigs: %u %u\n", sig, gdbctx->last_sig);
if (sig != gdbctx->last_sig) if (sig != gdbctx->last_sig)
return packet_error; return packet_error;
resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED); resume_debuggee(gdbctx, DBG_EXCEPTION_NOT_HANDLED);
@ -1236,8 +1188,8 @@ static enum packet_return packet_write_registers(struct gdb_context* gdbctx)
if (pctx != &gdbctx->context && if (pctx != &gdbctx->context &&
!gdbctx->process->be_cpu->set_context(gdbctx->other_thread->handle, pctx)) !gdbctx->process->be_cpu->set_context(gdbctx->other_thread->handle, pctx))
{ {
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) ERR("Failed to set context for tid %04x, error %u\n",
fprintf(stderr, "Cannot set context on thread %04x\n", gdbctx->other_thread->tid); gdbctx->other_thread->tid, GetLastError());
return packet_error; return packet_error;
} }
return packet_ok; return packet_ok;
@ -1271,10 +1223,8 @@ static enum packet_return packet_thread(struct gdb_context* gdbctx)
thread = strtol(gdbctx->in_packet + 1, &end, 16); thread = strtol(gdbctx->in_packet + 1, &end, 16);
if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len) if (end == NULL || end > gdbctx->in_packet + gdbctx->in_packet_len)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) ERR("Failed to parse %s\n",
fprintf(stderr, "Cannot get threadid %*.*s\n", debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
gdbctx->in_packet_len - 1, gdbctx->in_packet_len - 1,
gdbctx->in_packet + 1);
return packet_error; return packet_error;
} }
if (gdbctx->in_packet[0] == 'c') if (gdbctx->in_packet[0] == 'c')
@ -1283,8 +1233,7 @@ static enum packet_return packet_thread(struct gdb_context* gdbctx)
gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread); gdbctx->other_thread = dbg_get_thread(gdbctx->process, thread);
return packet_ok; return packet_ok;
default: default:
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) FIXME("Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
fprintf(stderr, "Unknown thread sub-command %c\n", gdbctx->in_packet[0]);
return packet_error; return packet_error;
} }
} }
@ -1300,8 +1249,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 (len <= 0) return packet_error; if (len <= 0) return packet_error;
if (gdbctx->trace & GDBPXY_TRC_COMMAND) TRACE("Read %u bytes at %p\n", len, addr);
fprintf(stderr, "Read mem at %p for %u bytes\n", addr, len);
for (nread = 0; nread < len; nread += r, addr += r) for (nread = 0; nread < len; nread += r, addr += r)
{ {
blk_len = min(sizeof(buffer), len - nread); blk_len = min(sizeof(buffer), len - nread);
@ -1332,28 +1280,23 @@ static enum packet_return packet_write_memory(struct gdb_context* gdbctx)
ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len); ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len);
if (ptr == NULL) if (ptr == NULL)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) ERR("Cannot find ':' in %s\n", debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
fprintf(stderr, "Cannot find ':' in %*.*s\n",
gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
return packet_error; return packet_error;
} }
*ptr++ = '\0'; *ptr++ = '\0';
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) ERR("Failed to parse %s\n", debugstr_a(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) ERR("Length %u does not match packet length %u\n",
fprintf(stderr, "Wrong sizes %u <> %u\n",
(int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len); (int)(ptr - gdbctx->in_packet) + len * 2, gdbctx->in_packet_len);
return packet_error; return packet_error;
} }
if (gdbctx->trace & GDBPXY_TRC_COMMAND) TRACE("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);
@ -1378,8 +1321,7 @@ static enum packet_return packet_read_register(struct gdb_context* gdbctx)
reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len); reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len);
if (reg >= gdbctx->process->be_cpu->gdb_num_regs) if (reg >= gdbctx->process->be_cpu->gdb_num_regs)
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) FIXME("Unhandled register %u\n", reg);
fprintf(stderr, "Register out of bounds %x\n", reg);
return packet_error; return packet_error;
} }
if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread) if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
@ -1387,14 +1329,9 @@ static enum packet_return packet_read_register(struct gdb_context* gdbctx)
if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx)) if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx))
return packet_error; return packet_error;
} }
if (gdbctx->trace & GDBPXY_TRC_COMMAND)
{ TRACE("%u => %s\n", reg, wine_dbgstr_longlong(cpu_register(gdbctx, pctx, reg)));
if (gdbctx->process->be_cpu->gdb_register_map[reg].ctx_length <= sizeof(DWORD64))
fprintf(stderr, "Read register %x => %08x%08x\n", reg,
(unsigned)(cpu_register(gdbctx, pctx, reg) >> 32), (unsigned)cpu_register(gdbctx, pctx, reg));
else
fprintf(stderr, "Read register %x\n", reg);
}
packet_reply_open(gdbctx); packet_reply_open(gdbctx);
packet_reply_register_hex_to(gdbctx, reg); packet_reply_register_hex_to(gdbctx, reg);
packet_reply_close(gdbctx); packet_reply_close(gdbctx);
@ -1413,18 +1350,16 @@ static enum packet_return packet_write_register(struct gdb_context* gdbctx)
reg = strtoul(gdbctx->in_packet, &ptr, 16); reg = strtoul(gdbctx->in_packet, &ptr, 16);
if (ptr == NULL || reg >= gdbctx->process->be_cpu->gdb_num_regs || *ptr++ != '=') if (ptr == NULL || reg >= gdbctx->process->be_cpu->gdb_num_regs || *ptr++ != '=')
{ {
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) FIXME("Unhandled register %s\n",
fprintf(stderr, "Invalid register index %s\n", gdbctx->in_packet); debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
/* 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
*/ */
return (ptr == NULL) ? packet_error : packet_ok; return (ptr == NULL) ? packet_error : packet_ok;
} }
if (gdbctx->trace & GDBPXY_TRC_COMMAND)
{ TRACE("%u <= %s\n", reg,
int len = gdbctx->in_packet_len - (ptr - gdbctx->in_packet); debugstr_an(ptr, (int)(gdbctx->in_packet_len - (ptr - gdbctx->in_packet))));
fprintf(stderr, "Writing reg %u <= %*.*s\n", reg, len, len, ptr);
}
if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread) if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread)
{ {
@ -1436,8 +1371,8 @@ static enum packet_return packet_write_register(struct gdb_context* gdbctx)
if (pctx != &gdbctx->context && if (pctx != &gdbctx->context &&
!gdbctx->process->be_cpu->set_context(gdbctx->other_thread->handle, pctx)) !gdbctx->process->be_cpu->set_context(gdbctx->other_thread->handle, pctx))
{ {
if (gdbctx->trace & GDBPXY_TRC_WIN32_ERROR) ERR("Failed to set context for tid %04x, error %u\n",
fprintf(stderr, "Cannot set context for thread %04x\n", gdbctx->other_thread->tid); gdbctx->other_thread->tid, GetLastError());
return packet_error; return packet_error;
} }
@ -1601,32 +1536,6 @@ static void packet_query_monitor_mem(struct gdb_context* gdbctx, int len, const
packet_reply(gdbctx, "OK", 2); packet_reply(gdbctx, "OK", 2);
} }
static void packet_query_monitor_trace(struct gdb_context* gdbctx,
int len, const char* str)
{
char buffer[128];
if (len == 0)
{
snprintf(buffer, sizeof(buffer), "trace=%x\n", gdbctx->trace);
}
else if (len >= 2 && str[0] == '=')
{
unsigned val = atoi(&str[1]);
snprintf(buffer, sizeof(buffer), "trace: %x => %x\n", gdbctx->trace, val);
gdbctx->trace = val;
}
else
{
/* FIXME: ugly but can use error packet here */
packet_reply_cat(gdbctx, "E00");
return;
}
packet_reply_open(gdbctx);
packet_reply_hex_to_str(gdbctx, buffer);
packet_reply_close(gdbctx);
}
struct query_detail struct query_detail
{ {
int with_arg; int with_arg;
@ -1640,7 +1549,6 @@ struct query_detail
{0, "proc", 4, packet_query_monitor_process}, {0, "proc", 4, packet_query_monitor_process},
{0, "process", 7, packet_query_monitor_process}, {0, "process", 7, packet_query_monitor_process},
{0, "mem", 3, packet_query_monitor_mem}, {0, "mem", 3, packet_query_monitor_mem},
{1, "trace", 5, packet_query_monitor_trace},
{0, NULL, 0, NULL}, {0, NULL, 0, NULL},
}; };
@ -1799,9 +1707,7 @@ static enum packet_return packet_query(struct gdb_context* gdbctx)
return packet_reply(gdbctx, target_xml, -1); return packet_reply(gdbctx, target_xml, -1);
break; break;
} }
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) ERR("Unhandled query %s\n", debugstr_an(gdbctx->in_packet, gdbctx->in_packet_len));
fprintf(stderr, "Unknown or malformed query %*.*s\n",
gdbctx->in_packet_len, gdbctx->in_packet_len, gdbctx->in_packet);
return packet_error; return packet_error;
} }
@ -1810,8 +1716,7 @@ 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 (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread) if (dbg_curr_thread != gdbctx->exec_thread && gdbctx->exec_thread)
if (gdbctx->trace & GDBPXY_TRC_COMMAND_FIXME) FIXME("Can't single-step thread %04x while on thread %04x\n",
fprintf(stderr, "NIY: step on %04x, while last thread is %04x\n",
gdbctx->exec_thread->tid, dbg_curr_thread->tid); gdbctx->exec_thread->tid, dbg_curr_thread->tid);
gdbctx->process->be_cpu->single_step(&gdbctx->context, TRUE); gdbctx->process->be_cpu->single_step(&gdbctx->context, TRUE);
resume_debuggee(gdbctx, DBG_CONTINUE); resume_debuggee(gdbctx, DBG_CONTINUE);
@ -1902,17 +1807,13 @@ 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)) TRACE("Packet: %s\n", debugstr_an(gdbctx->in_buf, gdbctx->in_len));
fprintf(stderr, "In-buf: %*.*s\n",
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;
if (ptr != gdbctx->in_buf) if (ptr != gdbctx->in_buf)
{ {
int glen = ptr - gdbctx->in_buf; /* garbage len */ int glen = ptr - gdbctx->in_buf; /* garbage len */
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) WARN("Removing garbage: %s\n", debugstr_an(gdbctx->in_buf, glen));
fprintf(stderr, "Removing garbage: %*.*s\n",
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);
} }
@ -1939,20 +1840,11 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
if (packet_entries[i].key == gdbctx->in_buf[1]) break; if (packet_entries[i].key == gdbctx->in_buf[1]) break;
} }
if (i == ARRAY_SIZE(packet_entries)) if (i == ARRAY_SIZE(packet_entries))
{ WARN("Unhandled packet %s\n", debugstr_an(&gdbctx->in_buf[1], plen));
if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR)
fprintf(stderr, "Unknown packet request %*.*s\n",
plen, plen, &gdbctx->in_buf[1]);
}
else else
{ {
gdbctx->in_packet = gdbctx->in_buf + 2; gdbctx->in_packet = gdbctx->in_buf + 2;
gdbctx->in_packet_len = plen - 1; gdbctx->in_packet_len = plen - 1;
if (gdbctx->trace & GDBPXY_TRC_PACKET)
fprintf(stderr, "Packet: %c%*.*s\n",
gdbctx->in_buf[1],
gdbctx->in_packet_len, gdbctx->in_packet_len,
gdbctx->in_packet);
ret = (packet_entries[i].handler)(gdbctx); ret = (packet_entries[i].handler)(gdbctx);
} }
switch (ret & ~packet_last_f) switch (ret & ~packet_last_f)
@ -1961,9 +1853,7 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
case packet_ok: packet_reply(gdbctx, "OK", 2); break; case packet_ok: packet_reply(gdbctx, "OK", 2); break;
case packet_done: break; case packet_done: break;
} }
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) TRACE("Reply: %s\n", debugstr_an(gdbctx->out_buf, gdbctx->out_len));
fprintf(stderr, "Reply-full: %*.*s\n",
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);
/* if this fails, we'll have to use POLLOUT... /* if this fails, we'll have to use POLLOUT...
@ -1984,15 +1874,13 @@ static BOOL extract_packets(struct gdb_context* gdbctx)
* This would allow us to send the reply with the '+' character (Ack of * This would allow us to send the reply with the '+' character (Ack of
* the command) way sooner than we do now. * the command) way sooner than we do now.
*/ */
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) ERR("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) ERR("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);
@ -2011,18 +1899,12 @@ static int fetch_data(struct gdb_context* gdbctx)
if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc) if (gdbctx->in_len + STEP > gdbctx->in_buf_alloc)
gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP); gdbctx->in_buf = packet_realloc(gdbctx->in_buf, gdbctx->in_buf_alloc += STEP);
#undef STEP #undef STEP
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "%d %d %*.*s\n",
gdbctx->in_len, gdbctx->in_buf_alloc,
gdbctx->in_len, gdbctx->in_len, gdbctx->in_buf);
len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len); len = read(gdbctx->sock, gdbctx->in_buf + gdbctx->in_len, gdbctx->in_buf_alloc - gdbctx->in_len);
if (len <= 0) break; if (len <= 0) break;
gdbctx->in_len += len; gdbctx->in_len += len;
assert(gdbctx->in_len <= gdbctx->in_buf_alloc); assert(gdbctx->in_len <= gdbctx->in_buf_alloc);
if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break; if (len < gdbctx->in_buf_alloc - gdbctx->in_len) break;
} }
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL)
fprintf(stderr, "=> %d\n", gdbctx->in_len - in_len);
return gdbctx->in_len - in_len; return gdbctx->in_len - in_len;
} }
@ -2045,7 +1927,6 @@ static BOOL gdb_exec(const char* wine_path, unsigned port, unsigned flags)
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(port)); fprintf(f, "target remote localhost:%d\n", ntohs(port));
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");
@ -2080,8 +1961,7 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
/* step 1: create socket for gdb connection request */ /* step 1: create socket for gdb connection request */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{ {
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) ERR("Failed to create socket: %s\n", strerror(errno));
fprintf(stderr, "Can't create socket");
return FALSE; return FALSE;
} }
@ -2108,7 +1988,7 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
switch (fork()) switch (fork())
{ {
case -1: /* error in parent... */ case -1: /* error in parent... */
fprintf(stderr, "Cannot create gdb\n"); ERR("Failed to start gdb: fork: %s\n", strerror(errno));
goto cleanup; goto cleanup;
default: /* in parent... success */ default: /* in parent... success */
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
@ -2134,8 +2014,7 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
if (gdbctx->sock == -1) if (gdbctx->sock == -1)
break; break;
ret = TRUE; ret = TRUE;
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) TRACE("connected on %d\n", gdbctx->sock);
fprintf(stderr, "Connected on %d\n", gdbctx->sock);
/* don't keep our small packets too long: send them ASAP back to GDB /* don't keep our small packets too long: send them ASAP back to GDB
* without this, GDB really crawls * without this, GDB really crawls
*/ */
@ -2143,12 +2022,10 @@ 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) ERR("Timed out connecting to gdb\n");
fprintf(stderr, "Poll for cnx failed (timeout)\n");
break; break;
case -1: case -1:
if (gdbctx->trace & GDBPXY_TRC_LOWLEVEL) ERR("Failed to connect to gdb: poll: %s\n", strerror(errno));
fprintf(stderr, "Poll for cnx failed (error)\n");
break; break;
default: default:
assert(0); assert(0);
@ -2176,7 +2053,6 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigne
gdbctx->exec_thread = gdbctx->other_thread = NULL; 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_COMMAND_FIXME | GDBPXY_TRC_WIN32_EVENT;
gdbctx->process = NULL; gdbctx->process = NULL;
for (i = 0; i < ARRAY_SIZE(gdbctx->wine_segs); i++) for (i = 0; i < ARRAY_SIZE(gdbctx->wine_segs); i++)
gdbctx->wine_segs[i] = 0; gdbctx->wine_segs[i] = 0;
@ -2221,8 +2097,7 @@ static int gdb_remote(unsigned flags, unsigned port)
/* got something */ /* got something */
if (pollfd.revents & (POLLHUP | POLLERR)) if (pollfd.revents & (POLLHUP | POLLERR))
{ {
if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL) ERR("gdb hung up\n");
fprintf(stderr, "Gdb hung up\n");
/* kill also debuggee process - questionnable - */ /* kill also debuggee process - questionnable - */
detach_debuggee(&gdbctx, TRUE); detach_debuggee(&gdbctx, TRUE);
doLoop = FALSE; doLoop = FALSE;
@ -2237,8 +2112,7 @@ static int gdb_remote(unsigned flags, unsigned port)
/* timeout, should never happen (infinite timeout) */ /* timeout, should never happen (infinite timeout) */
break; break;
case -1: case -1:
if (gdbctx.trace & GDBPXY_TRC_LOWLEVEL) ERR("poll failed: %s\n", strerror(errno));
fprintf(stderr, "Poll failed\n");
doLoop = FALSE; doLoop = FALSE;
break; break;
} }