[1/4] Add and implement thread_to_thread_handle

Message ID 20180915221505.00d30923@pinnacle.lan
State New
Headers show
Series
  • Add python method gdb.InferiorThread.thread_handle
Related show

Commit Message

Kevin Buettner Sept. 16, 2018, 5:15 a.m.
This patch adds a thread_to_thread_handle method to the target vector.
It also implements this functionality for remote targets and linux
native threads.

gdb/ChangeLog:
    
    	* gdbthread.h (thread_to_thread_handle): Declare.
    	* thread.c (gdbtypes.h): Include.
    	(thread_to_thread_handle): New function.
    
    	* target.h (struct target_ops): Add thread_info_to_thread_handle.
    	(target_thread_info_to_thread_handle): Declare.
    	* target.c (target_thread_info_to_thread_handle): New function.
    	* target-debug.h, target-delegates.c: Regenerate.
    
    	* linux-thread-db.c (class thread_db_target): Add method
    	thread_info_to_thread_handle.
    	(thread_db_target::thread_info_to_thread_handle): Define.
    	* remote.c (class remote_target): Add new method
    	thread_info_to_thread_handle.
    	(remote_target::thread_info_to_thread_handle): Define.
---
 gdb/gdbthread.h        |  5 +++++
 gdb/linux-thread-db.c  | 19 +++++++++++++++++++
 gdb/remote.c           | 10 ++++++++++
 gdb/target-debug.h     |  2 ++
 gdb/target-delegates.c | 28 ++++++++++++++++++++++++++++
 gdb/target.c           |  6 ++++++
 gdb/target.h           |  6 ++++++
 gdb/thread.c           | 22 ++++++++++++++++++++++
 8 files changed, 98 insertions(+)

Patch

diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 5950512..45a2259 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -459,6 +459,11 @@  struct thread_info *find_thread_by_handle (struct value *thread_handle,
 /* Finds the first thread of the specified inferior.  */
 extern struct thread_info *first_thread_of_inferior (inferior *inf);
 
+/* Return thread handle of type TYPE given thread THR.  Returns NULL if
+   there is no handle and throw an error if there is a size mismatch.  */
+struct value *thread_to_thread_handle (struct thread_info *thr,
+                                       struct type *type);
+
 /* Find thread parent.  */
 struct thread_info * thread_parent (struct thread_info *thread);
 
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index ad193d6..689e0f7 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -105,6 +105,7 @@  public:
   thread_info *thread_handle_to_thread_info (const gdb_byte *thread_handle,
 					     int handle_len,
 					     inferior *inf) override;
+  gdb::byte_vector thread_info_to_thread_handle (struct thread_info *) override;
 };
 
 thread_db_target::thread_db_target ()
@@ -1695,6 +1696,24 @@  thread_db_target::thread_handle_to_thread_info (const gdb_byte *thread_handle,
   return NULL;
 }
 
+/* Return the thread handle associated the thread_info pointer TP.  */
+
+gdb::byte_vector
+thread_db_target::thread_info_to_thread_handle (struct thread_info *tp)
+{
+  thread_db_thread_info *priv = get_thread_db_thread_info (tp);
+
+  if (priv == NULL)
+    return gdb::byte_vector ();
+
+  int handle_size = sizeof (priv->tid);
+  gdb::byte_vector rv (handle_size);
+
+  memcpy (rv.data (), &priv->tid, handle_size);
+
+  return rv;
+}
+
 /* 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.  */
 
diff --git a/gdb/remote.c b/gdb/remote.c
index 3b19da7..e46575d 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -499,6 +499,9 @@  public:
 					     int handle_len,
 					     inferior *inf) override;
 
+  gdb::byte_vector thread_info_to_thread_handle (struct thread_info *tp)
+						 override;
+
   void stop (ptid_t) override;
 
   void interrupt () override;
@@ -14093,6 +14096,13 @@  remote_target::thread_handle_to_thread_info (const gdb_byte *thread_handle,
   return NULL;
 }
 
