Update release making notes.
[deliverable/binutils-gdb.git] / gdb / gdbserver / thread-db.c
index 9bedd8973c796a3e56a5204c4b5810815f46257e..2bb6d28820e7e529568391a7f2d188c791766fad 100644 (file)
@@ -1,6 +1,5 @@
 /* Thread management interface, for the remote server for GDB.
-   Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2002-2020 Free Software Foundation, Inc.
 
    Contributed by MontaVista Software.
 
 
 #include "linux-low.h"
 
-extern int debug_threads;
-
-static int thread_db_use_events;
-
+#include "debug.h"
 #include "gdb_proc_service.h"
-#include "gdb_thread_db.h"
+#include "nat/gdb_thread_db.h"
+#include "gdbsupport/gdb_vecs.h"
+#include "nat/linux-procfs.h"
+#include "gdbsupport/scoped_restore.h"
 
 #ifndef USE_LIBTHREAD_DB_DIRECTLY
 #include <dlfcn.h>
 #endif
-
-#include <stdint.h>
 #include <limits.h>
 #include <ctype.h>
 
@@ -57,38 +54,14 @@ struct thread_db
   void *handle;
 #endif
 
-  /* Thread creation event breakpoint.  The code at this location in
-     the child process will be called by the pthread library whenever
-     a new thread is created.  By setting a special breakpoint at this
-     location, GDB can detect when a new thread is created.  We obtain
-     this location via the td_ta_event_addr call.  Note that if the
-     running kernel supports tracing clones, then we don't need to use
-     (and in fact don't use) this magic thread event breakpoint to
-     learn about threads.  */
-  struct breakpoint *td_create_bp;
-
   /* Addresses of libthread_db functions.  */
-  td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, td_thragent_t **ta);
-  td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
-                                   td_event_msg_t *msg);
-  td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
-                                td_thr_events_t *event);
-  td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
-                                 td_event_e event, td_notify_t *ptr);
-  td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, lwpid_t lwpid,
-                                  td_thrhandle_t *th);
-  td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
-                                td_thrinfo_t *infop);
-  td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, int event);
-  td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
-                               td_thr_iter_f *callback, void *cbdata_p,
-                               td_thr_state_e state, int ti_pri,
-                               sigset_t *ti_sigmask_p,
-                               unsigned int ti_user_flags);
-  td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
-                                    psaddr_t map_address,
-                                    size_t offset, psaddr_t *address);
-  const char ** (*td_symbol_list_p) (void);
+  td_ta_new_ftype *td_ta_new_p;
+  td_ta_map_lwp2thr_ftype *td_ta_map_lwp2thr_p;
+  td_thr_get_info_ftype *td_thr_get_info_p;
+  td_ta_thr_iter_ftype *td_ta_thr_iter_p;
+  td_thr_tls_get_addr_ftype *td_thr_tls_get_addr_p;
+  td_thr_tlsbase_ftype *td_thr_tlsbase_p;
+  td_symbol_list_ftype *td_symbol_list_p;
 };
 
 static char *libthread_db_search_path;
@@ -182,84 +155,8 @@ thread_db_state_str (td_thr_state_e state)
 }
 #endif
 
-static int
-thread_db_create_event (CORE_ADDR where)
-{
-  td_event_msg_t msg;
-  td_err_e err;
-  struct lwp_info *lwp;
-  struct thread_db *thread_db = current_process ()->private->thread_db;
-
-  if (thread_db->td_ta_event_getmsg_p == NULL)
-    fatal ("unexpected thread_db->td_ta_event_getmsg_p == NULL");
-
-  if (debug_threads)
-    fprintf (stderr, "Thread creation event.\n");
-
-  /* FIXME: This assumes we don't get another event.
-     In the LinuxThreads implementation, this is safe,
-     because all events come from the manager thread
-     (except for its own creation, of course).  */
-  err = thread_db->td_ta_event_getmsg_p (thread_db->thread_agent, &msg);
-  if (err != TD_OK)
-    fprintf (stderr, "thread getmsg err: %s\n",
-            thread_db_err_str (err));
-
-  /* If we do not know about the main thread yet, this would be a good time to
-     find it.  We need to do this to pick up the main thread before any newly
-     created threads.  */
-  lwp = get_thread_lwp (current_inferior);
-  if (lwp->thread_known == 0)
-    find_one_thread (lwp->head.id);
-
-  /* msg.event == TD_EVENT_CREATE */
-
-  find_new_threads_callback (msg.th_p, NULL);
-
-  return 0;
-}
-
-static int
-thread_db_enable_reporting (void)
-{
-  td_thr_events_t events;
-  td_notify_t notify;
-  td_err_e err;
-  struct thread_db *thread_db = current_process ()->private->thread_db;
-
-  if (thread_db->td_ta_set_event_p == NULL
-      || thread_db->td_ta_event_addr_p == NULL
-      || thread_db->td_ta_event_getmsg_p == NULL)
-    /* This libthread_db is missing required support.  */
-    return 0;
-
-  /* Set the process wide mask saying which events we're interested in.  */
-  td_event_emptyset (&events);
-  td_event_addset (&events, TD_CREATE);
-
-  err = thread_db->td_ta_set_event_p (thread_db->thread_agent, &events);
-  if (err != TD_OK)
-    {
-      warning ("Unable to set global thread event mask: %s",
-              thread_db_err_str (err));
-      return 0;
-    }
-
-  /* Get address for thread creation breakpoint.  */
-  err = thread_db->td_ta_event_addr_p (thread_db->thread_agent, TD_CREATE,
-                                      &notify);
-  if (err != TD_OK)
-    {
-      warning ("Unable to get location for thread creation breakpoint: %s",
-              thread_db_err_str (err));
-      return 0;
-    }
-  thread_db->td_create_bp
-    = set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
-                        thread_db_create_event);
-
-  return 1;
-}
+/* Get thread info about PTID, accessing memory via the current
+   thread.  */
 
 static int
 find_one_thread (ptid_t ptid)
@@ -267,13 +164,12 @@ find_one_thread (ptid_t ptid)
   td_thrhandle_t th;
   td_thrinfo_t ti;
   td_err_e err;
-  struct thread_info *inferior;
   struct lwp_info *lwp;
-  struct thread_db *thread_db = current_process ()->private->thread_db;
-  int lwpid = ptid_get_lwp (ptid);
+  struct thread_db *thread_db = current_process ()->priv->thread_db;
+  int lwpid = ptid.lwp ();
 
-  inferior = (struct thread_info *) find_inferior_id (&all_threads, ptid);
-  lwp = get_thread_lwp (inferior);
+  thread_info *thread = find_thread_ptid (ptid);
+  lwp = get_thread_lwp (thread);
   if (lwp->thread_known)
     return 1;
 
@@ -289,8 +185,8 @@ find_one_thread (ptid_t ptid)
           lwpid, thread_db_err_str (err));
 
   if (debug_threads)
-    fprintf (stderr, "Found thread %ld (LWP %d)\n",
-            ti.ti_tid, ti.ti_lid);
+    debug_printf ("Found thread %ld (LWP %d)\n",
+                 (unsigned long) ti.ti_tid, ti.ti_lid);
 
   if (lwpid != ti.ti_lid)
     {
@@ -299,14 +195,6 @@ find_one_thread (ptid_t ptid)
       return 0;
     }
 
-  if (thread_db_use_events)
-    {
-      err = thread_db->td_thr_event_enable_p (&th, 1);
-      if (err != TD_OK)
-       error ("Cannot enable thread event reporting for %d: %s",
-              ti.ti_lid, thread_db_err_str (err));
-    }
-
   /* If the new thread ID is zero, a final thread ID will be available
      later.  Do not enable thread debugging yet.  */
   if (ti.ti_tid == 0)
@@ -314,6 +202,7 @@ find_one_thread (ptid_t ptid)
 
   lwp->thread_known = 1;
   lwp->th = th;
+  lwp->thread_handle = ti.ti_tid;
 
   return 1;
 }
@@ -323,33 +212,31 @@ find_one_thread (ptid_t ptid)
 static int
 attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
 {
+  struct process_info *proc = current_process ();
+  int pid = pid_of (proc);
+  ptid_t ptid = ptid_t (pid, ti_p->ti_lid, 0);
   struct lwp_info *lwp;
+  int err;
 
   if (debug_threads)
-    fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
-            ti_p->ti_tid, ti_p->ti_lid);
-  linux_attach_lwp (ti_p->ti_lid);
-  lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
-  if (lwp == NULL)
+    debug_printf ("Attaching to thread %ld (LWP %d)\n",
+                 (unsigned long) ti_p->ti_tid, ti_p->ti_lid);
+  err = linux_attach_lwp (ptid);
+  if (err != 0)
     {
-      warning ("Could not attach to thread %ld (LWP %d)\n",
-              ti_p->ti_tid, ti_p->ti_lid);
+      std::string reason = linux_ptrace_attach_fail_reason_string (ptid, err);
+
+      warning ("Could not attach to thread %ld (LWP %d): %s",
+              (unsigned long) ti_p->ti_tid, ti_p->ti_lid, reason.c_str ());
+
       return 0;
     }
 
+  lwp = find_lwp_pid (ptid);
+  gdb_assert (lwp != NULL);
   lwp->thread_known = 1;
   lwp->th = *th_p;
-
-  if (thread_db_use_events)
-    {
-      td_err_e err;
-      struct thread_db *thread_db = current_process ()->private->thread_db;
-
-      err = thread_db->td_thr_event_enable_p (th_p, 1);
-      if (err != TD_OK)
-       error ("Cannot enable thread event reporting for %d: %s",
-              ti_p->ti_lid, thread_db_err_str (err));
-    }
+  lwp->thread_handle = ti_p->ti_tid;
 
   return 1;
 }
