diff options
author | Руслан Ижбулатов <lrn1986@gmail.com> | 2016-08-10 19:22:45 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2016-08-10 19:22:45 +0100 |
commit | 24cdb46e9f0a694b4fbc11085e094857f08c0419 (patch) | |
tree | bcd2b884c7e5923934e0bec0fd26f97ab2aecca6 /gdb/windows-nat.c | |
parent | f571390111e28717935ea1b6edd1afc902c5c61c (diff) | |
download | gdb-24cdb46e9f0a694b4fbc11085e094857f08c0419.zip gdb-24cdb46e9f0a694b4fbc11085e094857f08c0419.tar.gz gdb-24cdb46e9f0a694b4fbc11085e094857f08c0419.tar.bz2 |
Support setting thread names (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 new
HANDLE_EXCEPTION_IGNORED value means that gdb should just continue,
without returning the thread ID up the stack (which would result in
further handling of the exception, which is not what we want).
gdb/ChangeLog:
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.
Diffstat (limited to 'gdb/windows-nat.c')
-rw-r--r-- | gdb/windows-nat.c | 93 |
1 files changed, 82 insertions, 11 deletions
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; } |