+gdb::byte_vector
+remote_target::thread_info_to_thread_handle (struct thread_info *tp)
+{
+  remote_thread_info *priv = get_remote_thread_info (tp);
+  return priv->thread_handle;
+}
+
 bool
 remote_target::can_async_p ()
 {
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
index 1e904b9..503482a 100644
--- a/gdb/target-debug.h
+++ b/gdb/target-debug.h
@@ -184,6 +184,8 @@ 
   target_debug_do_print (host_address_to_string (X))
 #define target_debug_print_thread_info_pp(X)		\
   target_debug_do_print (host_address_to_string (X))
+#define target_debug_print_gdb_byte_vector(X)	\
+  target_debug_do_print (host_address_to_string (X.data ()))
 
 static void
 target_debug_print_struct_target_waitstatus_p (struct target_waitstatus *status)
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 03136df..76519f3 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -70,6 +70,7 @@  struct dummy_target : public target_ops
   const char *extra_thread_info (thread_info *arg0) override;
   const char *thread_name (thread_info *arg0) override;
   thread_info *thread_handle_to_thread_info (const gdb_byte *arg0, int arg1, inferior *arg2) override;
+  gdb::byte_vector thread_info_to_thread_handle (struct thread_info *arg0) override;
   void stop (ptid_t arg0) override;
   void interrupt () override;
   void pass_ctrlc () override;
@@ -237,6 +238,7 @@  struct debug_target : public target_ops
   const char *extra_thread_info (thread_info *arg0) override;
   const char *thread_name (thread_info *arg0) override;
   thread_info *thread_handle_to_thread_info (const gdb_byte *arg0, int arg1, inferior *arg2) override;
+  gdb::byte_vector thread_info_to_thread_handle (struct thread_info *arg0) override;
   void stop (ptid_t arg0) override;
   void interrupt () override;
   void pass_ctrlc () override;
@@ -1858,6 +1860,32 @@  debug_target::thread_handle_to_thread_info (const gdb_byte *arg0, int arg1, infe
   return result;
 }
 
+gdb::byte_vector
+target_ops::thread_info_to_thread_handle (struct thread_info *arg0)
+{
+  return this->beneath ()->thread_info_to_thread_handle (arg0);
+}
+
+gdb::byte_vector
+dummy_target::thread_info_to_thread_handle (struct thread_info *arg0)
+{
+  return gdb::byte_vector ();
+}
+
+gdb::byte_vector
+debug_target::thread_info_to_thread_handle (struct thread_info *arg0)
+{
+  gdb::byte_vector result;
+  fprintf_unfiltered (gdb_stdlog, "-> %s->thread_info_to_thread_handle (...)\n", this->beneath ()->shortname ());
+  result = this->beneath ()->thread_info_to_thread_handle (arg0);
+  fprintf_unfiltered (gdb_stdlog, "<- %s->thread_info_to_thread_handle (", this->beneath ()->shortname ());
+  target_debug_print_struct_thread_info_p (arg0);
+  fputs_unfiltered (") = ", gdb_stdlog);
+  target_debug_print_gdb_byte_vector (result);
+  fputs_unfiltered ("\n", gdb_stdlog);
+  return result;
+}
+
 void
 target_ops::stop (ptid_t arg0)
 {
diff --git a/gdb/target.c b/gdb/target.c
index 2d98954..8af2368 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2147,6 +2147,12 @@  target_thread_handle_to_thread_info (const gdb_byte *thread_handle,
 						     handle_len, inf);
 }
 
+gdb::byte_vector
+target_thread_info_to_thread_handle (struct thread_info *tip)
+{
+  return current_top_target ()->thread_info_to_thread_handle (tip);
+}
+
 void
 target_resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
diff --git a/gdb/target.h b/gdb/target.h
index a3000c8..3ee744b 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -658,6 +658,8 @@  struct target_ops
 						       int,
 						       inferior *inf)
       TARGET_DEFAULT_RETURN (NULL);
+    virtual gdb::byte_vector thread_info_to_thread_handle (struct thread_info *)
+      TARGET_DEFAULT_RETURN (gdb::byte_vector ());
     virtual void stop (ptid_t)
       TARGET_DEFAULT_IGNORE ();
     virtual void interrupt ()
@@ -1863,6 +1865,10 @@  extern const char *target_thread_name (struct thread_info *);
 extern struct thread_info *target_thread_handle_to_thread_info
   (const gdb_byte *thread_handle, int handle_len, struct inferior *inf);
 
+/* Given a thread, return the thread handle.  */
+extern gdb::byte_vector target_thread_info_to_thread_handle
+  (struct thread_info *);
+
 /* Attempts to find the pathname of the executable file
    that was run to create a specified process.
 
diff --git a/gdb/thread.c b/gdb/thread.c
index 6c17923..8ac8b97 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -46,6 +46,7 @@ 
 #include <algorithm>
 #include "common/gdb_optional.h"
 #include "extension.h"
+#include "gdbtypes.h"
 
 /* Definition of struct thread_info exported to gdbthread.h.  */
 
@@ -532,6 +533,27 @@  find_thread_by_handle (struct value *thread_handle, struct inferior *inf)
 	    inf);
 }
 
+/* See gdbthread.h.  */
+
+struct value *
+thread_to_thread_handle (struct thread_info *thr, struct type *type)
+{
+  gdb::byte_vector hv = target_thread_info_to_thread_handle (thr);
+
+  if (hv.size () == 0)
+    return NULL;
+
+  check_typedef (type);
+  if (hv.size () != TYPE_LENGTH (type))
+    error (_("Thread handle size mismatch: Expecting %d, got %zu instead"),
+           TYPE_LENGTH (type), hv.size ());
+
+  struct value *rv = allocate_value (type);
+  memcpy (value_contents_raw (rv), hv.data (), hv.size ());
+
+  return rv;
+}
+
 /*
  * Thread iterator function.
  *