* Makefile.in (mips-tdep.o, target-descriptions.o): Update.
[deliverable/binutils-gdb.git] / gdb / gdbserver / thread-db.c
index f3d57a54d622eb323061d34a023fcb81dca058a0..78bc6434076a0b6de675d2348d11a365736d6515 100644 (file)
@@ -1,5 +1,5 @@
 /* Thread management interface, for the remote server for GDB.
-   Copyright 2002
+   Copyright (C) 2002, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    Contributed by MontaVista Software.
@@ -18,8 +18,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "server.h"
 
@@ -31,19 +31,7 @@ extern int debug_threads;
 #include <thread_db.h>
 #endif
 
-/* Correct for all GNU/Linux targets (for quite some time).  */
-#define GDB_GREGSET_T elf_gregset_t
-#define GDB_FPREGSET_T elf_fpregset_t
-
-#ifndef HAVE_ELF_FPREGSET_T
-/* Make sure we have said types.  Not all platforms bring in <linux/elf.h>
-   via <sys/procfs.h>.  */
-#ifdef HAVE_LINUX_ELF_H
-#include <linux/elf.h>
-#endif
-#endif
-
-#include "../gdb_proc_service.h"
+#include "gdb_proc_service.h"
 
 /* Structure that identifies the child process for the
    <proc_service.h> interface.  */
@@ -103,6 +91,10 @@ thread_db_err_str (td_err_e err)
       return "only part of register set was written/read";
     case TD_NOXREGS:
       return "X register set not available for this thread";
+#ifdef HAVE_TD_VERSION
+    case TD_VERSION:
+      return "version mismatch between libthread_db and libpthread";
+#endif
     default:
       snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err);
       return buf;
@@ -274,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",
@@ -312,13 +305,68 @@ thread_db_find_new_threads (void)
     error ("Cannot find new threads: %s", thread_db_err_str (err));
 }
 
+/* Cache all future symbols that thread_db might request.  We can not
+   request symbols at arbitrary states in the remote protocol, only
+   when the client tells us that new symbols are available.  So when
+   we load the thread library, make sure to check the entire list.  */
+
+static void
+thread_db_look_up_symbols (void)
+{
+  const char **sym_list = td_symbol_list ();
+  CORE_ADDR unused;
+
+  for (sym_list = td_symbol_list (); *sym_list; sym_list++)
+    look_up_one_symbol (*sym_list, &unused);
+}
+
+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;
 
+  /* FIXME drow/2004-10-16: This is the "overall process ID", which
+     GNU/Linux calls tgid, "thread group ID".  When we support
+     attaching to threads, the original thread may not be the correct
+     thread.  We would have to get the process ID from /proc for NPTL.
+     For LinuxThreads we could do something similar: follow the chain
+     of parent processes until we find the highest one we're attached
+     to, and use its tgid.
+
+     This isn't the only place in gdbserver that assumes that the first
+     process in the list is the thread group leader.  */
   proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
 
+  /* Allow new symbol lookups.  */
+  all_symbols_looked_up = 0;
+
   err = td_ta_new (&proc_handle, &thread_agent);
   switch (err)
     {
@@ -332,10 +380,13 @@ thread_db_init ()
       if (thread_db_enable_reporting () == 0)
        return 0;
       thread_db_find_new_threads ();
+      thread_db_look_up_symbols ();
+      all_symbols_looked_up = 1;
       return 1;
 
     default:
-      warning ("error initializing thread_db library.");
+      warning ("error initializing thread_db library: %s",
+              thread_db_err_str (err));
     }
 
   return 0;
This page took 0.04778 seconds and 4 git commands to generate.