Pedro Alves has posted comments on this change.
Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/425
......................................................................
Patch Set 1:
(5 comments)
| --- /dev/null
| +++ /COMMIT_MSG
| @@ -1,0 +3,20 @@ Author: Tom Tromey <tromey@adacore.com>
| +AuthorDate: 2019-10-18 13:26:45 -0600
| +Commit: Tom Tromey <tromey@adacore.com>
| +CommitDate: 2019-10-29 10:08:40 -0600
| +
| +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.
PS1, Line 13:
That's:
> (windows_nat::handle_ms_vc_exception): New function.
There's no reason we couldn't just support thread names in gdbserver
as well. It just wasn't done when the original support was added,
left forever stuck as a TODO item. You'd just have to install a
target_ops::thread_name implementation on win32-low.c as well.
| +
| +Change-Id: I4e6e0d17b868cd51964c273fb28ec066fea6b767
| +
| +gdb/ChangeLog
| +2019-10-29 Tom Tromey <tromey@adacore.com>
| +
| + * 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.
| --- gdb/gdbserver/win32-low.c
| +++ gdb/gdbserver/win32-low.c
| @@ -1287,16 +1187,18 @@ /* 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;
PS1, Line 1195:
Given this...
|
| /* Check if GDB sent us an interrupt request. */
| check_remote_input_interrupt_request ();
|
| if (soft_interrupt_requested)
| {
| soft_interrupt_requested = 0;
| fake_breakpoint_event ();
| goto gotevent;
...
| @@ -1499,17 +1403,18 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
| fails). Report it now. */
| *ourstatus = cached_status;
| cached_status.kind = TARGET_WAITKIND_IGNORE;
| return debug_event_ptid (¤t_event);
| }
|
| while (1)
| {
| - if (!get_child_debug_event (ourstatus))
| + DWORD continue_status = DBG_CONTINUE;
PS1, Line 1411:
... this here doesn't appear necessary.
| + if (!get_child_debug_event (&continue_status, ourstatus))
| continue;
|
| switch (ourstatus->kind)
| {
| case TARGET_WAITKIND_EXITED:
| OUTMSG2 (("Child exited with retcode = %x\n",
| ourstatus->value.integer));
| win32_clear_inferiors ();
| --- gdb/nat/windows-nat.h
| +++ gdb/nat/windows-nat.h
| @@ -123,11 +123,19 @@ extern void handle_load_dll ();
| /* Handle a DLL unload event.
|
| This function assumes that this event did not occur during inferior
| initialization.
|
| This function must be supplied by the embedding application. */
|
| extern void handle_unload_dll ();
|
| +/* Handle MS_VC_EXCEPTION when processing a FIXME.
PS1, Line 132:
FIXME?
| +
| + 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 */
...
| @@ -195,4 +203,14 @@ 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);
PS1, Line 212:
Two leading spaces:
extern handle_exception_result handle_exception
(struct target_waitstatus *ourstatus, bool debug_exceptions);
See e.g. extension-priv.h.
| +
| }
|
| #endif
@@ -1,5 +1,19 @@
2019-10-29 Tom Tromey <tromey@adacore.com>
+ * 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-10-29 Tom Tromey <tromey@adacore.com>
+
* windows-nat.c (exception_count, event_count): Remove.
(handle_exception, get_windows_debug_event)
(do_initial_windows_stuff): Update.
@@ -1,5 +1,13 @@
2019-10-29 Tom Tromey <tromey@adacore.com>
+ * 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-10-29 Tom Tromey <tromey@adacore.com>
+
* 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.
@@ -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 = DBG_CONTINUE;
+ 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;
}
}
@@ -18,6 +18,7 @@
#include "gdbsupport/common-defs.h"
#include "nat/windows-nat.h"
+#include "gdbsupport/common-debug.h"
namespace windows_nat
{
@@ -136,4 +137,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
+}
+
}
@@ -129,6 +129,14 @@
extern void handle_unload_dll ();
+/* Handle MS_VC_EXCEPTION when processing a FIXME.
+
+ 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 +201,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
@@ -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
@@ -1042,173 +1029,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<char> 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<char> 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
@@ -1620,7 +1479,7 @@
"EXCEPTION_DEBUG_EVENT"));
if (saw_create != 1)
break;
- switch (handle_exception (ourstatus))
+ switch (handle_exception (ourstatus, debug_exceptions))
{
case HANDLE_EXCEPTION_UNHANDLED:
default: