We read it into a void* so we also need to zero initialize it in case the target pointer size is shorter than ours.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- programs/winedbg/memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index 053ace94ac81..c9b97686aab0 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -268,12 +268,12 @@ BOOL memory_get_string(struct dbg_process* pcs, void* addr, BOOL in_debuggee,
BOOL memory_get_string_indirect(struct dbg_process* pcs, void* addr, BOOL unicode, WCHAR* buffer, int size) { - void* ad; + void* ad = 0; SIZE_T sz;
buffer[0] = 0; if (addr && - pcs->process_io->read(pcs->handle, addr, &ad, sizeof(ad), &sz) && sz == sizeof(ad) && ad) + pcs->process_io->read(pcs->handle, addr, &ad, pcs->be_cpu->pointer_size, &sz) && sz == pcs->be_cpu->pointer_size && ad) { LPSTR buff; BOOL ret;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- programs/winedbg/gdbproxy.c | 186 ++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index 8e1267a01832..81fc64898511 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -67,6 +67,17 @@
WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
+struct gdb_xpoint +{ + struct list entry; + int pid; + int tid; + enum be_xpoint_type type; + void *addr; + int size; + unsigned long value; +}; + struct gdb_context { /* gdb information */ @@ -86,6 +97,7 @@ struct gdb_context /* generic GDB thread information */ int exec_tid; /* tid used in step & continue */ int other_tid; /* tid to be used in any other operation */ + struct list xpoint_list; /* current Win32 trap env */ DEBUG_EVENT de; DWORD de_reply; @@ -98,6 +110,64 @@ struct gdb_context BOOL no_ack_mode; };
+static void gdbctx_delete_xpoint(struct gdb_context *gdbctx, struct dbg_thread *thread, + dbg_ctx_t *ctx, struct gdb_xpoint *x) +{ + struct dbg_process *process = thread->process; + struct backend_cpu *cpu = process->be_cpu; + + if (!cpu->remove_Xpoint(process->handle, process->process_io, ctx, x->type, x->addr, x->value, x->size)) + ERR("%04x:%04x: Couldn't remove breakpoint at:%p/%x type:%d\n", process->pid, thread->tid, x->addr, x->size, x->type); + + list_remove(&x->entry); + HeapFree(GetProcessHeap(), 0, x); +} + +static void gdbctx_insert_xpoint(struct gdb_context *gdbctx, struct dbg_thread *thread, + dbg_ctx_t *ctx, enum be_xpoint_type type, void *addr, int size) +{ + struct dbg_process *process = thread->process; + struct backend_cpu *cpu = process->be_cpu; + struct gdb_xpoint *x; + unsigned long value; + + if (!cpu->insert_Xpoint(process->handle, process->process_io, ctx, type, addr, &value, size)) + { + ERR("%04x:%04x: Couldn't insert breakpoint at:%p/%x type:%d\n", process->pid, thread->tid, addr, size, type); + return; + } + + if (!(x = HeapAlloc(GetProcessHeap(), 0, sizeof(struct gdb_xpoint)))) + { + ERR("%04x:%04x: Couldn't allocate memory for breakpoint at:%p/%x type:%d\n", process->pid, thread->tid, addr, size, type); + return; + } + + x->pid = process->pid; + x->tid = thread->tid; + x->type = type; + x->addr = addr; + x->size = size; + x->value = value; + list_add_head(&gdbctx->xpoint_list, &x->entry); +} + +static struct gdb_xpoint *gdb_find_xpoint(struct gdb_context *gdbctx, struct dbg_thread *thread, + enum be_xpoint_type type, void *addr, int size) +{ + struct gdb_xpoint *x; + + LIST_FOR_EACH_ENTRY(x, &gdbctx->xpoint_list, struct gdb_xpoint, entry) + { + if (thread && (x->pid != thread->process->pid || x->tid != thread->tid)) + continue; + if (x->type == type && x->addr == addr && x->size == size) + return x; + } + + return NULL; +} + static BOOL tgt_process_gdbproxy_read(HANDLE hProcess, const void* addr, void* buffer, SIZE_T len, SIZE_T* rlen) { @@ -775,6 +845,34 @@ static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, dbg_ * =============================================== * */
+static void packet_reply_status_xpoints(struct gdb_context* gdbctx, struct dbg_thread *thread, + dbg_ctx_t *ctx) +{ + struct dbg_process *process = thread->process; + struct backend_cpu *cpu = process->be_cpu; + struct gdb_xpoint *x; + + LIST_FOR_EACH_ENTRY(x, &gdbctx->xpoint_list, struct gdb_xpoint, entry) + { + if (x->pid != process->pid || x->tid != thread->tid) + continue; + if (!cpu->is_watchpoint_set(ctx, x->value)) + continue; + if (x->type == be_xpoint_watch_write) + { + packet_reply_add(gdbctx, "watch:"); + packet_reply_val(gdbctx, (unsigned long)x->addr, sizeof(x->addr)); + packet_reply_add(gdbctx, ";"); + } + if (x->type == be_xpoint_watch_read) + { + packet_reply_add(gdbctx, "rwatch:"); + packet_reply_val(gdbctx, (unsigned long)x->addr, sizeof(x->addr)); + packet_reply_add(gdbctx, ";"); + } + } +} + static enum packet_return packet_reply_status(struct gdb_context* gdbctx) { struct dbg_process *process = gdbctx->process; @@ -800,6 +898,7 @@ static enum packet_return packet_reply_status(struct gdb_context* gdbctx) packet_reply_add(gdbctx, "thread:"); packet_reply_val(gdbctx, gdbctx->de.dwThreadId, 4); packet_reply_add(gdbctx, ";"); + packet_reply_status_xpoints(gdbctx, thread, &ctx);
for (i = 0; i < backend->gdb_num_regs; i++) { @@ -924,6 +1023,90 @@ static enum packet_return packet_continue_signal(struct gdb_context* gdbctx) return packet_reply_status(gdbctx); }
+static enum packet_return packet_delete_breakpoint(struct gdb_context* gdbctx) +{ + struct dbg_process *process = gdbctx->process; + struct dbg_thread *thread; + struct backend_cpu *cpu; + struct gdb_xpoint *x; + dbg_ctx_t ctx; + char type; + void *addr; + int size; + + if (!process) return packet_error; + if (!(cpu = process->be_cpu)) return packet_error; + + if (sscanf(gdbctx->in_packet, "%c,%p,%x", &type, &addr, &size) < 3) + return packet_error; + + if (type == '0') + return packet_error; + + LIST_FOR_EACH_ENTRY(thread, &process->threads, struct dbg_thread, entry) + { + if (!cpu->get_context(thread->handle, &ctx)) + continue; + if ((type == '1') && (x = gdb_find_xpoint(gdbctx, thread, be_xpoint_watch_exec, addr, size))) + gdbctx_delete_xpoint(gdbctx, thread, &ctx, x); + if ((type == '2' || type == '4') && (x = gdb_find_xpoint(gdbctx, thread, be_xpoint_watch_read, addr, size))) + gdbctx_delete_xpoint(gdbctx, thread, &ctx, x); + if ((type == '3' || type == '4') && (x = gdb_find_xpoint(gdbctx, thread, be_xpoint_watch_write, addr, size))) + gdbctx_delete_xpoint(gdbctx, thread, &ctx, x); + cpu->set_context(thread->handle, &ctx); + } + + while ((type == '1') && (x = gdb_find_xpoint(gdbctx, NULL, be_xpoint_watch_exec, addr, size))) + gdbctx_delete_xpoint(gdbctx, NULL, NULL, x); + while ((type == '2' || type == '4') && (x = gdb_find_xpoint(gdbctx, NULL, be_xpoint_watch_read, addr, size))) + gdbctx_delete_xpoint(gdbctx, NULL, NULL, x); + while ((type == '3' || type == '4') && (x = gdb_find_xpoint(gdbctx, NULL, be_xpoint_watch_write, addr, size))) + gdbctx_delete_xpoint(gdbctx, NULL, NULL, x); + + return packet_ok; +} + +static enum packet_return packet_insert_breakpoint(struct gdb_context* gdbctx) +{ + struct dbg_process *process = gdbctx->process; + struct dbg_thread *thread; + struct backend_cpu *cpu; + dbg_ctx_t ctx; + char type; + void *addr; + int size; + + if (!process) return packet_error; + if (!(cpu = process->be_cpu)) return packet_error; + + if (memchr(gdbctx->in_packet, ';', gdbctx->in_packet_len)) + { + FIXME("breakpoint commands not supported\n"); + return packet_error; + } + + if (sscanf(gdbctx->in_packet, "%c,%p,%x", &type, &addr, &size) < 3) + return packet_error; + + if (type == '0') + return packet_error; + + LIST_FOR_EACH_ENTRY(thread, &process->threads, struct dbg_thread, entry) + { + if (!cpu->get_context(thread->handle, &ctx)) + continue; + if (type == '1') + gdbctx_insert_xpoint(gdbctx, thread, &ctx, be_xpoint_watch_exec, addr, size); + if (type == '2' || type == '4') + gdbctx_insert_xpoint(gdbctx, thread, &ctx, be_xpoint_watch_read, addr, size); + if (type == '3' || type == '4') + gdbctx_insert_xpoint(gdbctx, thread, &ctx, be_xpoint_watch_write, addr, size); + cpu->set_context(thread->handle, &ctx); + } + + return packet_ok; +} + static enum packet_return packet_detach(struct gdb_context* gdbctx) { detach_debuggee(gdbctx, FALSE); @@ -1815,6 +1998,8 @@ static struct packet_entry packet_entries[] = {'s', packet_step}, {'T', packet_thread_alive}, {'v', packet_verbose}, + {'z', packet_delete_breakpoint}, + {'Z', packet_insert_breakpoint}, };
static BOOL extract_packets(struct gdb_context* gdbctx) @@ -2069,6 +2254,7 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigne
gdbctx->exec_tid = -1; gdbctx->other_tid = -1; + list_init(&gdbctx->xpoint_list); gdbctx->last_sig = 0; gdbctx->in_trap = FALSE; gdbctx->process = NULL;
It was returning a mix of TRUE/FALSE and in some cases DBG_CONTINUE.
Let's return TRUE if the exception has been handled and should be ignored, or FALSE if not and if we should notify gdb.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- programs/winedbg/gdbproxy.c | 39 +++++++++++++------------------------ 1 file changed, 14 insertions(+), 25 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index 81fc64898511..5b7fdaa83eb4 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -312,8 +312,7 @@ static void dbg_thread_set_single_step(struct dbg_thread *thread, BOOL enable)
static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc) { - EXCEPTION_RECORD* rec = &exc->ExceptionRecord; - BOOL ret = FALSE; + EXCEPTION_RECORD* rec = &exc->ExceptionRecord;
switch (rec->ExceptionCode) { @@ -322,18 +321,15 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e case EXCEPTION_STACK_OVERFLOW: case EXCEPTION_GUARD_PAGE: gdbctx->last_sig = SIGSEGV; - ret = TRUE; - break; + return FALSE; case EXCEPTION_DATATYPE_MISALIGNMENT: gdbctx->last_sig = SIGBUS; - ret = TRUE; - break; + return FALSE; case EXCEPTION_SINGLE_STEP: /* fall through */ case EXCEPTION_BREAKPOINT: gdbctx->last_sig = SIGTRAP; - ret = TRUE; - break; + return FALSE; case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_INEXACT_RESULT: @@ -342,26 +338,21 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e case EXCEPTION_FLT_STACK_CHECK: case EXCEPTION_FLT_UNDERFLOW: gdbctx->last_sig = SIGFPE; - ret = TRUE; - break; + return FALSE; case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_OVERFLOW: gdbctx->last_sig = SIGFPE; - ret = TRUE; - break; + return FALSE; case EXCEPTION_ILLEGAL_INSTRUCTION: gdbctx->last_sig = SIGILL; - ret = TRUE; - break; + return FALSE; case CONTROL_C_EXIT: gdbctx->last_sig = SIGINT; - ret = TRUE; - break; + return FALSE; case STATUS_POSSIBLE_DEADLOCK: - gdbctx->last_sig = SIGALRM; - ret = TRUE; /* FIXME: we could also add here a O packet with additional information */ - break; + gdbctx->last_sig = SIGALRM; + return FALSE; case EXCEPTION_NAME_THREAD: { const THREADNAME_INFO *threadname = (const THREADNAME_INFO *)rec->ExceptionInformation; @@ -384,17 +375,15 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e } else ERR("Cannot set name of thread %04x\n", threadname->dwThreadID); - return DBG_CONTINUE; + return TRUE; } case EXCEPTION_INVALID_HANDLE: - return DBG_CONTINUE; + return TRUE; default: fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode); gdbctx->last_sig = SIGABRT; - ret = TRUE; - break; + return FALSE; } - return ret; }
static void handle_debug_event(struct gdb_context* gdbctx) @@ -469,7 +458,7 @@ static void handle_debug_event(struct gdb_context* gdbctx) TRACE("%08x:%08x: exception code=0x%08x\n", de->dwProcessId, de->dwThreadId, de->u.Exception.ExceptionRecord.ExceptionCode);
- gdbctx->in_trap = handle_exception(gdbctx, &de->u.Exception); + gdbctx->in_trap = !handle_exception(gdbctx, &de->u.Exception); break;
case CREATE_THREAD_DEBUG_EVENT:
As in the previous patch, return TRUE if the debug event should be ignored or FALSE is we should tell gdb. There's no need to have an in_trap context member for that.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- programs/winedbg/gdbproxy.c | 58 +++++++++++++------------------------ 1 file changed, 20 insertions(+), 38 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index 5b7fdaa83eb4..3d605e4fd076 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -102,7 +102,6 @@ struct gdb_context DEBUG_EVENT de; DWORD de_reply; unsigned last_sig; - BOOL in_trap; /* Win32 information */ struct dbg_process* process; /* Unix environment */ @@ -386,7 +385,7 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e } }
-static void handle_debug_event(struct gdb_context* gdbctx) +static BOOL handle_debug_event(struct gdb_context* gdbctx) { DEBUG_EVENT *de = &gdbctx->de; struct dbg_thread *thread; @@ -405,7 +404,9 @@ static void handle_debug_event(struct gdb_context* gdbctx) case CREATE_PROCESS_DEBUG_EVENT: gdbctx->process = dbg_add_process(&be_process_gdbproxy_io, de->dwProcessId, de->u.CreateProcessInfo.hProcess); - if (!gdbctx->process) break; + if (!gdbctx->process) + return TRUE; + memory_get_string_indirect(gdbctx->process, de->u.CreateProcessInfo.lpImageName, de->u.CreateProcessInfo.fUnicode, @@ -430,7 +431,7 @@ static void handle_debug_event(struct gdb_context* gdbctx) dbg_add_thread(gdbctx->process, de->dwThreadId, de->u.CreateProcessInfo.hThread, de->u.CreateProcessInfo.lpThreadLocalBase); - break; + return TRUE;
case LOAD_DLL_DEBUG_EVENT: memory_get_string_indirect(gdbctx->process, @@ -445,20 +446,21 @@ static void handle_debug_event(struct gdb_context* gdbctx) de->u.LoadDll.nDebugInfoSize); dbg_load_module(gdbctx->process->handle, de->u.LoadDll.hFile, u.buffer, (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0); - break; + return TRUE;
case UNLOAD_DLL_DEBUG_EVENT: fprintf(stderr, "%08x:%08x: unload DLL @%p\n", de->dwProcessId, de->dwThreadId, de->u.UnloadDll.lpBaseOfDll); SymUnloadModule(gdbctx->process->handle, (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll); - break; + return TRUE;
case EXCEPTION_DEBUG_EVENT: TRACE("%08x:%08x: exception code=0x%08x\n", de->dwProcessId, de->dwThreadId, de->u.Exception.ExceptionRecord.ExceptionCode);
- gdbctx->in_trap = !handle_exception(gdbctx, &de->u.Exception); + if (handle_exception(gdbctx, &de->u.Exception)) + return TRUE; break;
case CREATE_THREAD_DEBUG_EVENT: @@ -469,14 +471,14 @@ static void handle_debug_event(struct gdb_context* gdbctx) de->dwThreadId, de->u.CreateThread.hThread, de->u.CreateThread.lpThreadLocalBase); - break; + return TRUE;
case EXIT_THREAD_DEBUG_EVENT: fprintf(stderr, "%08x:%08x: exit thread (%u)\n", de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode); if ((thread = dbg_get_thread(gdbctx->process, de->dwThreadId))) dbg_del_thread(thread); - break; + return TRUE;
case EXIT_PROCESS_DEBUG_EVENT: fprintf(stderr, "%08x:%08x: exit process (%u)\n", @@ -486,8 +488,7 @@ static void handle_debug_event(struct gdb_context* gdbctx) gdbctx->process = NULL; /* now signal gdb that we're done */ gdbctx->last_sig = SIGTERM; - gdbctx->in_trap = TRUE; - break; + return FALSE;
case OUTPUT_DEBUG_STRING_EVENT: memory_get_string(gdbctx->process, @@ -495,25 +496,25 @@ static void handle_debug_event(struct gdb_context* gdbctx) de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA)); fprintf(stderr, "%08x:%08x: output debug string (%s)\n", de->dwProcessId, de->dwThreadId, debugstr_a(u.bufferA)); - break; + return TRUE;
case RIP_EVENT: fprintf(stderr, "%08x:%08x: rip error=%u type=%u\n", de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError, de->u.RipInfo.dwType); - break; + return TRUE;
default: FIXME("%08x:%08x: unknown event (%u)\n", de->dwProcessId, de->dwThreadId, de->dwDebugEventCode); }
- if (!gdbctx->in_trap || !gdbctx->process) return; - LIST_FOR_EACH_ENTRY(thread, &gdbctx->process->threads, struct dbg_thread, entry) { if (!thread->suspended) SuspendThread(thread->handle); thread->suspended = TRUE; } + + return FALSE; }
static void handle_step_or_continue(struct gdb_context* gdbctx, int tid, BOOL step, int sig) @@ -568,7 +569,6 @@ static void wait_for_debuggee(struct gdb_context* gdbctx) if (gdbctx->de.dwDebugEventCode) ContinueDebugEvent(gdbctx->de.dwProcessId, gdbctx->de.dwThreadId, gdbctx->de_reply);
- gdbctx->in_trap = FALSE; for (;;) { if (!WaitForDebugEvent(&gdbctx->de, 10)) @@ -588,11 +588,8 @@ static void wait_for_debuggee(struct gdb_context* gdbctx) break; } } - handle_debug_event(gdbctx); - assert(!gdbctx->process || - gdbctx->process->pid == 0 || - gdbctx->de.dwProcessId == gdbctx->process->pid); - if (gdbctx->in_trap) break; + if (!handle_debug_event(gdbctx)) + break; ContinueDebugEvent(gdbctx->de.dwProcessId, gdbctx->de.dwThreadId, DBG_CONTINUE); } } @@ -1109,8 +1106,6 @@ static enum packet_return packet_read_registers(struct gdb_context* gdbctx) dbg_ctx_t ctx; size_t i;
- assert(gdbctx->in_trap); - if (!thread) return packet_error; if (!thread->process) return packet_error; if (!(backend = thread->process->be_cpu)) return packet_error; @@ -1134,8 +1129,6 @@ static enum packet_return packet_write_registers(struct gdb_context* gdbctx) const char *ptr; size_t i;
- assert(gdbctx->in_trap); - if (!thread) return packet_error; if (!thread->process) return packet_error; if (!(backend = thread->process->be_cpu)) return packet_error; @@ -1190,7 +1183,6 @@ static enum packet_return packet_read_memory(struct gdb_context* gdbctx) char buffer[32]; SIZE_T r = 0;
- assert(gdbctx->in_trap); if (sscanf(gdbctx->in_packet, "%p,%x", &addr, &len) != 2) return packet_error; if (len <= 0) return packet_error; TRACE("Read %u bytes at %p\n", len, addr); @@ -1220,7 +1212,6 @@ static enum packet_return packet_write_memory(struct gdb_context* gdbctx) char buffer[32]; SIZE_T w;
- assert(gdbctx->in_trap); ptr = memchr(gdbctx->in_packet, ':', gdbctx->in_packet_len); if (ptr == NULL) { @@ -1262,8 +1253,6 @@ static enum packet_return packet_read_register(struct gdb_context* gdbctx) dbg_ctx_t ctx; size_t reg;
- assert(gdbctx->in_trap); - if (!thread) return packet_error; if (!thread->process) return packet_error; if (!(backend = thread->process->be_cpu)) return packet_error; @@ -1295,8 +1284,6 @@ static enum packet_return packet_write_register(struct gdb_context* gdbctx) size_t reg; char *ptr;
- assert(gdbctx->in_trap); - if (!thread) return packet_error; if (!thread->process) return packet_error; if (!(backend = thread->process->be_cpu)) return packet_error; @@ -2245,7 +2232,6 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigne gdbctx->other_tid = -1; list_init(&gdbctx->xpoint_list); gdbctx->last_sig = 0; - gdbctx->in_trap = FALSE; gdbctx->process = NULL; gdbctx->no_ack_mode = FALSE; for (i = 0; i < ARRAY_SIZE(gdbctx->wine_segs); i++) @@ -2261,13 +2247,9 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigne assert(gdbctx->process == NULL && gdbctx->de.dwProcessId == dbg_curr_pid); /* gdbctx->dwProcessId = pid; */ if (!gdb_startup(gdbctx, flags, port)) return FALSE; - assert(!gdbctx->in_trap); - } - else - { - handle_debug_event(gdbctx); - if (gdbctx->in_trap) break; } + else if (!handle_debug_event(gdbctx)) + break; ContinueDebugEvent(gdbctx->de.dwProcessId, gdbctx->de.dwThreadId, DBG_CONTINUE); } return TRUE;
No real need for a context member for that as well, the mapping is quite straightforward. It also simplifies handle_exception.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- programs/winedbg/gdbproxy.c | 69 +++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 33 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index 3d605e4fd076..3903f113470e 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -101,7 +101,6 @@ struct gdb_context /* current Win32 trap env */ DEBUG_EVENT de; DWORD de_reply; - unsigned last_sig; /* Win32 information */ struct dbg_process* process; /* Unix environment */ @@ -309,26 +308,28 @@ static void dbg_thread_set_single_step(struct dbg_thread *thread, BOOL enable) ERR("set_context failed for thread %04x:%04x\n", thread->process->pid, thread->tid); }
-static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc) +static unsigned char signal_from_debug_event(DEBUG_EVENT* de) { - EXCEPTION_RECORD* rec = &exc->ExceptionRecord; + DWORD ec;
- switch (rec->ExceptionCode) + if (de->dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) + return SIGTERM; + if (de->dwDebugEventCode != EXCEPTION_DEBUG_EVENT) + return SIGTRAP; + + ec = de->u.Exception.ExceptionRecord.ExceptionCode; + switch (ec) { case EXCEPTION_ACCESS_VIOLATION: case EXCEPTION_PRIV_INSTRUCTION: case EXCEPTION_STACK_OVERFLOW: case EXCEPTION_GUARD_PAGE: - gdbctx->last_sig = SIGSEGV; - return FALSE; + return SIGSEGV; case EXCEPTION_DATATYPE_MISALIGNMENT: - gdbctx->last_sig = SIGBUS; - return FALSE; + return SIGBUS; case EXCEPTION_SINGLE_STEP: - /* fall through */ case EXCEPTION_BREAKPOINT: - gdbctx->last_sig = SIGTRAP; - return FALSE; + return SIGTRAP; case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_INEXACT_RESULT: @@ -336,22 +337,32 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e case EXCEPTION_FLT_OVERFLOW: case EXCEPTION_FLT_STACK_CHECK: case EXCEPTION_FLT_UNDERFLOW: - gdbctx->last_sig = SIGFPE; - return FALSE; + return SIGFPE; case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_OVERFLOW: - gdbctx->last_sig = SIGFPE; - return FALSE; + return SIGFPE; case EXCEPTION_ILLEGAL_INSTRUCTION: - gdbctx->last_sig = SIGILL; - return FALSE; + return SIGILL; case CONTROL_C_EXIT: - gdbctx->last_sig = SIGINT; - return FALSE; + return SIGINT; case STATUS_POSSIBLE_DEADLOCK: - /* FIXME: we could also add here a O packet with additional information */ - gdbctx->last_sig = SIGALRM; - return FALSE; + return SIGALRM; + /* should not be here */ + case EXCEPTION_INVALID_HANDLE: + case EXCEPTION_NAME_THREAD: + return SIGTRAP; + default: + ERR("Unknown exception code 0x%08x\n", ec); + return SIGABRT; + } +} + +static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* exc) +{ + EXCEPTION_RECORD* rec = &exc->ExceptionRecord; + + switch (rec->ExceptionCode) + { case EXCEPTION_NAME_THREAD: { const THREADNAME_INFO *threadname = (const THREADNAME_INFO *)rec->ExceptionInformation; @@ -379,8 +390,6 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e case EXCEPTION_INVALID_HANDLE: return TRUE; default: - fprintf(stderr, "Unhandled exception code 0x%08x\n", rec->ExceptionCode); - gdbctx->last_sig = SIGABRT; return FALSE; } } @@ -486,8 +495,6 @@ static BOOL handle_debug_event(struct gdb_context* gdbctx)
dbg_del_process(gdbctx->process); gdbctx->process = NULL; - /* now signal gdb that we're done */ - gdbctx->last_sig = SIGTERM; return FALSE;
case OUTPUT_DEBUG_STRING_EVENT: @@ -869,8 +876,6 @@ static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
if (process != NULL) { - unsigned char sig; - if (!(backend = process->be_cpu)) return packet_error;
if (!(thread = dbg_get_thread(process, gdbctx->de.dwThreadId)) || @@ -879,8 +884,7 @@ static enum packet_return packet_reply_status(struct gdb_context* gdbctx)
packet_reply_open(gdbctx); packet_reply_add(gdbctx, "T"); - sig = gdbctx->last_sig; - packet_reply_val(gdbctx, sig, 1); + packet_reply_val(gdbctx, signal_from_debug_event(&gdbctx->de), 1); packet_reply_add(gdbctx, "thread:"); packet_reply_val(gdbctx, gdbctx->de.dwThreadId, 4); packet_reply_add(gdbctx, ";"); @@ -957,7 +961,7 @@ static enum packet_return packet_verbose_cont(struct gdb_context* gdbctx) case 'C': case 'S': if (sscanf(buf, ";%*c%2x", &sig) <= 0 || - sig != gdbctx->last_sig) + sig != signal_from_debug_event(&gdbctx->de)) return packet_error; buf += 4; break; @@ -997,7 +1001,7 @@ static enum packet_return packet_continue_signal(struct gdb_context* gdbctx) FIXME("Continue at address %p not supported\n", addr); if (n < 1) return packet_error;
- if (sig != gdbctx->last_sig) + if (sig != signal_from_debug_event(&gdbctx->de)) { ERR("Changing signals is not supported.\n"); return packet_error; @@ -2231,7 +2235,6 @@ static BOOL gdb_init_context(struct gdb_context* gdbctx, unsigned flags, unsigne gdbctx->exec_tid = -1; gdbctx->other_tid = -1; list_init(&gdbctx->xpoint_list); - gdbctx->last_sig = 0; gdbctx->process = NULL; gdbctx->no_ack_mode = FALSE; for (i = 0; i < ARRAY_SIZE(gdbctx->wine_segs); i++)