Add target method for converting thread handle to thread_info struct pointer

This patch adds a target method named `to_thread_handle_to_thread_info'.
It is intended to map a thread library specific thread handle (such as
pthread_t for the pthread library) to the corresponding GDB internal
thread_info struct (pointer).

An implementation is provided for Linux pthreads; see linux-thread-db.c.

gdb/ChangeLog:

	* target.h (struct target_ops): Add to_thread_handle_to_thread_info.
	(target_thread_handle_to_thread_info): Declare.
	* target.c (target_thread_handle_to_thread_info): New function.
	* target-delegates.c: Regenerate.
	* gdbthread.h (find_thread_by_handle): Declare.
	* thread.c (find_thread_by_handle): New function.
	* linux-thread-db.c (thread_db_thread_handle_to_thread_info): New
	function.
	(init_thread_db_ops): Register thread_db_thread_handle_to_thread_info.
This commit is contained in:
Kevin Buettner 2016-05-04 15:21:12 -07:00
parent f557a88ab1
commit e04ee09e24
7 changed files with 117 additions and 0 deletions

View file

@ -1,3 +1,15 @@
2017-09-21 Kevin Buettner <kevinb@redhat.com>
* target.h (struct target_ops): Add to_thread_handle_to_thread_info.
(target_thread_handle_to_thread_info): Declare.
* target.c (target_thread_handle_to_thread_info): New function.
* target-delegates.c: Regenerate.
* gdbthread.h (find_thread_by_handle): Declare.
* thread.c (find_thread_by_handle): New function.
* linux-thread-db.c (thread_db_thread_handle_to_thread_info): New
function.
(init_thread_db_ops): Register thread_db_thread_handle_to_thread_info.
2017-09-21 Simon Marchi <simon.marchi@ericsson.com> 2017-09-21 Simon Marchi <simon.marchi@ericsson.com>
* nat/linux-waitpid.c (linux_debug): Add ATTRIBUTE_PRINTF. * nat/linux-waitpid.c (linux_debug): Add ATTRIBUTE_PRINTF.

View file

@ -448,6 +448,10 @@ extern struct thread_info *find_thread_ptid (ptid_t ptid);
/* Find thread by GDB global thread ID. */ /* Find thread by GDB global thread ID. */
struct thread_info *find_thread_global_id (int global_id); struct thread_info *find_thread_global_id (int global_id);
/* Find thread by thread library specific handle in inferior INF. */
struct thread_info *find_thread_by_handle (struct value *thread_handle,
struct inferior *inf);
/* Finds the first thread of the inferior given by PID. If PID is -1, /* Finds the first thread of the inferior given by PID. If PID is -1,
returns the first thread in the list. */ returns the first thread in the list. */
struct thread_info *first_thread_of_process (int pid); struct thread_info *first_thread_of_process (int pid);

View file

@ -1410,6 +1410,37 @@ thread_db_extra_thread_info (struct target_ops *self,
return NULL; return NULL;
} }
/* Return pointer to the thread_info struct which corresponds to
THREAD_HANDLE (having length HANDLE_LEN). */
static struct thread_info *
thread_db_thread_handle_to_thread_info (struct target_ops *ops,
const gdb_byte *thread_handle,
int handle_len,
struct inferior *inf)
{
struct thread_info *tp;
thread_t handle_tid;
/* Thread handle sizes must match in order to proceed. We don't use an
assert here because the resulting internal error will cause GDB to
exit. This isn't necessarily an internal error due to the possibility
of garbage being passed as the thread handle via the python interface. */
if (handle_len != sizeof (handle_tid))
error (_("Thread handle size mismatch: %d vs %zu (from libthread_db)"),
handle_len, sizeof (handle_tid));
handle_tid = * (const thread_t *) thread_handle;
ALL_NON_EXITED_THREADS (tp)
{
if (tp->inf == inf && tp->priv != NULL && handle_tid == tp->priv->tid)
return tp;
}
return NULL;
}
/* Get the address of the thread local variable in load module LM which /* Get the address of the thread local variable in load module LM which
is stored at OFFSET within the thread local storage for thread PTID. */ is stored at OFFSET within the thread local storage for thread PTID. */
@ -1691,6 +1722,7 @@ init_thread_db_ops (void)
= thread_db_get_thread_local_address; = thread_db_get_thread_local_address;
thread_db_ops.to_extra_thread_info = thread_db_extra_thread_info; thread_db_ops.to_extra_thread_info = thread_db_extra_thread_info;
thread_db_ops.to_get_ada_task_ptid = thread_db_get_ada_task_ptid; thread_db_ops.to_get_ada_task_ptid = thread_db_get_ada_task_ptid;
thread_db_ops.to_thread_handle_to_thread_info = thread_db_thread_handle_to_thread_info;
thread_db_ops.to_magic = OPS_MAGIC; thread_db_ops.to_magic = OPS_MAGIC;
complete_target_initialization (&thread_db_ops); complete_target_initialization (&thread_db_ops);

View file

@ -1583,6 +1583,39 @@ debug_thread_name (struct target_ops *self, struct thread_info *arg1)
return result; return result;
} }
static struct thread_info *
delegate_thread_handle_to_thread_info (struct target_ops *self, const gdb_byte *arg1, int arg2, struct inferior *arg3)
{
self = self->beneath;
return self->to_thread_handle_to_thread_info (self, arg1, arg2, arg3);
}
static struct thread_info *
tdefault_thread_handle_to_thread_info (struct target_ops *self, const gdb_byte *arg1, int arg2, struct inferior *arg3)
{
return NULL;
}
static struct thread_info *
debug_thread_handle_to_thread_info (struct target_ops *self, const gdb_byte *arg1, int arg2, struct inferior *arg3)
{
struct thread_info * result;
fprintf_unfiltered (gdb_stdlog, "-> %s->to_thread_handle_to_thread_info (...)\n", debug_target.to_shortname);
result = debug_target.to_thread_handle_to_thread_info (&debug_target, arg1, arg2, arg3);
fprintf_unfiltered (gdb_stdlog, "<- %s->to_thread_handle_to_thread_info (", debug_target.to_shortname);
target_debug_print_struct_target_ops_p (&debug_target);
fputs_unfiltered (", ", gdb_stdlog);
target_debug_print_const_gdb_byte_p (arg1);
fputs_unfiltered (", ", gdb_stdlog);
target_debug_print_int (arg2);
fputs_unfiltered (", ", gdb_stdlog);
target_debug_print_struct_inferior_p (arg3);
fputs_unfiltered (") = ", gdb_stdlog);
target_debug_print_struct_thread_info_p (result);
fputs_unfiltered ("\n", gdb_stdlog);
return result;
}
static void static void
delegate_stop (struct target_ops *self, ptid_t arg1) delegate_stop (struct target_ops *self, ptid_t arg1)
{ {
@ -4267,6 +4300,8 @@ install_delegators (struct target_ops *ops)
ops->to_extra_thread_info = delegate_extra_thread_info; ops->to_extra_thread_info = delegate_extra_thread_info;
if (ops->to_thread_name == NULL) if (ops->to_thread_name == NULL)
ops->to_thread_name = delegate_thread_name; ops->to_thread_name = delegate_thread_name;
if (ops->to_thread_handle_to_thread_info == NULL)
ops->to_thread_handle_to_thread_info = delegate_thread_handle_to_thread_info;
if (ops->to_stop == NULL) if (ops->to_stop == NULL)
ops->to_stop = delegate_stop; ops->to_stop = delegate_stop;
if (ops->to_interrupt == NULL) if (ops->to_interrupt == NULL)
@ -4522,6 +4557,7 @@ install_dummy_methods (struct target_ops *ops)
ops->to_pid_to_str = default_pid_to_str; ops->to_pid_to_str = default_pid_to_str;
ops->to_extra_thread_info = tdefault_extra_thread_info; ops->to_extra_thread_info = tdefault_extra_thread_info;
ops->to_thread_name = tdefault_thread_name; ops->to_thread_name = tdefault_thread_name;
ops->to_thread_handle_to_thread_info = tdefault_thread_handle_to_thread_info;
ops->to_stop = tdefault_stop; ops->to_stop = tdefault_stop;
ops->to_interrupt = tdefault_interrupt; ops->to_interrupt = tdefault_interrupt;
ops->to_pass_ctrlc = default_target_pass_ctrlc; ops->to_pass_ctrlc = default_target_pass_ctrlc;
@ -4681,6 +4717,7 @@ init_debug_target (struct target_ops *ops)
ops->to_pid_to_str = debug_pid_to_str; ops->to_pid_to_str = debug_pid_to_str;
ops->to_extra_thread_info = debug_extra_thread_info; ops->to_extra_thread_info = debug_extra_thread_info;
ops->to_thread_name = debug_thread_name; ops->to_thread_name = debug_thread_name;
ops->to_thread_handle_to_thread_info = debug_thread_handle_to_thread_info;
ops->to_stop = debug_stop; ops->to_stop = debug_stop;
ops->to_interrupt = debug_interrupt; ops->to_interrupt = debug_interrupt;
ops->to_pass_ctrlc = debug_pass_ctrlc; ops->to_pass_ctrlc = debug_pass_ctrlc;

View file

@ -2244,6 +2244,15 @@ target_thread_name (struct thread_info *info)
return current_target.to_thread_name (&current_target, info); return current_target.to_thread_name (&current_target, info);
} }
struct thread_info *
target_thread_handle_to_thread_info (const gdb_byte *thread_handle,
int handle_len,
struct inferior *inf)
{
return current_target.to_thread_handle_to_thread_info
(&current_target, thread_handle, handle_len, inf);
}
void void
target_resume (ptid_t ptid, int step, enum gdb_signal signal) target_resume (ptid_t ptid, int step, enum gdb_signal signal)
{ {

View file

@ -644,6 +644,11 @@ struct target_ops
TARGET_DEFAULT_RETURN (NULL); TARGET_DEFAULT_RETURN (NULL);
const char *(*to_thread_name) (struct target_ops *, struct thread_info *) const char *(*to_thread_name) (struct target_ops *, struct thread_info *)
TARGET_DEFAULT_RETURN (NULL); TARGET_DEFAULT_RETURN (NULL);
struct thread_info *(*to_thread_handle_to_thread_info) (struct target_ops *,
const gdb_byte *,
int,
struct inferior *inf)
TARGET_DEFAULT_RETURN (NULL);
void (*to_stop) (struct target_ops *, ptid_t) void (*to_stop) (struct target_ops *, ptid_t)
TARGET_DEFAULT_IGNORE (); TARGET_DEFAULT_IGNORE ();
void (*to_interrupt) (struct target_ops *, ptid_t) void (*to_interrupt) (struct target_ops *, ptid_t)
@ -1828,6 +1833,12 @@ extern const char *normal_pid_to_str (ptid_t ptid);
extern const char *target_thread_name (struct thread_info *); extern const char *target_thread_name (struct thread_info *);
/* Given a pointer to a thread library specific thread handle and
its length, return a pointer to the corresponding thread_info struct. */
extern struct thread_info *target_thread_handle_to_thread_info
(const gdb_byte *thread_handle, int handle_len, struct inferior *inf);
/* Attempts to find the pathname of the executable file /* Attempts to find the pathname of the executable file
that was run to create a specified process. that was run to create a specified process.

View file

@ -519,6 +519,7 @@ find_thread_id (struct inferior *inf, int thr_num)
} }
/* Find a thread_info by matching PTID. */ /* Find a thread_info by matching PTID. */
struct thread_info * struct thread_info *
find_thread_ptid (ptid_t ptid) find_thread_ptid (ptid_t ptid)
{ {
@ -531,6 +532,17 @@ find_thread_ptid (ptid_t ptid)
return NULL; return NULL;
} }
/* See gdbthread.h. */
struct thread_info *
find_thread_by_handle (struct value *thread_handle, struct inferior *inf)
{
return target_thread_handle_to_thread_info
(value_contents_all (thread_handle),
TYPE_LENGTH (value_type (thread_handle)),
inf);
}
/* /*
* Thread iterator function. * Thread iterator function.
* *