diff options
author | Tom Tromey <tromey@adacore.com> | 2020-04-08 14:33:35 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2020-04-08 14:47:59 -0600 |
commit | 8d30e395779603a8d36fa8bdfddba88a312552f4 (patch) | |
tree | 469d9065623bf700d4a4fa02988fc58f415f9195 /gdb/windows-nat.c | |
parent | 29de418deeac717886df20ef0419240aa0dfc32a (diff) | |
download | gdb-8d30e395779603a8d36fa8bdfddba88a312552f4.zip gdb-8d30e395779603a8d36fa8bdfddba88a312552f4.tar.gz gdb-8d30e395779603a8d36fa8bdfddba88a312552f4.tar.bz2 |
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
2020-04-08 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.
(STATUS_WX86_BREAKPOINT, STATUS_WX86_SINGLE_STEP): Move to
nat/windows-nat.c.
* 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)
(STATUS_WX86_SINGLE_STEP, STATUS_WX86_BREAKPOINT): Move from
windows-nat.c.
gdbserver/ChangeLog
2020-04-08 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.
Diffstat (limited to 'gdb/windows-nat.c')
-rw-r--r-- | gdb/windows-nat.c | 218 |
1 files changed, 29 insertions, 189 deletions
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index eb55025..d48f90a 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -72,9 +72,6 @@ #include "gdbsupport/gdb_wait.h" #include "nat/windows-nat.h" -#define STATUS_WX86_BREAKPOINT 0x4000001F -#define STATUS_WX86_SINGLE_STEP 0x4000001E - using namespace windows_nat; #define AdjustTokenPrivileges dyn_AdjustTokenPrivileges @@ -213,19 +210,6 @@ static int debug_registers_used; 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 @@ -1203,189 +1187,45 @@ display_selectors (const char * args, int from_tty) } } -#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; - - memcpy (&siginfo_er, rec, sizeof siginfo_er); - - 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; - - 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: -#ifdef __x86_64__ - if (ignore_first_breakpoint) - { - /* For WOW64 processes, there are always 2 breakpoint exceptions - on startup, first a BREAKPOINT for the 64bit ntdll.dll, - then a WX86_BREAKPOINT for the 32bit ntdll.dll. - Here we only care about the WX86_BREAKPOINT's. */ - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - ignore_first_breakpoint = false; - } -#endif - /* FALLTHROUGH */ - case STATUS_WX86_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: - case STATUS_WX86_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) - { - DWORD named_thread_id; - windows_thread_info *named_thread; - CORE_ADDR thread_name_target; + DWORD named_thread_id; + windows_thread_info *named_thread; + CORE_ADDR thread_name_target; - DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION"); + thread_name_target = rec->ExceptionInformation[1]; + named_thread_id = (DWORD) (0xffffffff & rec->ExceptionInformation[2]); - 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; - 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) + { + int thread_name_len; + gdb::unique_xmalloc_ptr<char> thread_name; - 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 @@ -1876,7 +1716,7 @@ windows_nat_target::get_windows_debug_event (int pid, "EXCEPTION_DEBUG_EVENT")); if (saw_create != 1) break; - switch (handle_exception (ourstatus)) + switch (handle_exception (ourstatus, debug_exceptions)) { case HANDLE_EXCEPTION_UNHANDLED: default: |