253 lines
8.4 KiB
Diff
253 lines
8.4 KiB
Diff
From 7d9da3e5dcae68c4838ca0726ec672fba375bc4a 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?= <lrn1986@gmail.com>
|
|
Date: Wed, 10 Aug 2016 19:22:45 +0100
|
|
Subject: [PATCH 4/4] Support setting thread names (MS-Windows)
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
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).
|
|
|
|
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.
|
|
---
|
|
gdb/ChangeLog | 12 +++++++
|
|
gdb/NEWS | 8 +++++
|
|
gdb/windows-nat.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++-------
|
|
3 files changed, 102 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
|
|
index 6082ebb..732212f 100644
|
|
--- a/gdb/ChangeLog
|
|
+++ b/gdb/ChangeLog
|
|
@@ -2191,6 +2191,18 @@
|
|
* remote-fileio.c (remote_fileio_ctrl_c_signal_handler): Call
|
|
quit_serial_event_set.
|
|
|
|
+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-06-01 Joel Brobecker <brobecker@adacore.com>
|
|
|
|
GDB 7.11.1 released.
|
|
diff --git a/gdb/NEWS b/gdb/NEWS
|
|
index a568367..2d602a1 100644
|
|
--- a/gdb/NEWS
|
|
+++ b/gdb/NEWS
|
|
@@ -1,6 +1,14 @@
|
|
What has changed in GDB?
|
|
(Organized release by release)
|
|
|
|
+*** Changes since GDB 7.11
|
|
+
|
|
+* 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.11
|
|
|
|
* GDB now supports debugging kernel-based threads on FreeBSD.
|
|
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
|
|
index b477cc1..2b75b08 100644
|
|
--- a/gdb/windows-nat.c
|
|
+++ b/gdb/windows-nat.c
|
|
@@ -172,6 +172,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
|
|
@@ -440,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);
|
|
}
|
|
}
|
|
@@ -1029,10 +1043,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;
|
|
|
|
@@ -1056,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;
|
|
@@ -1139,10 +1154,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 (
|
|
@@ -1152,7 +1205,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
|
|
@@ -1508,10 +1561,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. */
|
|
@@ -2512,6 +2574,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)
|
|
{
|
|
@@ -2536,6 +2606,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;
|
|
}
|
|
--
|
|
2.8.3
|
|
|