From patchwork Tue Nov 26 17:11:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Simon Marchi (Code Review)" X-Patchwork-Id: 36236 Received: (qmail 119553 invoked by alias); 26 Nov 2019 17:21:58 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 119483 invoked by uid 89); 26 Nov 2019 17:21:57 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=13316, violation X-HELO: mx1.osci.io Received: from polly.osci.io (HELO mx1.osci.io) (8.43.85.229) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 26 Nov 2019 17:21:53 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id 36D04203AC; Tue, 26 Nov 2019 12:11:59 -0500 (EST) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [8.43.85.239]) by mx1.osci.io (Postfix) with ESMTP id 4C3C321063 for ; Tue, 26 Nov 2019 12:11:33 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id 1BC352817A for ; Tue, 26 Nov 2019 12:11:33 -0500 (EST) X-Gerrit-PatchSet: 1 Date: Tue, 26 Nov 2019 12:11:33 -0500 From: "Tom Tromey (Code Review)" To: gdb-patches@sourceware.org Message-ID: Auto-Submitted: auto-generated X-Gerrit-MessageType: newchange Subject: [review] Share handle_exception X-Gerrit-Change-Id: I4e6e0d17b868cd51964c273fb28ec066fea6b767 X-Gerrit-Change-Number: 716 X-Gerrit-ChangeURL: X-Gerrit-Commit: af02ef9ff229d33502ed385327036e8688d94758 References: Reply-To: tromey@sourceware.org, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3-79-g83ff7f88f1 Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/716 ...................................................................... Share handle_exception Both gdb and gdbserver have a "handle_exception" function, the bulk of which is shared between the two implementations. This patch arranges for the entire thing to be moved into nat/windows-nat.c, with the differences handled by callbacks. This patch introduces one more callback to make this possible. gdb/ChangeLog 2019-11-26 Tom Tromey * windows-nat.c (MS_VC_EXCEPTION): Move to nat/windows-nat.c. (handle_exception_result): Move to nat/windows-nat.h. (DEBUG_EXCEPTION_SIMPLE): Remove. (windows_nat::handle_ms_vc_exception): New function. (handle_exception): Move to nat/windows-nat.c. (get_windows_debug_event): Update. * nat/windows-nat.h (handle_ms_vc_exception): Declare. (handle_exception_result): Move from windows-nat.c. (handle_exception): Declare. * nat/windows-nat.c (MS_VC_EXCEPTION, handle_exception): Move from windows-nat.c. gdb/gdbserver/ChangeLog 2019-11-26 Tom Tromey * win32-low.c (handle_exception): Remove. (windows_nat::handle_ms_vc_exception): New function. (get_child_debug_event): Add "continue_status" parameter. Update. (win32_wait): Update. Change-Id: I4e6e0d17b868cd51964c273fb28ec066fea6b767 --- M gdb/ChangeLog M gdb/gdbserver/ChangeLog M gdb/gdbserver/win32-low.c M gdb/nat/windows-nat.c M gdb/nat/windows-nat.h M gdb/windows-nat.c 6 files changed, 245 insertions(+), 283 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 221a6e7..d2caa25 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,19 @@ 2019-11-26 Tom Tromey + * windows-nat.c (MS_VC_EXCEPTION): Move to nat/windows-nat.c. + (handle_exception_result): Move to nat/windows-nat.h. + (DEBUG_EXCEPTION_SIMPLE): Remove. + (windows_nat::handle_ms_vc_exception): New function. + (handle_exception): Move to nat/windows-nat.c. + (get_windows_debug_event): Update. + * nat/windows-nat.h (handle_ms_vc_exception): Declare. + (handle_exception_result): Move from windows-nat.c. + (handle_exception): Declare. + * nat/windows-nat.c (MS_VC_EXCEPTION, handle_exception): Move from + windows-nat.c. + +2019-11-26 Tom Tromey + * windows-nat.c (exception_count, event_count): Remove. (handle_exception, get_windows_debug_event) (do_initial_windows_stuff): Update. diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 5c4c580..8ca754b 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,5 +1,13 @@ 2019-11-26 Tom Tromey + * win32-low.c (handle_exception): Remove. + (windows_nat::handle_ms_vc_exception): New function. + (get_child_debug_event): Add "continue_status" parameter. + Update. + (win32_wait): Update. + +2019-11-26 Tom Tromey + * win32-low.c (windows_nat::handle_load_dll): Rename from handle_load_dll. No longer static. (windows_nat::handle_unload_dll): Rename from handle_unload_dll. diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c index 3fcd2a6..ba49dd9 100644 --- a/gdb/gdbserver/win32-low.c +++ b/gdb/gdbserver/win32-low.c @@ -1143,114 +1143,6 @@ } static void -handle_exception (struct target_waitstatus *ourstatus) -{ - DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode; - - ourstatus->kind = TARGET_WAITKIND_STOPPED; - - switch (code) - { - case EXCEPTION_ACCESS_VIOLATION: - OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION")); - ourstatus->value.sig = GDB_SIGNAL_SEGV; - break; - case STATUS_STACK_OVERFLOW: - OUTMSG2 (("STATUS_STACK_OVERFLOW")); - ourstatus->value.sig = GDB_SIGNAL_SEGV; - break; - case STATUS_FLOAT_DENORMAL_OPERAND: - OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_INEXACT_RESULT: - OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_INVALID_OPERATION: - OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_OVERFLOW: - OUTMSG2 (("STATUS_FLOAT_OVERFLOW")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_STACK_CHECK: - OUTMSG2 (("STATUS_FLOAT_STACK_CHECK")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_UNDERFLOW: - OUTMSG2 (("STATUS_FLOAT_UNDERFLOW")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_DIVIDE_BY_ZERO: - OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_INTEGER_DIVIDE_BY_ZERO: - OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_INTEGER_OVERFLOW: - OUTMSG2 (("STATUS_INTEGER_OVERFLOW")); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case EXCEPTION_BREAKPOINT: - OUTMSG2 (("EXCEPTION_BREAKPOINT")); - ourstatus->value.sig = GDB_SIGNAL_TRAP; -#ifdef _WIN32_WCE - /* Remove the initial breakpoint. */ - check_breakpoints ((CORE_ADDR) (long) current_event - .u.Exception.ExceptionRecord.ExceptionAddress); -#endif - break; - case DBG_CONTROL_C: - OUTMSG2 (("DBG_CONTROL_C")); - ourstatus->value.sig = GDB_SIGNAL_INT; - break; - case DBG_CONTROL_BREAK: - OUTMSG2 (("DBG_CONTROL_BREAK")); - ourstatus->value.sig = GDB_SIGNAL_INT; - break; - case EXCEPTION_SINGLE_STEP: - OUTMSG2 (("EXCEPTION_SINGLE_STEP")); - ourstatus->value.sig = GDB_SIGNAL_TRAP; - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION")); - ourstatus->value.sig = GDB_SIGNAL_ILL; - break; - case EXCEPTION_PRIV_INSTRUCTION: - OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION")); - ourstatus->value.sig = GDB_SIGNAL_ILL; - break; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION")); - ourstatus->value.sig = GDB_SIGNAL_ILL; - break; - default: - if (current_event.u.Exception.dwFirstChance) - { - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - return; - } - OUTMSG2 (("gdbserver: unknown target exception 0x%08x at 0x%s", - (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode, - phex_nz ((uintptr_t) current_event.u.Exception.ExceptionRecord. - ExceptionAddress, sizeof (uintptr_t)))); - ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; - break; - } - OUTMSG2 (("\n")); - last_sig = ourstatus->value.sig; -} - - -static void suspend_one_thread (thread_info *thread) { windows_thread_info *th = (windows_thread_info *) thread_target_data (thread); @@ -1282,15 +1174,25 @@ } #endif +/* See nat/windows-nat.h. */ + +bool +windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec) +{ + return false; +} + /* Get the next event from the child. */ static int -get_child_debug_event (struct target_waitstatus *ourstatus) +get_child_debug_event (DWORD *continue_status, + struct target_waitstatus *ourstatus) { ptid_t ptid; last_sig = GDB_SIGNAL_0; ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + *continue_status = DBG_CONTINUE; /* Check if GDB sent us an interrupt request. */ check_remote_input_interrupt_request (); @@ -1457,7 +1359,9 @@ "for pid=%u tid=%x\n", (unsigned) current_event.dwProcessId, (unsigned) current_event.dwThreadId)); - handle_exception (ourstatus); + if (handle_exception (ourstatus, debug_threads) + == HANDLE_EXCEPTION_UNHANDLED) + *continue_status = DBG_EXCEPTION_NOT_HANDLED; break; case OUTPUT_DEBUG_STRING_EVENT: @@ -1504,7 +1408,8 @@ while (1) { - if (!get_child_debug_event (ourstatus)) + DWORD continue_status; + if (!get_child_debug_event (&continue_status, ourstatus)) continue; switch (ourstatus->kind) @@ -1527,7 +1432,7 @@ /* fall-through */ case TARGET_WAITKIND_SPURIOUS: /* do nothing, just continue */ - child_continue (DBG_CONTINUE, -1); + child_continue (continue_status, -1); break; } } diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c index 57bbae1..1d76f37 100644 --- a/gdb/nat/windows-nat.c +++ b/gdb/nat/windows-nat.c @@ -18,6 +18,7 @@ #include "gdbsupport/common-defs.h" #include "nat/windows-nat.h" +#include "gdbsupport/common-debug.h" namespace windows_nat { @@ -137,4 +138,159 @@ return buf; } +/* The exception thrown by a program to tell the debugger the name of + a thread. The exception record contains an ID of a thread and a + name to give it. This exception has no documented name, but MSDN + dubs it "MS_VC_EXCEPTION" in one code example. */ +#define MS_VC_EXCEPTION 0x406d1388 + +handle_exception_result +handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions) +{ +#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \ + debug_printf ("gdb: Target exception %s at %s\n", x, \ + host_address_to_string (\ + current_event.u.Exception.ExceptionRecord.ExceptionAddress)) + + EXCEPTION_RECORD *rec = ¤t_event.u.Exception.ExceptionRecord; + DWORD code = rec->ExceptionCode; + handle_exception_result result = HANDLE_EXCEPTION_HANDLED; + + ourstatus->kind = TARGET_WAITKIND_STOPPED; + + /* Record the context of the current thread. */ + thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0), + DONT_SUSPEND); + + switch (code) + { + case EXCEPTION_ACCESS_VIOLATION: + DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION"); + ourstatus->value.sig = GDB_SIGNAL_SEGV; +#ifdef __CYGWIN__ + { + /* See if the access violation happened within the cygwin DLL + itself. Cygwin uses a kind of exception handling to deal + with passed-in invalid addresses. gdb should not treat + these as real SEGVs since they will be silently handled by + cygwin. A real SEGV will (theoretically) be caught by + cygwin later in the process and will be sent as a + cygwin-specific-signal. So, ignore SEGVs if they show up + within the text segment of the DLL itself. */ + const char *fn; + CORE_ADDR addr = (CORE_ADDR) (uintptr_t) rec->ExceptionAddress; + + if ((!cygwin_exceptions && (addr >= cygwin_load_start + && addr < cygwin_load_end)) + || (find_pc_partial_function (addr, &fn, NULL, NULL) + && startswith (fn, "KERNEL32!IsBad"))) + return HANDLE_EXCEPTION_UNHANDLED; + } +#endif + break; + case STATUS_STACK_OVERFLOW: + DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW"); + ourstatus->value.sig = GDB_SIGNAL_SEGV; + break; + case STATUS_FLOAT_DENORMAL_OPERAND: + DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_FLOAT_INEXACT_RESULT: + DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_FLOAT_INVALID_OPERATION: + DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_FLOAT_OVERFLOW: + DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_FLOAT_STACK_CHECK: + DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_FLOAT_UNDERFLOW: + DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_FLOAT_DIVIDE_BY_ZERO: + DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_INTEGER_DIVIDE_BY_ZERO: + DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case STATUS_INTEGER_OVERFLOW: + DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW"); + ourstatus->value.sig = GDB_SIGNAL_FPE; + break; + case EXCEPTION_BREAKPOINT: + DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT"); + ourstatus->value.sig = GDB_SIGNAL_TRAP; +#ifdef _WIN32_WCE + /* Remove the initial breakpoint. */ + check_breakpoints ((CORE_ADDR) (long) current_event + .u.Exception.ExceptionRecord.ExceptionAddress); +#endif + break; + case DBG_CONTROL_C: + DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C"); + ourstatus->value.sig = GDB_SIGNAL_INT; + break; + case DBG_CONTROL_BREAK: + DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK"); + ourstatus->value.sig = GDB_SIGNAL_INT; + break; + case EXCEPTION_SINGLE_STEP: + DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP"); + ourstatus->value.sig = GDB_SIGNAL_TRAP; + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION"); + ourstatus->value.sig = GDB_SIGNAL_ILL; + break; + case EXCEPTION_PRIV_INSTRUCTION: + DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION"); + ourstatus->value.sig = GDB_SIGNAL_ILL; + break; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION"); + ourstatus->value.sig = GDB_SIGNAL_ILL; + break; + case MS_VC_EXCEPTION: + DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION"); + if (handle_ms_vc_exception (rec)) + { + ourstatus->value.sig = GDB_SIGNAL_TRAP; + result = HANDLE_EXCEPTION_IGNORED; + break; + } + /* treat improperly formed exception as unknown */ + /* FALLTHROUGH */ + default: + /* Treat unhandled first chance exceptions specially. */ + if (current_event.u.Exception.dwFirstChance) + return HANDLE_EXCEPTION_UNHANDLED; + debug_printf ("gdb: unknown target exception 0x%08x at %s\n", + (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode, + host_address_to_string ( + current_event.u.Exception.ExceptionRecord.ExceptionAddress)); + ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; + break; + } + + last_sig = ourstatus->value.sig; + return result; + +#undef DEBUG_EXCEPTION_SIMPLE +} + } diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h index 78d0421..5fd6174 100644 --- a/gdb/nat/windows-nat.h +++ b/gdb/nat/windows-nat.h @@ -133,6 +133,16 @@ extern void handle_unload_dll (); +/* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is + somewhat undocumented but is used to tell the debugger the name of + a thread. + + Return true if the exception was handled; return false otherwise. + + This function must be supplied by the embedding application. */ + +extern bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec); + /* Currently executing process */ extern HANDLE current_process_handle; @@ -193,6 +203,16 @@ get_image_name. */ extern const char *get_image_name (HANDLE h, void *address, int unicode); +typedef enum +{ + HANDLE_EXCEPTION_UNHANDLED = 0, + HANDLE_EXCEPTION_HANDLED, + HANDLE_EXCEPTION_IGNORED +} handle_exception_result; + +extern handle_exception_result handle_exception + (struct target_waitstatus *ourstatus, bool debug_exceptions); + } #endif diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index c046f91..8c690b6 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -182,19 +182,6 @@ static int windows_initialization_done; #define DR6_CLEAR_VALUE 0xffff0ff0 -/* The exception thrown by a program to tell the debugger the name of - a thread. The exception record contains an ID of a thread and a - name to give it. This exception has no documented name, but MSDN - dubs it "MS_VC_EXCEPTION" in one code example. */ -#define MS_VC_EXCEPTION 0x406d1388 - -typedef enum -{ - HANDLE_EXCEPTION_UNHANDLED = 0, - HANDLE_EXCEPTION_HANDLED, - HANDLE_EXCEPTION_IGNORED -} handle_exception_result; - /* The string sent by cygwin when it processes a signal. FIXME: This should be in a cygwin include file. */ #ifndef _CYGWIN_SIGNAL_STRING @@ -1067,173 +1054,45 @@ } } -#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \ - printf_unfiltered ("gdb: Target exception %s at %s\n", x, \ - host_address_to_string (\ - current_event.u.Exception.ExceptionRecord.ExceptionAddress)) +/* See nat/windows-nat.h. */ -static handle_exception_result -handle_exception (struct target_waitstatus *ourstatus) +bool +windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec) { - EXCEPTION_RECORD *rec = ¤t_event.u.Exception.ExceptionRecord; - DWORD code = rec->ExceptionCode; - handle_exception_result result = HANDLE_EXCEPTION_HANDLED; - - ourstatus->kind = TARGET_WAITKIND_STOPPED; - - /* Record the context of the current thread. */ - thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0), - DONT_SUSPEND); - - switch (code) + if (rec->NumberParameters >= 3 + && (rec->ExceptionInformation[0] & 0xffffffff) == 0x1000) { - case EXCEPTION_ACCESS_VIOLATION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION"); - ourstatus->value.sig = GDB_SIGNAL_SEGV; -#ifdef __CYGWIN__ - { - /* See if the access violation happened within the cygwin DLL - itself. Cygwin uses a kind of exception handling to deal - with passed-in invalid addresses. gdb should not treat - these as real SEGVs since they will be silently handled by - cygwin. A real SEGV will (theoretically) be caught by - cygwin later in the process and will be sent as a - cygwin-specific-signal. So, ignore SEGVs if they show up - within the text segment of the DLL itself. */ - const char *fn; - CORE_ADDR addr = (CORE_ADDR) (uintptr_t) rec->ExceptionAddress; + DWORD named_thread_id; + windows_thread_info *named_thread; + CORE_ADDR thread_name_target; - if ((!cygwin_exceptions && (addr >= cygwin_load_start - && addr < cygwin_load_end)) - || (find_pc_partial_function (addr, &fn, NULL, NULL) - && startswith (fn, "KERNEL32!IsBad"))) - return HANDLE_EXCEPTION_UNHANDLED; - } -#endif - break; - case STATUS_STACK_OVERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW"); - ourstatus->value.sig = GDB_SIGNAL_SEGV; - break; - case STATUS_FLOAT_DENORMAL_OPERAND: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_INEXACT_RESULT: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_INVALID_OPERATION: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_OVERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_STACK_CHECK: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_UNDERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_FLOAT_DIVIDE_BY_ZERO: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_INTEGER_DIVIDE_BY_ZERO: - DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case STATUS_INTEGER_OVERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW"); - ourstatus->value.sig = GDB_SIGNAL_FPE; - break; - case EXCEPTION_BREAKPOINT: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT"); - ourstatus->value.sig = GDB_SIGNAL_TRAP; - break; - case DBG_CONTROL_C: - DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C"); - ourstatus->value.sig = GDB_SIGNAL_INT; - break; - case DBG_CONTROL_BREAK: - DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK"); - ourstatus->value.sig = GDB_SIGNAL_INT; - break; - case EXCEPTION_SINGLE_STEP: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP"); - ourstatus->value.sig = GDB_SIGNAL_TRAP; - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION"); - ourstatus->value.sig = GDB_SIGNAL_ILL; - break; - case EXCEPTION_PRIV_INSTRUCTION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION"); - ourstatus->value.sig = GDB_SIGNAL_ILL; - break; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION"); - ourstatus->value.sig = GDB_SIGNAL_ILL; - break; - case MS_VC_EXCEPTION: - if (rec->NumberParameters >= 3 - && (rec->ExceptionInformation[0] & 0xffffffff) == 0x1000) + thread_name_target = rec->ExceptionInformation[1]; + named_thread_id = (DWORD) (0xffffffff & rec->ExceptionInformation[2]); + + if (named_thread_id == (DWORD) -1) + named_thread_id = current_event.dwThreadId; + + named_thread = thread_rec (ptid_t (current_event.dwProcessId, + named_thread_id, 0), + DONT_INVALIDATE_CONTEXT); + if (named_thread != NULL) { - DWORD named_thread_id; - windows_thread_info *named_thread; - CORE_ADDR thread_name_target; + int thread_name_len; + gdb::unique_xmalloc_ptr thread_name; - DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION"); - - thread_name_target = rec->ExceptionInformation[1]; - named_thread_id = (DWORD) (0xffffffff & rec->ExceptionInformation[2]); - - if (named_thread_id == (DWORD) -1) - named_thread_id = current_event.dwThreadId; - - named_thread = thread_rec (ptid_t (current_event.dwProcessId, - named_thread_id, 0), - DONT_INVALIDATE_CONTEXT); - if (named_thread != NULL) + thread_name_len = target_read_string (thread_name_target, + &thread_name, 1025, NULL); + if (thread_name_len > 0) { - int thread_name_len; - gdb::unique_xmalloc_ptr thread_name; - - thread_name_len = target_read_string (thread_name_target, - &thread_name, 1025, NULL); - if (thread_name_len > 0) - { - thread_name.get ()[thread_name_len - 1] = '\0'; - named_thread->name = std::move (thread_name); - } + thread_name.get ()[thread_name_len - 1] = '\0'; + named_thread->name = std::move (thread_name); } - ourstatus->value.sig = GDB_SIGNAL_TRAP; - result = HANDLE_EXCEPTION_IGNORED; - break; } - /* treat improperly formed exception as unknown */ - /* FALLTHROUGH */ - default: - /* Treat unhandled first chance exceptions specially. */ - if (current_event.u.Exception.dwFirstChance) - return HANDLE_EXCEPTION_UNHANDLED; - printf_unfiltered ("gdb: unknown target exception 0x%08x at %s\n", - (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode, - host_address_to_string ( - current_event.u.Exception.ExceptionRecord.ExceptionAddress)); - ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; - break; + + return true; } - last_sig = ourstatus->value.sig; - return result; + + return false; } /* Resume thread specified by ID, or all artificially suspended @@ -1644,7 +1503,7 @@ "EXCEPTION_DEBUG_EVENT")); if (saw_create != 1) break; - switch (handle_exception (ourstatus)) + switch (handle_exception (ourstatus, debug_exceptions)) { case HANDLE_EXCEPTION_UNHANDLED: default: