This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Implement qGetTLSAddr for gdbserver


Something I've been meaning to do for ages; this patch fixes the TLS
tests when using gdbserver on GNU/Linux.  Tested and committed.

-- 
Daniel Jacobowitz
CodeSourcery

2006-10-17  Daniel Jacobowitz  <dan@codesourcery.com>

	* acinclude.m4 (SRV_CHECK_TLS_GET_ADDR): New.
	* configure.ac: Use it.  Define HAVE_TD_THR_TLS_GET_ADDR.
	* config.in, configure: Regenerated.
	* inferiors.c (gdb_id_to_thread): New function.
	(gdb_id_to_thread_id): Use it.
	* linux-low.c (linux_target_ops): Use thread_db_get_tls_address.
	* linux-low.h (struct process_info): Add th member.
	(thread_db_get_tls_address): New prototype.
	* remote-utils.c (decode_address): Make non-static.
	* server.c (handle_query): Handle qGetTLSAddr.
	* server.h (gdb_id_to_thread, decode_address): New prototypes.
	* target.h (struct target_ops): Add get_tls_address.
	* thread-db.c (maybe_attach_thread): Save the thread handle.
	(thread_db_get_tls_address): New.

Index: acinclude.m4
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/acinclude.m4,v
retrieving revision 1.4
diff -u -p -r1.4 acinclude.m4
--- acinclude.m4	17 Sep 2005 23:14:37 -0000	1.4
+++ acinclude.m4	17 Oct 2006 15:56:42 -0000
@@ -41,3 +41,23 @@ AC_DEFUN([SRV_CHECK_THREAD_DB],
   ])
  LIBS="$old_LIBS"
 ])])
+
+AC_DEFUN([SRV_CHECK_TLS_GET_ADDR],
+[AC_CACHE_CHECK([for thread_db_tls_get_addr],[srv_cv_tls_get_addr],
+ [old_LIBS="$LIBS"
+  LIBS="$LIBS $srv_cv_thread_db"
+  AC_TRY_LINK(
+   [void ps_pglobal_lookup() {}
+    void ps_pdread() {}
+    void ps_pdwrite() {}
+    void ps_lgetregs() {}
+    void ps_lsetregs() {}
+    void ps_lgetfpregs() {}
+    void ps_lsetfpregs() {}
+    void ps_get_thread_area() {}
+    void ps_getpid() {}],
+   [td_thr_tls_get_addr();],
+   [srv_cv_tls_get_addr=yes],
+   [srv_cv_tls_get_addr=no])
+  LIBS="$old_LIBS"
+])])
Index: configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/configure.ac,v
retrieving revision 1.10
diff -u -p -r1.10 configure.ac
--- configure.ac	23 Jul 2006 03:52:15 -0000	1.10
+++ configure.ac	17 Oct 2006 15:56:43 -0000
@@ -115,6 +115,7 @@ if test "$srv_linux_thread_db" = "yes"; 
     srv_linux_thread_db=no
   else
     srv_libs="$srv_cv_thread_db"
+    SRV_CHECK_TLS_GET_ADDR
   fi
   old_LDFLAGS="$LDFLAGS"
   LDFLAGS="$LDFLAGS -rdynamic"
@@ -133,6 +134,10 @@ if test "$srv_linux_thread_db" = "yes"; 
   if test $gdbsrv_cv_have_td_version = yes; then
     AC_DEFINE(HAVE_TD_VERSION, 1, [Define if TD_VERSION is available.])
   fi
+
+  if test "$srv_cv_tls_get_addr"; then
+    AC_DEFINE(HAVE_TD_THR_TLS_GET_ADDR, 1, [Define if td_thr_tls_get_addr is available.])
+  fi
 fi
 
 GDBSERVER_DEPFILES="$srv_regobj $srv_tgtobj $srv_thread_depfiles"
Index: inferiors.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/inferiors.c,v
retrieving revision 1.7
diff -u -p -r1.7 inferiors.c
--- inferiors.c	23 Dec 2005 18:11:55 -0000	1.7
+++ inferiors.c	17 Oct 2006 15:56:43 -0000
@@ -144,8 +144,8 @@ thread_to_gdb_id (struct thread_info *th
   return thread->gdb_id;
 }
 
-unsigned long
-gdb_id_to_thread_id (unsigned int gdb_id)
+struct thread_info *
+gdb_id_to_thread (unsigned int gdb_id)
 {
   struct inferior_list_entry *inf = all_threads.head;
 
@@ -153,11 +153,19 @@ gdb_id_to_thread_id (unsigned int gdb_id
     {
       struct thread_info *thread = get_thread (inf);
       if (thread->gdb_id == gdb_id)
-	return inf->id;
+	return thread;
       inf = inf->next;
     }
 
-  return 0;
+  return NULL;
+}
+
+unsigned long
+gdb_id_to_thread_id (unsigned int gdb_id)
+{
+  struct thread_info *thread = gdb_id_to_thread (gdb_id);
+
+  return thread ? thread->entry.id : 0;
 }
 
 static void
Index: linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.46
diff -u -p -r1.46 linux-low.c
--- linux-low.c	28 Sep 2006 22:46:29 -0000	1.46
+++ linux-low.c	17 Oct 2006 15:56:43 -0000
@@ -1652,6 +1652,13 @@ static struct target_ops linux_target_op
   linux_stopped_data_address,
 #if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
   linux_read_offsets,
+#else
+  NULL,
+#endif
+#ifdef USE_THREAD_DB
+  thread_db_get_tls_address,
+#else
+  NULL,
 #endif
 };
 
Index: linux-low.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.h,v
retrieving revision 1.13
diff -u -p -r1.13 linux-low.h
--- linux-low.h	28 Sep 2006 22:46:29 -0000	1.13
+++ linux-low.h	17 Oct 2006 15:56:43 -0000
@@ -18,6 +18,10 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.  */
 
+#ifdef HAVE_THREAD_DB_H
+#include <thread_db.h>
+#endif
+
 #ifdef HAVE_LINUX_REGSETS
 typedef void (*regset_fill_func) (void *);
 typedef void (*regset_store_func) (const void *);
@@ -124,6 +128,11 @@ struct process_info
      and then processed and cleared in linux_resume_one_process.  */
 
   struct thread_resume *resume;
+
+#ifdef HAVE_THREAD_DB_H
+  /* The thread handle, used for e.g. TLS access.  */
+  td_thrhandle_t th;
+#endif
 };
 
 extern struct inferior_list all_processes;
@@ -131,3 +140,5 @@ extern struct inferior_list all_processe
 void linux_attach_lwp (unsigned long pid, unsigned long tid);
 
 int thread_db_init (void);
+int thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
+			       CORE_ADDR load_module, CORE_ADDR *address);
Index: remote-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/remote-utils.c,v
retrieving revision 1.32
diff -u -p -r1.32 remote-utils.c
--- remote-utils.c	21 Sep 2006 16:09:54 -0000	1.32
+++ remote-utils.c	17 Oct 2006 15:56:43 -0000
@@ -279,7 +279,7 @@ unhexify (char *bin, const char *hex, in
   return i;
 }
 
