From 34c05e6eb6e9d94700f8dc9695a214fdf6fabaea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1?= =?UTF-8?q?=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= Date: Sun, 26 Jun 2016 11:14:49 +0000 Subject: [PATCH 1/3] Support settings thread name (MS-Windows) This is done by catching an exception number 0x406D1388 (it has no documented name, though MSDN dubs it "MS_VC_EXCEPTION" in one code example), which is thrown by the program. The exception record contains an ID of a thread and a name to give it. This requires rolling back some changes in handle_exception(), which now again returns more than two distinct values. The value HANDLE_EXCEPTION_IGNORED means that gdb should just continue, without returning thread ID up the stack (which will result in further handling of the exception, which is not what we want). --- gdb/windows-nat.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 107 insertions(+), 14 deletions(-) diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 3f67486..6315303 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -174,6 +174,18 @@ static int debug_registers_used; static int windows_initialization_done; #define DR6_CLEAR_VALUE 0xffff0ff0 +/* This exception has no documented name, but MSDN dubs it "MS_VC_EXCEPTION" + in one code example. It's thrown by a program to tell the debugger the name + of a thread. */ +#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 +453,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 +1044,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 +1072,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,20 +1154,64 @@ 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) + { + long named_thread_id; + windows_thread_info *named_windows_thread; + CORE_ADDR thread_name_target; + char *thread_name; + int thread_name_len; + + DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION"); + + named_thread_id = (long) (0xffffffff & rec->ExceptionInformation[2]); + thread_name_target = rec->ExceptionInformation[1]; + + if (named_thread_id == (DWORD) -1) + named_thread_id = current_event.dwThreadId; + + named_windows_thread = thread_rec (named_thread_id, 0); + + thread_name = NULL; + thread_name_len = 0; + + if (named_windows_thread != NULL) + thread_name_len = target_read_string (thread_name_target, + &thread_name, 1025, 0); + + if (thread_name_len > 0 && thread_name != NULL) + { + thread_name[thread_name_len - 1] = '\0'; + if (thread_name[0] != '\0') + { + xfree (named_windows_thread->name); + named_windows_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 ( - current_event.u.Exception.ExceptionRecord.ExceptionAddress)); + (unsigned) rec->ExceptionCode, + host_address_to_string (rec->ExceptionAddress)); ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; break; } exception_count++; last_sig = ourstatus->value.sig; - return 1; + return result; } /* Resume thread specified by ID, or all artificially suspended @@ -1510,10 +1568,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 +2581,31 @@ windows_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp); } +static const char * +windows_get_thread_name (struct target_ops *self, struct thread_info *thr) +{ + struct thread_info *threadinfo; + windows_thread_info *windows_threadinfo; + DWORD id = ptid_get_tid (thr->ptid); + char *name; + + name = NULL; + threadinfo = find_thread_ptid (thr->ptid); + + if (threadinfo != NULL) + name = threadinfo->name; + + if (name == NULL && id != 0) + { + windows_threadinfo = thread_rec (id, 0); + + if (windows_threadinfo != NULL) + name = windows_threadinfo->name; + } + + return (const char *) name; +} + static struct target_ops * windows_target (void) { @@ -2538,6 +2630,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_get_thread_name; return t; } -- 2.4.0