diff options
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/NEWS | 6 | ||||
-rw-r--r-- | gdb/windows-nat.c | 93 |
3 files changed, 100 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a1865f9..843da83 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2016-08-10 Руслан Ижбулатов <lrn1986@gmail.com> + Pedro Alves <palves@redhat.com> + + * windows-nat.c (MS_VC_EXCEPTION): New define. + (handle_exception_result): New enum. + (windows_delete_thread): Free the thread's name. + (handle_exception): Handle MS_VC_EXCEPTION. + (get_windows_debug_event): Handle HANDLE_EXCEPTION_IGNORED. + (windows_thread_name): New function. + (windows_target): Install it as to_thread_name method. + * NEWS: Mention the thread naming support on MS-Windows. + 2016-08-10 Pedro Alves <palves@redhat.com> * common/signals-state-save-restore.c @@ -3,6 +3,12 @@ *** Changes since GDB 7.12 +* Support for thread names on MS-Windows. + + GDB now catches and handles the special exception that programs + running on MS-Windows use to assign names to threads in the + debugger. + *** Changes in GDB 7.12 * GDB and GDBserver now build with a C++ compiler by default. diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 3f67486..0470f31 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -174,6 +174,19 @@ 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 @@ -441,6 +454,7 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code) { windows_thread_info *here = th->next; th->next = here->next; + xfree (here->name); xfree (here); } } @@ -1031,10 +1045,12 @@ display_selectors (char * args, int from_tty) host_address_to_string (\ current_event.u.Exception.ExceptionRecord.ExceptionAddress)) -static int +static handle_exception_result handle_exception (struct target_waitstatus *ourstatus) { - DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode; + EXCEPTION_RECORD *rec = ¤t_event.u.Exception.ExceptionRecord; + DWORD code = rec->ExceptionCode; + handle_exception_result result = HANDLE_EXCEPTION_HANDLED; ourstatus->kind = TARGET_WAITKIND_STOPPED; @@ -1057,14 +1073,13 @@ handle_exception (struct target_waitstatus *ourstatus) 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) - current_event.u.Exception.ExceptionRecord.ExceptionAddress; + 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 0; + return HANDLE_EXCEPTION_UNHANDLED; } #endif break; @@ -1140,10 +1155,48 @@ handle_exception (struct target_waitstatus *ourstatus) 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; + + 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 (named_thread_id, 0); + if (named_thread != NULL) + { + int thread_name_len; + char *thread_name; + + thread_name_len = target_read_string (thread_name_target, + &thread_name, 1025, NULL); + if (thread_name_len > 0) + { + thread_name[thread_name_len - 1] = '\0'; + xfree (named_thread->name); + named_thread->name = thread_name; + } + else + xfree (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 0; + 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 ( @@ -1153,7 +1206,7 @@ handle_exception (struct target_waitstatus *ourstatus) } exception_count++; last_sig = ourstatus->value.sig; - return 1; + return result; } /* Resume thread specified by ID, or all artificially suspended @@ -1510,10 +1563,19 @@ get_windows_debug_event (struct target_ops *ops, "EXCEPTION_DEBUG_EVENT")); if (saw_create != 1) break; - if (handle_exception (ourstatus)) - thread_id = current_event.dwThreadId; - else - continue_status = DBG_EXCEPTION_NOT_HANDLED; + switch (handle_exception (ourstatus)) + { + case HANDLE_EXCEPTION_UNHANDLED: + default: + continue_status = DBG_EXCEPTION_NOT_HANDLED; + break; + case HANDLE_EXCEPTION_HANDLED: + thread_id = current_event.dwThreadId; + break; + case HANDLE_EXCEPTION_IGNORED: + continue_status = DBG_CONTINUE; + break; + } break; case OUTPUT_DEBUG_STRING_EVENT: /* Message from the kernel. */ @@ -2514,6 +2576,14 @@ windows_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp); } +/* Implementation of the to_thread_name method. */ + +static const char * +windows_thread_name (struct target_ops *self, struct thread_info *thr) +{ + return thread_rec (ptid_get_tid (thr->ptid), 0)->name; +} + static struct target_ops * windows_target (void) { @@ -2538,6 +2608,7 @@ windows_target (void) t->to_pid_to_exec_file = windows_pid_to_exec_file; t->to_get_ada_task_ptid = windows_get_ada_task_ptid; t->to_get_tib_address = windows_get_tib_address; + t->to_thread_name = windows_thread_name; return t; } |