-static void
+void
 decode_address (CORE_ADDR *addrp, const char *start, int len)
 {
   CORE_ADDR addr;
Index: server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.39
diff -u -p -r1.39 server.c
--- server.c	8 Aug 2006 16:03:29 -0000	1.39
+++ server.c	17 Oct 2006 15:56:43 -0000
@@ -254,6 +254,65 @@ handle_query (char *own_buf, int *new_pa
       return;
     }
 
+  /* Thread-local storage support.  */
+  if (the_target->get_tls_address != NULL
+      && strncmp ("qGetTLSAddr:", own_buf, 12) == 0)
+    {
+      char *p = own_buf + 12;
+      CORE_ADDR parts[3], address = 0;
+      int i, err;
+
+      for (i = 0; i < 3; i++)
+	{
+	  char *p2;
+	  int len;
+
+	  if (p == NULL)
+	    break;
+
+	  p2 = strchr (p, ',');
+	  if (p2)
+	    {
+	      len = p2 - p;
+	      p2++;
+	    }
+	  else
+	    {
+	      len = strlen (p);
+	      p2 = NULL;
+	    }
+
+	  decode_address (&parts[i], p, len);
+	  p = p2;
+	}
+
+      if (p != NULL || i < 3)
+	err = 1;
+      else
+	{
+	  struct thread_info *thread = gdb_id_to_thread (parts[0]);
+
+	  if (thread == NULL)
+	    err = 2;
+	  else
+	    err = the_target->get_tls_address (thread, parts[1], parts[2],
+					       &address);
+	}
+
+      if (err == 0)
+	{
+	  sprintf (own_buf, "%llx", address);
+	  return;
+	}
+      else if (err > 0)
+	{
+	  write_enn (own_buf);
+	  return;
+	}
+
+      /* Otherwise, pretend we do not understand this packet.  */
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
Index: server.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.h,v
retrieving revision 1.25
diff -u -p -r1.25 server.h
--- server.h	23 Jul 2006 03:52:15 -0000	1.25
+++ server.h	17 Oct 2006 15:56:43 -0000
@@ -105,6 +105,7 @@ void add_thread (unsigned long thread_id
 unsigned int thread_id_to_gdb_id (unsigned long);
 unsigned int thread_to_gdb_id (struct thread_info *);
 unsigned long gdb_id_to_thread_id (unsigned int);
+struct thread_info *gdb_id_to_thread (unsigned int);
 void clear_inferiors (void);
 struct inferior_list_entry *find_inferior
      (struct inferior_list *,
@@ -152,6 +153,7 @@ void new_thread_notify (int id);
 void dead_thread_notify (int id);
 void prepare_resume_reply (char *buf, char status, unsigned char sig);
 
+void decode_address (CORE_ADDR *addrp, const char *start, int len);
 void decode_m_packet (char *from, CORE_ADDR * mem_addr_ptr,
 		      unsigned int *len_ptr);
 void decode_M_packet (char *from, CORE_ADDR * mem_addr_ptr,
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.h,v
retrieving revision 1.17
diff -u -p -r1.17 target.h
--- target.h	23 Jul 2006 03:52:15 -0000	1.17
+++ target.h	17 Oct 2006 15:56:43 -0000
@@ -163,6 +163,15 @@ struct target_ops
      time.  */
   
   int (*read_offsets) (CORE_ADDR *text, CORE_ADDR *data);
+
+  /* Fetch the address associated with a specific thread local storage
+     area, determined by the specified THREAD, OFFSET, and LOAD_MODULE.
+     Stores it in *ADDRESS and returns zero on success; otherwise returns
+     an error code.  A return value of -1 means this system does not
+     support the operation.  */
+
+  int (*get_tls_address) (struct thread_info *thread, CORE_ADDR offset,
+			  CORE_ADDR load_module, CORE_ADDR *address);
 };
 
 extern struct target_ops *the_target;
Index: thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/thread-db.c,v
retrieving revision 1.6
diff -u -p -r1.6 thread-db.c
--- thread-db.c	30 May 2006 19:05:33 -0000	1.6
+++ thread-db.c	17 Oct 2006 15:56:43 -0000
@@ -266,6 +266,7 @@ found:
   process->lwpid = ti_p->ti_lid;
 
   process->thread_known = 1;
+  process->th = *th_p;
   err = td_thr_event_enable (th_p, 1);
   if (err != TD_OK)
     error ("Cannot enable thread event reporting for %d: %s",
@@ -320,6 +321,33 @@ thread_db_look_up_symbols (void)
 }
 
 int
+thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
+			   CORE_ADDR load_module, CORE_ADDR *address)
+{
+#if HAVE_TD_THR_TLS_GET_ADDR
+  psaddr_t addr;
+  td_err_e err;
+  struct process_info *process;
+
+  process = get_thread_process (thread);
+  if (!process->thread_known)
+    return TD_NOTHR;
+
+  err = td_thr_tls_get_addr (&process->th, (psaddr_t) load_module, offset,
+			     &addr);
+  if (err == TD_OK)
+    {
+      *address = (CORE_ADDR) addr;
+      return 0;
+    }
+  else
+    return err;
+#else
+  return -1;
+#endif
+}
+
+int
 thread_db_init ()
 {
   int err;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]