@@ -364,7 +251,7 @@ maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p,
 {
   struct lwp_info *lwp;
 
-  lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
+  lwp = find_lwp_pid (ptid_t (ti_p->ti_lid));
   if (lwp != NULL)
     return 1;
 
@@ -382,12 +269,27 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
 {
   td_thrinfo_t ti;
   td_err_e err;
-  struct thread_db *thread_db = current_process ()->private->thread_db;
+  struct thread_db *thread_db = current_process ()->priv->thread_db;
 
   err = thread_db->td_thr_get_info_p (th_p, &ti);
   if (err != TD_OK)
     error ("Cannot get thread info: %s", thread_db_err_str (err));
 
+  if (ti.ti_lid == -1)
+    {
+      /* A thread with kernel thread ID -1 is either a thread that
+        exited and was joined, or a thread that is being created but
+        hasn't started yet, and that is reusing the tcb/stack of a
+        thread that previously exited and was joined.  (glibc marks
+        terminated and joined threads with kernel thread ID -1.  See
+        glibc PR17707.  */
+      if (debug_threads)
+       debug_printf ("thread_db: skipping exited and "
+                     "joined thread (0x%lx)\n",
+                     (unsigned long) ti.ti_tid);
+      return 0;
+    }
+
   /* Check for zombies.  */
   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
     return 0;
@@ -406,8 +308,8 @@ static void
 thread_db_find_new_threads (void)
 {
   td_err_e err;
-  ptid_t ptid = ((struct inferior_list_entry *) current_inferior)->id;
-  struct thread_db *thread_db = current_process ()->private->thread_db;
+  ptid_t ptid = current_ptid;
+  struct thread_db *thread_db = current_process ()->priv->thread_db;
   int loop, iteration;
 
   /* This function is only called when we first initialize thread_db.
@@ -432,8 +334,8 @@ thread_db_find_new_threads (void)
                                         TD_THR_LOWEST_PRIORITY,
                                         TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
       if (debug_threads)
-       fprintf (stderr, "Found %d threads in iteration %d.\n",
-                new_thread_count, iteration);
+       debug_printf ("Found %d threads in iteration %d.\n",
+                     new_thread_count, iteration);
 
       if (new_thread_count != 0)
        {
@@ -453,7 +355,7 @@ thread_db_find_new_threads (void)
 static void
 thread_db_look_up_symbols (void)
 {
-  struct thread_db *thread_db = current_process ()->private->thread_db;
+  struct thread_db *thread_db = current_process ()->priv->thread_db;
   const char **sym_list;
   CORE_ADDR unused;
 
@@ -468,7 +370,7 @@ thread_db_look_up_symbols (void)
 int
 thread_db_look_up_one_symbol (const char *name, CORE_ADDR *addrp)
 {
-  struct thread_db *thread_db = current_process ()->private->thread_db;
+  struct thread_db *thread_db = current_process ()->priv->thread_db;
   int may_ask_gdb = !thread_db->all_symbols_looked_up;
 
   /* If we've passed the call to thread_db_look_up_symbols, then
@@ -486,35 +388,54 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
   psaddr_t addr;
   td_err_e err;
   struct lwp_info *lwp;
-  struct thread_info *saved_inferior;
+  struct thread_info *saved_thread;
   struct process_info *proc;
   struct thread_db *thread_db;
 
   proc = get_thread_process (thread);
-  thread_db = proc->private->thread_db;
+  thread_db = proc->priv->thread_db;
 
   /* If the thread layer is not (yet) initialized, fail.  */
-  if (!thread_db->all_symbols_looked_up)
+  if (thread_db == NULL || !thread_db->all_symbols_looked_up)
     return TD_ERR;
 
-  if (thread_db->td_thr_tls_get_addr_p == NULL)
+  /* If td_thr_tls_get_addr is missing rather do not expect td_thr_tlsbase
+     could work.  */
+  if (thread_db->td_thr_tls_get_addr_p == NULL
+      || (load_module == 0 && thread_db->td_thr_tlsbase_p == NULL))
     return -1;
 
   lwp = get_thread_lwp (thread);
   if (!lwp->thread_known)
-    find_one_thread (lwp->head.id);
+    find_one_thread (thread->id);
   if (!lwp->thread_known)
     return TD_NOTHR;
 
-  saved_inferior = current_inferior;
-  current_inferior = thread;
-  /* Note the cast through uintptr_t: this interface only works if
-     a target address fits in a psaddr_t, which is a host pointer.
-     So a 32-bit debugger can not access 64-bit TLS through this.  */
-  err = thread_db->td_thr_tls_get_addr_p (&lwp->th,
-                                         (psaddr_t) (uintptr_t) load_module,
-                                         offset, &addr);
-  current_inferior = saved_inferior;
+  saved_thread = current_thread;
+  current_thread = thread;
+
+  if (load_module != 0)
+    {
+      /* Note the cast through uintptr_t: this interface only works if
+        a target address fits in a psaddr_t, which is a host pointer.
+        So a 32-bit debugger can not access 64-bit TLS through this.  */
+      err = thread_db->td_thr_tls_get_addr_p (&lwp->th,
+                                            (psaddr_t) (uintptr_t) load_module,
+                                             offset, &addr);
+    }
+  else
+    {
+      /* This code path handles the case of -static -pthread executables:
+        https://sourceware.org/ml/libc-help/2014-03/msg00024.html
+        For older GNU libc r_debug.r_map is NULL.  For GNU libc after
+        PR libc/16831 due to GDB PR threads/16954 LOAD_MODULE is also NULL.
+        The constant number 1 depends on GNU __libc_setup_tls
+        initialization of l_tls_modid to 1.  */
+      err = thread_db->td_thr_tlsbase_p (&lwp->th, 1, &addr);
+      addr = (char *) addr + offset;
+    }
+
+  current_thread = saved_thread;
   if (err == TD_OK)
     {
       *address = (CORE_ADDR) (uintptr_t) addr;
@@ -524,6 +445,35 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
     return err;
 }
 
+/* See linux-low.h.  */
+
+bool
+thread_db_thread_handle (ptid_t ptid, gdb_byte **handle, int *handle_len)
+{
+  struct thread_db *thread_db;
+  struct lwp_info *lwp;
+  thread_info *thread = find_thread_ptid (ptid);
+
+  if (thread == NULL)
+    return false;
+
+  thread_db = get_thread_process (thread)->priv->thread_db;
+
+  if (thread_db == NULL)
+    return false;
+
+  lwp = get_thread_lwp (thread);
+
+  if (!lwp->thread_known && !find_one_thread (thread->id))
+    return false;
+
+  gdb_assert (lwp->thread_known);
+
+  *handle = (gdb_byte *) &lwp->thread_handle;
+  *handle_len = sizeof (lwp->thread_handle);
+  return true;
+}
+
 #ifdef USE_LIBTHREAD_DB_DIRECTLY
 
 static int
@@ -533,11 +483,10 @@ thread_db_load_search (void)
   struct thread_db *tdb;
   struct process_info *proc = current_process ();
 
-  if (proc->private->thread_db != NULL)
-    fatal ("unexpected: proc->private->thread_db != NULL");
+  gdb_assert (proc->priv->thread_db == NULL);
 
-  tdb = xcalloc (1, sizeof (*tdb));
-  proc->private->thread_db = tdb;
+  tdb = XCNEW (struct thread_db);
+  proc->priv->thread_db = tdb;
 
   tdb->td_ta_new_p = &td_ta_new;
 
@@ -546,9 +495,9 @@ thread_db_load_search (void)
   if (err != TD_OK)
     {
       if (debug_threads)
-       fprintf (stderr, "td_ta_new(): %s\n", thread_db_err_str (err));
+       debug_printf ("td_ta_new(): %s\n", thread_db_err_str (err));
       free (tdb);
-      proc->private->thread_db = NULL;
+      proc->priv->thread_db = NULL;
       return 0;
     }
 
@@ -557,14 +506,9 @@ thread_db_load_search (void)
   tdb->td_ta_thr_iter_p = &td_ta_thr_iter;
   tdb->td_symbol_list_p = &td_symbol_list;
 
-  /* This is required only when thread_db_use_events is on.  */
-  tdb->td_thr_event_enable_p = &td_thr_event_enable;
-
   /* These are not essential.  */
-  tdb->td_ta_event_addr_p = &td_ta_event_addr;
-  tdb->td_ta_set_event_p = &td_ta_set_event;
-  tdb->td_ta_event_getmsg_p = &td_ta_event_getmsg;
   tdb->td_thr_tls_get_addr_p = &td_thr_tls_get_addr;
+  tdb->td_thr_tlsbase_p = &td_thr_tlsbase;
 
   return 1;
 }
@@ -578,11 +522,10 @@ try_thread_db_load_1 (void *handle)
   struct thread_db *tdb;
   struct process_info *proc = current_process ();
 
-  if (proc->private->thread_db != NULL)
-    fatal ("unexpected: proc->private->thread_db != NULL");
+  gdb_assert (proc->priv->thread_db == NULL);
 
-  tdb = xcalloc (1, sizeof (*tdb));
-  proc->private->thread_db = tdb;
+  tdb = XCNEW (struct thread_db);
+  proc->priv->thread_db = tdb;
 
   tdb->handle = handle;
 
@@ -595,46 +538,44 @@ try_thread_db_load_1 (void *handle)
       if ((a) == NULL)                                         \
        {                                                       \
          if (debug_threads)                                    \
-           fprintf (stderr, "dlsym: %s\n", dlerror ());        \
+           debug_printf ("dlsym: %s\n", dlerror ());           \
          if (required)                                         \
            {                                                   \
              free (tdb);                                       \
-             proc->private->thread_db = NULL;                  \
+             proc->priv->thread_db = NULL;                     \
              return 0;                                         \
            }                                                   \
        }                                                       \
     }                                                          \
   while (0)
 
-  CHK (1, tdb->td_ta_new_p = dlsym (handle, "td_ta_new"));
+#define TDB_DLSYM(tdb, func) \
+  tdb->func ## _p = (func ## _ftype *) dlsym (tdb->handle, #func)
+
+  CHK (1, TDB_DLSYM (tdb, td_ta_new));
 
   /* Attempt to open a connection to the thread library.  */
   err = tdb->td_ta_new_p (&tdb->proc_handle, &tdb->thread_agent);
   if (err != TD_OK)
     {
       if (debug_threads)
-       fprintf (stderr, "td_ta_new(): %s\n", thread_db_err_str (err));
+       debug_printf ("td_ta_new(): %s\n", thread_db_err_str (err));
       free (tdb);
-      proc->private->thread_db = NULL;
+      proc->priv->thread_db = NULL;
       return 0;
     }
 
-  CHK (1, tdb->td_ta_map_lwp2thr_p = dlsym (handle, "td_ta_map_lwp2thr"));
-  CHK (1, tdb->td_thr_get_info_p = dlsym (handle, "td_thr_get_info"));
-  CHK (1, tdb->td_ta_thr_iter_p = dlsym (handle, "td_ta_thr_iter"));
-  CHK (1, tdb->td_symbol_list_p = dlsym (handle, "td_symbol_list"));
-
-  /* This is required only when thread_db_use_events is on.  */
-  CHK (thread_db_use_events,
-       tdb->td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"));
+  CHK (1, TDB_DLSYM (tdb, td_ta_map_lwp2thr));
+  CHK (1, TDB_DLSYM (tdb, td_thr_get_info));
+  CHK (1, TDB_DLSYM (tdb, td_ta_thr_iter));
+  CHK (1, TDB_DLSYM (tdb, td_symbol_list));
 
   /* These are not essential.  */
-  CHK (0, tdb->td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"));
-  CHK (0, tdb->td_ta_set_event_p = dlsym (handle, "td_ta_set_event"));
-  CHK (0, tdb->td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"));
-  CHK (0, tdb->td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"));
+  CHK (0, TDB_DLSYM (tdb, td_thr_tls_get_addr));
+  CHK (0, TDB_DLSYM (tdb, td_thr_tlsbase));
 
 #undef CHK
+#undef TDB_DLSYM
 
   return 1;
 }
@@ -663,13 +604,13 @@ try_thread_db_load (const char *library)
   void *handle;
 
   if (debug_threads)
-    fprintf (stderr, "Trying host libthread_db library: %s.\n",
-            library);
+    debug_printf ("Trying host libthread_db library: %s.\n",
+                 library);
   handle = dlopen (library, RTLD_NOW);
   if (handle == NULL)
     {
       if (debug_threads)
-       fprintf (stderr, "dlopen failed: %s.\n", dlerror ());
+       debug_printf ("dlopen failed: %s.\n", dlerror ());
       return 0;
     }
 
@@ -684,8 +625,7 @@ try_thread_db_load (const char *library)
          const char *const libpath = dladdr_to_soname (td_init);
 
          if (libpath != NULL)
-           fprintf (stderr, "Host %s resolved to: %s.\n",
-                    library, libpath);
+           debug_printf ("Host %s resolved to: %s.\n", library, libpath);
        }
     }
 #endif
@@ -719,7 +659,7 @@ try_thread_db_load_from_dir (const char *dir, size_t dir_len)
 
   if (dir_len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
     {
-      char *cp = xmalloc (dir_len + 1);
+      char *cp = (char *) xmalloc (dir_len + 1);
 
       memcpy (cp, dir, dir_len);
       cp[dir_len] = '\0';
@@ -742,39 +682,31 @@ try_thread_db_load_from_dir (const char *dir, size_t dir_len)
 static int
 thread_db_load_search (void)
 {
-  const char *search_path;
   int rc = 0;
 
   if (libthread_db_search_path == NULL)
     libthread_db_search_path = xstrdup (LIBTHREAD_DB_SEARCH_PATH);
 
-  search_path = libthread_db_search_path;
-  while (*search_path)
+  std::vector<gdb::unique_xmalloc_ptr<char>> dir_vec
+    = dirnames_to_char_ptr_vec (libthread_db_search_path);
+
+  for (const gdb::unique_xmalloc_ptr<char> &this_dir_up : dir_vec)
     {
-      const char *end = strchr (search_path, ':');
-      const char *this_dir = search_path;
+      char *this_dir = this_dir_up.get ();
+      const int pdir_len = sizeof ("$pdir") - 1;
       size_t this_dir_len;
 
-      if (end)
-       {
-         this_dir_len = end - search_path;
-         search_path += this_dir_len + 1;
-       }
-      else
-       {
-         this_dir_len = strlen (this_dir);
-         search_path += this_dir_len;
-       }
+      this_dir_len = strlen (this_dir);
 
-      if (this_dir_len == sizeof ("$pdir") - 1
-         && strncmp (this_dir, "$pdir", this_dir_len) == 0)
+      if (strncmp (this_dir, "$pdir", pdir_len) == 0
+         && (this_dir[pdir_len] == '\0'
+             || this_dir[pdir_len] == '/'))
        {
          /* We don't maintain a list of loaded libraries so we don't know
             where libpthread lives.  We *could* fetch the info, but we don't
             do that yet.  Ignore it.  */
        }
-      else if (this_dir_len == sizeof ("$sdir") - 1
-              && strncmp (this_dir, "$sdir", this_dir_len) == 0)
+      else if (strcmp (this_dir, "$sdir") == 0)
        {
          if (try_thread_db_load_from_sdir ())
            {
@@ -793,14 +725,14 @@ thread_db_load_search (void)
     }
 
   if (debug_threads)
-    fprintf (stderr, "thread_db_load_search returning %d\n", rc);
+    debug_printf ("thread_db_load_search returning %d\n", rc);
   return rc;
 }
 
 #endif  /* USE_LIBTHREAD_DB_DIRECTLY */
 
 int
-thread_db_init (int use_events)
+thread_db_init (void)
 {
   struct process_info *proc = current_process ();
 
@@ -808,24 +740,26 @@ thread_db_init (int use_events)
      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.  */
 
-  thread_db_use_events = use_events;
-
   if (thread_db_load_search ())
     {
-      if (use_events && thread_db_enable_reporting () == 0)
-       {
-         /* Keep trying; maybe event reporting will work later.  */
-         thread_db_mourn (proc);
-         return 0;
-       }
-      thread_db_find_new_threads ();
+      /* It's best to avoid td_ta_thr_iter if possible.  That walks
+        data structures in the inferior's address space that may be
+        corrupted, or, if the target is running, the list may change
+        while we walk it.  In the latter case, it's possible that a
+        thread exits just at the exact time that causes GDBserver to
+        get stuck in an infinite loop.  As the kernel supports clone
+        events and /proc/PID/task/ exists, then we already know about
+        all threads in the process.  When we need info out of
+        thread_db on a given thread (e.g., for TLS), we'll use
+        find_one_thread then.  That uses thread_db entry points that
+        do not walk libpthread's thread list, so should be safe, as
+        well as more efficient.  */
+      if (!linux_proc_task_list_dir_exists (pid_of (proc)))
+       thread_db_find_new_threads ();
       thread_db_look_up_symbols ();
       return 1;
     }
@@ -833,25 +767,12 @@ thread_db_init (int use_events)
   return 0;
 }
 
-static int
-any_thread_of (struct inferior_list_entry *entry, void *args)
-{
-  int *pid_p = args;
-
-  if (ptid_get_pid (entry->id) == *pid_p)
-    return 1;
-
-  return 0;
-}
-
 static void
 switch_to_process (struct process_info *proc)
 {
   int pid = pid_of (proc);
 
-  current_inferior =
-    (struct thread_info *) find_inferior (&all_threads,
-                                         any_thread_of, &pid);
+  current_thread = find_any_thread_of_pid (pid);
 }
 
 /* Disconnect from libthread_db and free resources.  */
@@ -859,21 +780,23 @@ switch_to_process (struct process_info *proc)
 static void
 disable_thread_event_reporting (struct process_info *proc)
 {
-  struct thread_db *thread_db = proc->private->thread_db;
+  struct thread_db *thread_db = proc->priv->thread_db;
   if (thread_db)
     {
       td_err_e (*td_ta_clear_event_p) (const td_thragent_t *ta,
                                       td_thr_events_t *event);
 
 #ifndef USE_LIBTHREAD_DB_DIRECTLY
-      td_ta_clear_event_p = dlsym (thread_db->handle, "td_ta_clear_event");
+      td_ta_clear_event_p
+       = (td_ta_clear_event_ftype *) dlsym (thread_db->handle,
+                                            "td_ta_clear_event");
 #else
       td_ta_clear_event_p = &td_ta_clear_event;
 #endif
 
       if (td_ta_clear_event_p != NULL)
        {
-         struct thread_info *saved_inferior = current_inferior;
+         struct thread_info *saved_thread = current_thread;
          td_thr_events_t events;
 
          switch_to_process (proc);
@@ -883,38 +806,19 @@ disable_thread_event_reporting (struct process_info *proc)
          td_event_fillset (&events);
          (*td_ta_clear_event_p) (thread_db->thread_agent, &events);
 
-         current_inferior = saved_inferior;
+         current_thread = saved_thread;
        }
     }
 }
 
-static void
-remove_thread_event_breakpoints (struct process_info *proc)
-{
-  struct thread_db *thread_db = proc->private->thread_db;
-
-  if (thread_db->td_create_bp != NULL)
-    {
-      struct thread_info *saved_inferior = current_inferior;
-
-      switch_to_process (proc);
-
-      delete_breakpoint (thread_db->td_create_bp);
-      thread_db->td_create_bp = NULL;
-
-      current_inferior = saved_inferior;
-    }
-}
-
 void
 thread_db_detach (struct process_info *proc)
 {
-  struct thread_db *thread_db = proc->private->thread_db;
+  struct thread_db *thread_db = proc->priv->thread_db;
 
   if (thread_db)
     {
       disable_thread_event_reporting (proc);
-      remove_thread_event_breakpoints (proc);
     }
 }
 
@@ -923,13 +827,13 @@ thread_db_detach (struct process_info *proc)
 void
 thread_db_mourn (struct process_info *proc)
 {
-  struct thread_db *thread_db = proc->private->thread_db;
+  struct thread_db *thread_db = proc->priv->thread_db;
   if (thread_db)
     {
-      td_err_e (*td_ta_delete_p) (td_thragent_t *);
+      td_ta_delete_ftype *td_ta_delete_p;
 
 #ifndef USE_LIBTHREAD_DB_DIRECTLY
-      td_ta_delete_p = dlsym (thread_db->handle, "td_ta_delete");
+      td_ta_delete_p = (td_ta_delete_ftype *) dlsym (thread_db->handle, "td_ta_delete");
 #else
       td_ta_delete_p = &td_ta_delete;
 #endif
@@ -942,7 +846,7 @@ thread_db_mourn (struct process_info *proc)
 #endif  /* USE_LIBTHREAD_DB_DIRECTLY  */
 
       free (thread_db);
-      proc->private->thread_db = NULL;
+      proc->priv->thread_db = NULL;
     }
 }
 
@@ -981,3 +885,26 @@ thread_db_handle_monitor_command (char *mon)
   /* Tell server.c to perform default processing.  */
   return 0;
 }
+
+/* See linux-low.h.  */
+
+void
+thread_db_notice_clone (struct thread_info *parent_thr, ptid_t child_ptid)
+{
+  process_info *parent_proc = get_thread_process (parent_thr);
+  struct thread_db *thread_db = parent_proc->priv->thread_db;
+
+  /* If the thread layer isn't initialized, return.  It may just
+     be that the program uses clone, but does not use libthread_db.  */
+  if (thread_db == NULL || !thread_db->all_symbols_looked_up)
+    return;
+
+  /* find_one_thread calls into libthread_db which accesses memory via
+     the current thread.  Temporarily switch to a thread we know is
+     stopped.  */
+  scoped_restore restore_current_thread
+    = make_scoped_restore (&current_thread, parent_thr);
+
+  if (!find_one_thread (child_ptid))
+    warning ("Cannot find thread after clone.");
+}
This page took 0.074137 seconds and 4 git commands to generate.