*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / linux-thread-db.c
index 3efcae823275a3b628e685e73079dbc499f1e1d3..b64ac2ed0c063e2d0423fc0a0e28a38037243cfd 100644 (file)
@@ -1,7 +1,6 @@
 /* libthread_db assisted debugging support, generic parts.
 
-   Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1999-2001, 2003-2012 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -40,6 +39,7 @@
 #include "gdbcore.h"
 #include "observer.h"
 #include "linux-nat.h"
+#include "linux-procfs.h"
 
 #include <signal.h>
 
 
 static char *libthread_db_search_path;
 
+static void
+set_libthread_db_search_path (char *ignored, int from_tty,
+                             struct cmd_list_element *c)
+{
+  if (*libthread_db_search_path == '\0')
+    {
+      xfree (libthread_db_search_path);
+      libthread_db_search_path = xstrdup (LIBTHREAD_DB_SEARCH_PATH);
+    }
+}
+
+/* If non-zero, print details of libthread_db processing.  */
+
+static int libthread_db_debug;
+
+static void
+show_libthread_db_debug (struct ui_file *file, int from_tty,
+                        struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("libthread-db debugging is %s.\n"), value);
+}
+
 /* If we're running on GNU/Linux, we must explicitly attach to any new
    threads.  */
 
@@ -141,6 +163,8 @@ struct thread_db_info
                                  td_event_e event, td_notify_t *ptr);
   td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
                                 td_thr_events_t *event);
+  td_err_e (*td_ta_clear_event_p) (const td_thragent_t *ta,
+                                  td_thr_events_t *event);
   td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
                                    td_event_msg_t *msg);
 
@@ -151,8 +175,8 @@ struct thread_db_info
                                     int event);
 
   td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
-                                    void *map_address,
-                                    size_t offset, void **address);
+                                    psaddr_t map_address,
+                                    size_t offset, psaddr_t *address);
 };
 
 /* List of known processes using thread_db, and the required
@@ -160,6 +184,7 @@ struct thread_db_info
 struct thread_db_info *thread_db_list;
 
 static void thread_db_find_new_threads_1 (ptid_t ptid);
+static void thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new);
 
 /* Add the current inferior to the list of processes using libpthread.
    Return a pointer to the newly allocated object that was added to
@@ -169,13 +194,16 @@ static void thread_db_find_new_threads_1 (ptid_t ptid);
 static struct thread_db_info *
 add_thread_db_info (void *handle)
 {
-  int pid;
   struct thread_db_info *info;
 
   info = xcalloc (1, sizeof (*info));
   info->pid = ptid_get_pid (inferior_ptid);
   info->handle = handle;
-  info->need_stale_parent_threads_check = 1;
+
+  /* The workaround works by reading from /proc/pid/status, so it is
+     disabled for core files.  */
+  if (target_has_execution)
+    info->need_stale_parent_threads_check = 1;
 
   info->next = thread_db_list;
   thread_db_list = info;
@@ -229,8 +257,8 @@ delete_thread_db_info (int pid)
 }
 
 /* Prototypes for local functions.  */
-static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
-                          const td_thrinfo_t *ti_p);
+static int attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
+                         const td_thrinfo_t *ti_p);
 static void detach_thread (ptid_t ptid);
 \f
 
@@ -322,6 +350,7 @@ static int
 have_threads_callback (struct thread_info *thread, void *args)
 {
   int pid = * (int *) args;
+
   if (ptid_get_pid (thread->ptid) != pid)
     return 0;
 
@@ -371,7 +400,7 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *argp)
 
   /* Fill the cache.  */
   thread_ptid = ptid_build (info->pid, ti.ti_lid, 0);
-  inout->thread_info = find_thread_pid (thread_ptid);
+  inout->thread_info = find_thread_ptid (thread_ptid);
 
   /* In the case of a zombie thread, don't continue.  We don't want to
      attach to it thinking it is a new thread.  */
@@ -385,7 +414,7 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *argp)
        thread_db_find_new_threads_1 (thread_ptid);
       else
        attach_thread (thread_ptid, thp, &ti);
-      inout->thread_info = find_thread_pid (thread_ptid);
+      inout->thread_info = find_thread_ptid (thread_ptid);
       gdb_assert (inout->thread_info != NULL);
     }
 
@@ -399,10 +428,12 @@ thread_from_lwp (ptid_t ptid)
 {
   td_thrhandle_t th;
   td_err_e err;
-  ptid_t thread_ptid;
   struct thread_db_info *info;
   struct thread_get_info_inout io = {0};
 
+  /* Just in case td_ta_map_lwp2thr doesn't initialize it completely.  */
+  th.th_unique = 0;
+
   /* This ptid comes from linux-nat.c, which should always fill in the
      LWP.  */
   gdb_assert (GET_LWP (ptid) != 0);
@@ -485,7 +516,8 @@ verbose_dlsym (void *handle, const char *name)
 {
   void *sym = dlsym (handle, name);
   if (sym == NULL)
-    warning (_("Symbol \"%s\" not found in libthread_db: %s"), name, dlerror ());
+    warning (_("Symbol \"%s\" not found in libthread_db: %s"),
+            name, dlerror ());
   return sym;
 }
 
@@ -509,13 +541,13 @@ enable_thread_event (int event, CORE_ADDR *bp)
   /* Set up the breakpoint.  */
   gdb_assert (exec_bfd);
   (*bp) = (gdbarch_convert_from_func_ptr_addr
-          (current_gdbarch,
+          (target_gdbarch,
            /* Do proper sign extension for the target.  */
            (bfd_get_sign_extend_vma (exec_bfd) > 0
             ? (CORE_ADDR) (intptr_t) notify.u.bptaddr
             : (CORE_ADDR) (uintptr_t) notify.u.bptaddr),
            &current_target));
-  create_thread_event_breakpoint ((*bp));
+  create_thread_event_breakpoint (target_gdbarch, *bp);
 
   return TD_OK;
 }
@@ -524,7 +556,6 @@ static void
 enable_thread_event_reporting (void)
 {
   td_thr_events_t events;
-  td_notify_t notify;
   td_err_e err;
 #ifdef HAVE_GNU_LIBC_VERSION_H
   const char *libc_version;
@@ -588,6 +619,25 @@ enable_thread_event_reporting (void)
     }
 }
 
+/* Same as thread_db_find_new_threads_1, but silently ignore errors.  */
+
+static void
+thread_db_find_new_threads_silently (ptid_t ptid)
+{
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ERROR)
+    {
+      thread_db_find_new_threads_2 (ptid, 1);
+    }
+
+  if (except.reason < 0 && libthread_db_debug)
+    {
+      exception_fprintf (gdb_stderr, except,
+                        "Warning: thread_db_find_new_threads_silently: ");
+    }
+}
+
 /* Lookup a library in which given symbol resides.
    Note: this is looking in GDB process, not in the inferior.
    Returns library name, or NULL.  */
@@ -602,7 +652,7 @@ dladdr_to_soname (const void *addr)
   return NULL;
 }
 
-/* Attempt to initialize dlopen()ed libthread_db, described by HANDLE.
+/* Attempt to initialize dlopen()ed libthread_db, described by INFO.
    Return 1 on success.
    Failure could happen if libthread_db does not have symbols we expect,
    or when it refuses to work with the current inferior (e.g. due to
@@ -623,7 +673,8 @@ try_thread_db_load_1 (struct thread_db_info *info)
   err = info->td_init_p ();
   if (err != TD_OK)
     {
-      warning (_("Cannot initialize libthread_db: %s"), thread_db_err_str (err));
+      warning (_("Cannot initialize libthread_db: %s"),
+              thread_db_err_str (err));
       return 0;
     }
 
@@ -638,7 +689,7 @@ try_thread_db_load_1 (struct thread_db_info *info)
   err = info->td_ta_new_p (&info->proc_handle, &info->thread_agent);
   if (err != TD_OK)
     {
-      if (info_verbose)
+      if (libthread_db_debug)
        printf_unfiltered (_("td_ta_new failed: %s\n"),
                           thread_db_err_str (err));
       else
@@ -662,7 +713,8 @@ try_thread_db_load_1 (struct thread_db_info *info)
   if (info->td_ta_map_id2thr_p == NULL)
     return 0;
 
-  info->td_ta_map_lwp2thr_p = verbose_dlsym (info->handle, "td_ta_map_lwp2thr");
+  info->td_ta_map_lwp2thr_p = verbose_dlsym (info->handle,
+                                            "td_ta_map_lwp2thr");
   if (info->td_ta_map_lwp2thr_p == NULL)
     return 0;
 
@@ -681,13 +733,14 @@ try_thread_db_load_1 (struct thread_db_info *info)
   /* These are not essential.  */
   info->td_ta_event_addr_p = dlsym (info->handle, "td_ta_event_addr");
   info->td_ta_set_event_p = dlsym (info->handle, "td_ta_set_event");
+  info->td_ta_clear_event_p = dlsym (info->handle, "td_ta_clear_event");
   info->td_ta_event_getmsg_p = dlsym (info->handle, "td_ta_event_getmsg");
   info->td_thr_event_enable_p = dlsym (info->handle, "td_thr_event_enable");
   info->td_thr_tls_get_addr_p = dlsym (info->handle, "td_thr_tls_get_addr");
 
   printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
 
-  if (info_verbose || *libthread_db_search_path)
+  if (libthread_db_debug || *libthread_db_search_path)
     {
       const char *library;
 
@@ -704,8 +757,16 @@ try_thread_db_load_1 (struct thread_db_info *info)
   if (thread_db_list->next == NULL)
     push_target (&thread_db_ops);
 
-  enable_thread_event_reporting ();
-  thread_db_find_new_threads_1 (inferior_ptid);
+  /* Enable event reporting, but not when debugging a core file.  */
+  if (target_has_execution)
+    enable_thread_event_reporting ();
+
+  /* There appears to be a bug in glibc-2.3.6: calls to td_thr_get_info fail
+     with TD_ERR for statically linked executables if td_thr_get_info is
+     called before glibc has initialized itself.  Silently ignore such
+     errors, and let gdb enumerate threads again later.  */
+  thread_db_find_new_threads_silently (inferior_ptid);
+
   return 1;
 }
 
@@ -718,18 +779,18 @@ try_thread_db_load (const char *library)
   void *handle;
   struct thread_db_info *info;
 
-  if (info_verbose)
+  if (libthread_db_debug)
     printf_unfiltered (_("Trying host libthread_db library: %s.\n"),
                        library);
   handle = dlopen (library, RTLD_NOW);
   if (handle == NULL)
     {
-      if (info_verbose)
+      if (libthread_db_debug)
        printf_unfiltered (_("dlopen failed: %s.\n"), dlerror ());
       return 0;
     }
 
-  if (info_verbose && strchr (library, '/') == NULL)
+  if (libthread_db_debug && strchr (library, '/') == NULL)
     {
       void *td_init;
 
@@ -754,72 +815,178 @@ try_thread_db_load (const char *library)
   return 0;
 }
 
+/* Subroutine of try_thread_db_load_from_pdir to simplify it.
+   Try loading libthread_db from the same directory as OBJ.
+   The result is true for success.  */
+
+static int
+try_thread_db_load_from_pdir_1 (struct objfile *obj)
+{
+  struct cleanup *cleanup;
+  char *path, *cp;
+  int result;
+
+  if (obj->name[0] != '/')
+    {
+      warning (_("Expected absolute pathname for libpthread in the"
+                " inferior, but got %s."), obj->name);
+      return 0;
+    }
+
+  path = xmalloc (strlen (obj->name) + 1 + strlen (LIBTHREAD_DB_SO) + 1);
+  cleanup = make_cleanup (xfree, path);
+
+  strcpy (path, obj->name);
+  cp = strrchr (path, '/');
+  /* This should at minimum hit the first character.  */
+  gdb_assert (cp != NULL);
+  strcpy (cp + 1, LIBTHREAD_DB_SO);
+  result = try_thread_db_load (path);
+
+  do_cleanups (cleanup);
+  return result;
+}
+
+/* Handle $pdir in libthread-db-search-path.
+   Look for libthread_db in the directory of libpthread.
+   The result is true for success.  */
+
+static int
+try_thread_db_load_from_pdir (void)
+{
+  struct objfile *obj;
+
+  ALL_OBJFILES (obj)
+    if (libpthread_name_p (obj->name))
+      {
+       if (try_thread_db_load_from_pdir_1 (obj))
+         return 1;
+
+       /* We may have found the separate-debug-info version of
+          libpthread, and it may live in a directory without a matching
+          libthread_db.  */
+       if (obj->separate_debug_objfile_backlink != NULL)
+         return try_thread_db_load_from_pdir_1 (obj->separate_debug_objfile_backlink);
+
+       return 0;
+      }
+
+  return 0;
+}
+
+/* Handle $sdir in libthread-db-search-path.
+   Look for libthread_db in the system dirs, or wherever a plain
+   dlopen(file_without_path) will look.
+   The result is true for success.  */
+
+static int
+try_thread_db_load_from_sdir (void)
+{
+  return try_thread_db_load (LIBTHREAD_DB_SO);
+}
+
+/* Try to load libthread_db from directory DIR of length DIR_LEN.
+   The result is true for success.  */
+
+static int
+try_thread_db_load_from_dir (const char *dir, size_t dir_len)
+{
+  struct cleanup *cleanup;
+  char *path;
+  int result;
+
+  path = xmalloc (dir_len + 1 + strlen (LIBTHREAD_DB_SO) + 1);
+  cleanup = make_cleanup (xfree, path);
+
+  memcpy (path, dir, dir_len);
+  path[dir_len] = '/';
+  strcpy (path + dir_len + 1, LIBTHREAD_DB_SO);
+  result = try_thread_db_load (path);
+
+  do_cleanups (cleanup);
+  return result;
+}
 
 /* Search libthread_db_search_path for libthread_db which "agrees"
-   to work on current inferior.  */
+   to work on current inferior.
+   The result is true for success.  */
 
 static int
 thread_db_load_search (void)
 {
-  char path[PATH_MAX];
   const char *search_path = libthread_db_search_path;
   int rc = 0;
 
   while (*search_path)
     {
       const char *end = strchr (search_path, ':');
+      const char *this_dir = search_path;
+      size_t this_dir_len;
+
       if (end)
        {
-         size_t len = end - search_path;
-          if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
-            {
-              char *cp = xmalloc (len + 1);
-              memcpy (cp, search_path, len);
-              cp[len] = '\0';
-              warning (_("libthread_db_search_path component too long,"
-                         " ignored: %s."), cp);
-              xfree (cp);
-              search_path += len + 1;
-              continue;
-            }
-         memcpy (path, search_path, len);
-         path[len] = '\0';
-         search_path += len + 1;
+         this_dir_len = end - search_path;
+         search_path += this_dir_len + 1;
        }
       else
        {
-          size_t len = strlen (search_path);
+         this_dir_len = strlen (this_dir);
+         search_path += this_dir_len;
+       }
 
-          if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
-            {
-              warning (_("libthread_db_search_path component too long,"
-                         " ignored: %s."), search_path);
-              break;
-            }
-         memcpy (path, search_path, len + 1);
-         search_path += len;
+      if (this_dir_len == sizeof ("$pdir") - 1
+         && strncmp (this_dir, "$pdir", this_dir_len) == 0)
+       {
+         if (try_thread_db_load_from_pdir ())
+           {
+             rc = 1;
+             break;
+           }
        }
-      strcat (path, "/");
-      strcat (path, LIBTHREAD_DB_SO);
-      if (try_thread_db_load (path))
+      else if (this_dir_len == sizeof ("$sdir") - 1
+              && strncmp (this_dir, "$sdir", this_dir_len) == 0)
        {
-         rc = 1;
-         break;
+         if (try_thread_db_load_from_sdir ())
+           {
+             rc = 1;
+             break;
+           }
+       }
+      else
+       {
+         if (try_thread_db_load_from_dir (this_dir, this_dir_len))
+           {
+             rc = 1;
+             break;
+           }
        }
     }
-  if (rc == 0)
-    rc = try_thread_db_load (LIBTHREAD_DB_SO);
+
+  if (libthread_db_debug)
+    printf_unfiltered (_("thread_db_load_search returning %d\n"), rc);
   return rc;
 }
 
+/* Return non-zero if the inferior has a libpthread.  */
+
+static int
+has_libpthread (void)
+{
+  struct objfile *obj;
+
+  ALL_OBJFILES (obj)
+    if (libpthread_name_p (obj->name))
+      return 1;
+
+  return 0;
+}
+
 /* Attempt to load and initialize libthread_db.
-   Return 1 on success.
- */
+   Return 1 on success.  */
 
 static int
 thread_db_load (void)
 {
-  struct objfile *obj;
   struct thread_db_info *info;
 
   info = get_thread_db_info (GET_PID (inferior_ptid));
@@ -827,51 +994,27 @@ thread_db_load (void)
   if (info != NULL)
     return 1;
 
-  /* Don't attempt to use thread_db on targets which can not run
-     (executables not running yet, core files) for now.  */
-  if (!target_has_execution)
+  /* Don't attempt to use thread_db on executables not running
+     yet.  */
+  if (!target_has_registers)
     return 0;
 
   /* Don't attempt to use thread_db for remote targets.  */
-  if (!target_can_run (&current_target))
+  if (!(target_can_run (&current_target) || core_bfd))
     return 0;
 
   if (thread_db_load_search ())
     return 1;
 
-  /* None of the libthread_db's on our search path, not the system default
-     ones worked.  If the executable is dynamically linked against
-     libpthread, try loading libthread_db from the same directory.  */
-
-  ALL_OBJFILES (obj)
-    if (libpthread_name_p (obj->name))
-      {
-       char path[PATH_MAX], *cp;
-
-       gdb_assert (strlen (obj->name) < sizeof (path));
-       strcpy (path, obj->name);
-       cp = strrchr (path, '/');
-
-       if (cp == NULL)
-         {
-           warning (_("Expected absolute pathname for libpthread in the"
-                      " inferior, but got %s."), path);
-         }
-       else if (cp + 1 + strlen (LIBTHREAD_DB_SO) + 1 > path + sizeof (path))
-         {
-           warning (_("Unexpected: path to libpthread in the inferior is"
-                      " too long: %s"), path);
-         }
-       else
-         {
-           strcpy (cp + 1, LIBTHREAD_DB_SO);
-           if (try_thread_db_load (path))
-             return 1;
-         }
-       warning (_("Unable to find libthread_db matching inferior's thread"
-                  " library, thread debugging will not be available."));
-       return 0;
+  /* We couldn't find a libthread_db.
+     If the inferior has a libpthread warn the user.  */
+  if (has_libpthread ())
+    {
+      warning (_("Unable to find libthread_db matching inferior's thread"
+                " library, thread debugging will not be available."));
+      return 0;
     }
+
   /* Either this executable isn't using libpthread at all, or it is
      statically linked.  Since we can't easily distinguish these two cases,
      no warning is issued.  */
@@ -879,20 +1022,18 @@ thread_db_load (void)
 }
 
 static void
-disable_thread_event_reporting (void)
+disable_thread_event_reporting (struct thread_db_info *info)
 {
-  td_thr_events_t events;
-  struct thread_db_info *info;
-
-  info = get_thread_db_info (GET_PID (inferior_ptid));
+  if (info->td_ta_clear_event_p != NULL)
+    {
+      td_thr_events_t events;
 
-  /* Set the process wide mask saying we aren't interested in any
-     events anymore.  */
-  td_event_emptyset (&events);
-  info->td_ta_set_event_p (info->thread_agent, &events);
+      /* Set the process wide mask saying we aren't interested in any
+        events anymore.  */
+      td_event_fillset (&events);
+      info->td_ta_clear_event_p (info->thread_agent, &events);
+    }
 
-  /* Delete thread event breakpoints, if any.  */
-  remove_thread_event_breakpoints ();
   info->td_create_bp_addr = 0;
   info->td_death_bp_addr = 0;
 }
@@ -900,13 +1041,12 @@ disable_thread_event_reporting (void)
 static void
 check_thread_signals (void)
 {
-#ifdef GET_THREAD_SIGNALS
   if (!thread_signals)
     {
       sigset_t mask;
       int i;
 
-      GET_THREAD_SIGNALS (&mask);
+      lin_thread_get_thread_signals (&mask);
       sigemptyset (&thread_stop_set);
       sigemptyset (&thread_print_set);
 
@@ -922,7 +1062,6 @@ check_thread_signals (void)
            }
        }
     }
-#endif
 }
 
 /* Check whether thread_db is usable.  This function is called when
@@ -932,29 +1071,47 @@ check_thread_signals (void)
 void
 check_for_thread_db (void)
 {
-  td_err_e err;
-  static void *last_loaded;
-
   /* Do nothing if we couldn't load libthread_db.so.1.  */
   if (!thread_db_load ())
     return;
 }
 
+/* This function is called via the new_objfile observer.  */
+
 static void
 thread_db_new_objfile (struct objfile *objfile)
 {
   /* This observer must always be called with inferior_ptid set
      correctly.  */
 
-  if (objfile != NULL)
+  if (objfile != NULL
+      /* Only check for thread_db if we loaded libpthread,
+        or if this is the main symbol file.
+        We need to check OBJF_MAINLINE to handle the case of debugging
+        a statically linked executable AND the symbol file is specified AFTER
+        the exec file is loaded (e.g., gdb -c core ; file foo).
+        For dynamically linked executables, libpthread can be near the end
+        of the list of shared libraries to load, and in an app of several
+        thousand shared libraries, this can otherwise be painful.  */
+      && ((objfile->flags & OBJF_MAINLINE) != 0
+         || libpthread_name_p (objfile->name)))
     check_for_thread_db ();
 }
 
+/* This function is called via the inferior_created observer.
+   This handles the case of debugging statically linked executables.  */
+
+static void
+thread_db_inferior_created (struct target_ops *target, int from_tty)
+{
+  check_for_thread_db ();
+}
+
 /* Attach to a new thread.  This function is called when we receive a
    TD_CREATE event or when we iterate over all threads and find one
-   that wasn't already in our list.  */
+   that wasn't already in our list.  Returns true on success.  */
 
-static void
+static int
 attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
               const td_thrinfo_t *ti_p)
 {
@@ -975,7 +1132,7 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
      thread and attach to the new one.  */
   if (in_thread_list (ptid))
     {
-      tp = find_thread_pid (ptid);
+      tp = find_thread_ptid (ptid);
       gdb_assert (tp != NULL);
 
       /* If tp->private is NULL, then GDB is already attached to this
@@ -988,22 +1145,40 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
       if (tp->private != NULL)
        {
          if (!tp->private->dying)
-           return;
+           return 0;
 
          delete_thread (ptid);
          tp = NULL;
        }
     }
 
-  check_thread_signals ();
+  if (target_has_execution)
+    check_thread_signals ();
 
   if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
-    return;                    /* A zombie thread -- do not attach.  */
+    return 0;                  /* A zombie thread -- do not attach.  */
 
   /* Under GNU/Linux, we have to attach to each and every thread.  */
-  if (tp == NULL
-      && lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
-    return;
+  if (target_has_execution
+      && tp == NULL)
+    {
+      int res;
+
+      res = lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)));
+      if (res < 0)
+       {
+         /* Error, stop iterating.  */
+         return 0;
+       }
+      else if (res > 0)
+       {
+         /* Pretend this thread doesn't exist yet, and keep
+            iterating.  */
+         return 1;
+       }
+
+      /* Otherwise, we sucessfully attached to the thread.  */
+    }
 
   /* Construct the thread's private data.  */
   private = xmalloc (sizeof (struct private_thread_info));
@@ -1020,17 +1195,23 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
 
   /* Add the thread to GDB's thread list.  */
   if (tp == NULL)
-    tp = add_thread_with_info (ptid, private);
+    add_thread_with_info (ptid, private);
   else
     tp->private = private;
 
   info = get_thread_db_info (GET_PID (ptid));
 
-  /* Enable thread event reporting for this thread.  */
-  err = info->td_thr_event_enable_p (th_p, 1);
-  if (err != TD_OK)
-    error (_("Cannot enable thread event reporting for %s: %s"),
-          target_pid_to_str (ptid), thread_db_err_str (err));
+  /* Enable thread event reporting for this thread, except when
+     debugging a core file.  */
+  if (target_has_execution)
+    {
+      err = info->td_thr_event_enable_p (th_p, 1);
+      if (err != TD_OK)
+       error (_("Cannot enable thread event reporting for %s: %s"),
+              target_pid_to_str (ptid), thread_db_err_str (err));
+    }
+
+  return 1;
 }
 
 static void
@@ -1046,7 +1227,7 @@ detach_thread (ptid_t ptid)
      until we notice that it's dead (via prune_threads), or until
      something re-uses its thread ID.  We'll report the thread exit
      when the underlying LWP dies.  */
-  thread_info = find_thread_pid (ptid);
+  thread_info = find_thread_ptid (ptid);
   gdb_assert (thread_info != NULL && thread_info->private != NULL);
   thread_info->private->dying = 1;
 }
@@ -1061,14 +1242,17 @@ thread_db_detach (struct target_ops *ops, char *args, int from_tty)
 
   if (info)
     {
-      disable_thread_event_reporting ();
-
-      /* Delete the old thread event breakpoints.  Note that unlike
-        when mourning, we can remove them here because there's still
-        a live inferior to poke at.  In any case, GDB will not try to
-        insert anything in the inferior when removing a
-        breakpoint.  */
-      remove_thread_event_breakpoints ();
+      if (target_has_execution)
+       {
+         disable_thread_event_reporting (info);
+
+         /* Delete the old thread event breakpoints.  Note that
+            unlike when mourning, we can remove them here because
+            there's still a live inferior to poke at.  In any case,
+            GDB will not try to insert anything in the inferior when
+            removing a breakpoint.  */
+         remove_thread_event_breakpoints ();
+       }
 
       delete_thread_db_info (GET_PID (inferior_ptid));
     }
@@ -1178,12 +1362,13 @@ check_event (ptid_t ptid)
 
 static ptid_t
 thread_db_wait (struct target_ops *ops,
-               ptid_t ptid, struct target_waitstatus *ourstatus)
+               ptid_t ptid, struct target_waitstatus *ourstatus,
+               int options)
 {
   struct thread_db_info *info;
   struct target_ops *beneath = find_target_beneath (ops);
 
-  ptid = beneath->to_wait (beneath, ptid, ourstatus);
+  ptid = beneath->to_wait (beneath, ptid, ourstatus, options);
 
   if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
     return ptid;
@@ -1200,18 +1385,15 @@ thread_db_wait (struct target_ops *ops,
 
   if (ourstatus->kind == TARGET_WAITKIND_EXECD)
     {
-      /* Breakpoints have already been marked non-inserted by the
-        layer below.  We're safe in knowing that removing them will
-        not write the shadows of the old image into the new
-        image.  */
-      remove_thread_event_breakpoints ();
-
       /* New image, it may or may not end up using thread_db.  Assume
         not unless we find otherwise.  */
       delete_thread_db_info (GET_PID (ptid));
       if (!thread_db_list)
        unpush_target (&thread_db_ops);
 
+      /* Thread event breakpoints are deleted by
+        update_breakpoints_after_exec.  */
+
       return ptid;
     }
 
@@ -1248,18 +1430,23 @@ thread_db_mourn_inferior (struct target_ops *ops)
 
   delete_thread_db_info (GET_PID (inferior_ptid));
 
-  /* Delete the old thread event breakpoints.  Mark breakpoints out,
-     so that we don't try to un-insert them.  */
-  mark_breakpoints_out ();
-  remove_thread_event_breakpoints ();
-
   target_beneath->to_mourn_inferior (target_beneath);
 
+  /* Delete the old thread event breakpoints.  Do this after mourning
+     the inferior, so that we don't try to uninsert them.  */
+  remove_thread_event_breakpoints ();
+
   /* Detach thread_db target ops.  */
   if (!thread_db_list)
     unpush_target (ops);
 }
 
+struct callback_data
+{
+  struct thread_db_info *info;
+  int new_threads;
+};
+
 static int
 find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
 {
@@ -1267,7 +1454,8 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
   td_err_e err;
   ptid_t ptid;
   struct thread_info *tp;
-  struct thread_db_info *info = data;
+  struct callback_data *cb_data = data;
+  struct thread_db_info *info = cb_data->info;
 
   err = info->td_thr_get_info_p (th_p, &ti);
   if (err != TD_OK)
@@ -1289,10 +1477,13 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
         need this glibc bug workaround.  */
       info->need_stale_parent_threads_check = 0;
 
-      err = info->td_thr_event_enable_p (th_p, 1);
-      if (err != TD_OK)
-       error (_("Cannot enable thread event reporting for LWP %d: %s"),
-              (int) ti.ti_lid, thread_db_err_str (err));
+      if (target_has_execution)
+       {
+         err = info->td_thr_event_enable_p (th_p, 1);
+         if (err != TD_OK)
+           error (_("Cannot enable thread event reporting for LWP %d: %s"),
+                  (int) ti.ti_lid, thread_db_err_str (err));
+       }
 
       return 0;
     }
@@ -1303,67 +1494,154 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
   if (info->need_stale_parent_threads_check)
     {
       int tgid = linux_proc_get_tgid (ti.ti_lid);
+
       if (tgid != -1 && tgid != info->pid)
        return 0;
     }
 
   ptid = ptid_build (info->pid, ti.ti_lid, 0);
-  tp = find_thread_pid (ptid);
+  tp = find_thread_ptid (ptid);
   if (tp == NULL || tp->private == NULL)
-    attach_thread (ptid, th_p, &ti);
+    {
+      if (attach_thread (ptid, th_p, &ti))
+       cb_data->new_threads += 1;
+      else
+       /* Problem attaching this thread; perhaps it exited before we
+          could attach it?
+          This could mean that the thread list inside glibc itself is in
+          inconsistent state, and libthread_db could go on looping forever
+          (observed with glibc-2.3.6).  To prevent that, terminate
+          iteration: thread_db_find_new_threads_2 will retry.  */
+       return 1;
+    }
 
   return 0;
 }
 
+/* Helper for thread_db_find_new_threads_2.
+   Returns number of new threads found.  */
+
+static int
+find_new_threads_once (struct thread_db_info *info, int iteration,
+                      td_err_e *errp)
+{
+  volatile struct gdb_exception except;
+  struct callback_data data;
+  td_err_e err = TD_ERR;
+
+  data.info = info;
+  data.new_threads = 0;
+
+  TRY_CATCH (except, RETURN_MASK_ERROR)
+    {
+      /* Iterate over all user-space threads to discover new threads.  */
+      err = info->td_ta_thr_iter_p (info->thread_agent,
+                                   find_new_threads_callback,
+                                   &data,
+                                   TD_THR_ANY_STATE,
+                                   TD_THR_LOWEST_PRIORITY,
+                                   TD_SIGNO_MASK,
+                                   TD_THR_ANY_USER_FLAGS);
+    }
+
+  if (libthread_db_debug)
+    {
+      if (except.reason < 0)
+       exception_fprintf (gdb_stderr, except,
+                          "Warning: find_new_threads_once: ");
+
+      printf_filtered (_("Found %d new threads in iteration %d.\n"),
+                      data.new_threads, iteration);
+    }
+
+  if (errp != NULL)
+    *errp = err;
+
+  return data.new_threads;
+}
+
 /* Search for new threads, accessing memory through stopped thread
-   PTID.  */
+   PTID.  If UNTIL_NO_NEW is true, repeat searching until several
+   searches in a row do not discover any new threads.  */
 
 static void
-thread_db_find_new_threads_1 (ptid_t ptid)
+thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new)
 {
   td_err_e err;
-  struct lwp_info *lp;
   struct thread_db_info *info;
   int pid = ptid_get_pid (ptid);
-
-  /* In linux, we can only read memory through a stopped lwp.  */
-  ALL_LWPS (lp, ptid)
-    if (lp->stopped && ptid_get_pid (lp->ptid) == pid)
-      break;
-
-  if (!lp)
-    /* There is no stopped thread.  Bail out.  */
-    return;
+  int i, loop;
 
   info = get_thread_db_info (GET_PID (ptid));
 
   /* Access an lwp we know is stopped.  */
   info->proc_handle.ptid = ptid;
-  /* Iterate over all user-space threads to discover new threads.  */
-  err = info->td_ta_thr_iter_p (info->thread_agent, find_new_threads_callback,
-                               info, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
-                               TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
-  if (err != TD_OK)
-    error (_("Cannot find new threads: %s"), thread_db_err_str (err));
+
+  if (until_no_new)
+    {
+      /* Require 4 successive iterations which do not find any new threads.
+        The 4 is a heuristic: there is an inherent race here, and I have
+        seen that 2 iterations in a row are not always sufficient to
+        "capture" all threads.  */
+      for (i = 0, loop = 0; loop < 4; ++i, ++loop)
+       if (find_new_threads_once (info, i, NULL) != 0)
+         /* Found some new threads.  Restart the loop from beginning.  */
+         loop = -1;
+    }
+  else
+    {
+      find_new_threads_once (info, 0, &err);
+      if (err != TD_OK)
+       error (_("Cannot find new threads: %s"), thread_db_err_str (err));
+    }
+}
+
+static void
+thread_db_find_new_threads_1 (ptid_t ptid)
+{
+  thread_db_find_new_threads_2 (ptid, 0);
+}
+
+static int
+update_thread_core (struct lwp_info *info, void *closure)
+{
+  info->core = linux_nat_core_of_thread_1 (info->ptid);
+  return 0;
 }
 
 static void
 thread_db_find_new_threads (struct target_ops *ops)
 {
   struct thread_db_info *info;
+  struct inferior *inf;
 
-  info = get_thread_db_info (GET_PID (inferior_ptid));
+  ALL_INFERIORS (inf)
+    {
+      struct thread_info *thread;
 
-  if (info == NULL)
-    return;
+      if (inf->pid == 0)
+       continue;
 
-  thread_db_find_new_threads_1 (inferior_ptid);
+      info = get_thread_db_info (inf->pid);
+      if (info == NULL)
+       continue;
+
+      thread = any_live_thread_of_process (inf->pid);
+      if (thread == NULL || thread->executing)
+       continue;
+
+      thread_db_find_new_threads_1 (thread->ptid);
+    }
+
+  if (target_has_execution)
+    iterate_over_lwps (minus_one_ptid /* iterate over all */,
+                      update_thread_core, NULL);
 }
 
 static char *
 thread_db_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
-  struct thread_info *thread_info = find_thread_pid (ptid);
+  struct thread_info *thread_info = find_thread_ptid (ptid);
   struct target_ops *beneath;
 
   if (thread_info != NULL && thread_info->private != NULL)
@@ -1417,12 +1695,12 @@ thread_db_get_thread_local_address (struct target_ops *ops,
     thread_db_find_new_threads_1 (ptid);
 
   /* Find the matching thread.  */
-  thread_info = find_thread_pid (ptid);
+  thread_info = find_thread_ptid (ptid);
 
   if (thread_info != NULL && thread_info->private != NULL)
     {
       td_err_e err;
-      void *address;
+      psaddr_t address;
       struct thread_db_info *info;
 
       info = get_thread_db_info (GET_PID (ptid));
@@ -1436,8 +1714,11 @@ thread_db_get_thread_local_address (struct target_ops *ops,
       gdb_assert (lm != 0);
 
       /* Finally, get the address of the variable.  */
+      /* 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 = info->td_thr_tls_get_addr_p (&thread_info->private->th,
-                                        (void *)(size_t) lm,
+                                        (psaddr_t)(uintptr_t) lm,
                                         offset, &address);
 
 #ifdef THREAD_DB_HAS_TD_NOTALLOC
@@ -1556,7 +1837,7 @@ _initialize_thread_db (void)
      executable -- there could be mutiple versions of glibc,
      compiled with LinuxThreads or NPTL, and until there is
      a running inferior, we can't tell which libthread_db is
-     the correct one to load. */
+     the correct one to load.  */
 
   libthread_db_search_path = xstrdup (LIBTHREAD_DB_SEARCH_PATH);
 
@@ -1566,10 +1847,27 @@ _initialize_thread_db (void)
 Set search path for libthread_db."), _("\
 Show the current search path or libthread_db."), _("\
 This path is used to search for libthread_db to be loaded into \
-gdb itself."),
-                           NULL,
+gdb itself.\n\
+Its value is a colon (':') separate list of directories to search.\n\
+Setting the search path to an empty list resets it to its default value."),
+                           set_libthread_db_search_path,
                            NULL,
                            &setlist, &showlist);
+
+  add_setshow_zinteger_cmd ("libthread-db", class_maintenance,
+                           &libthread_db_debug, _("\
+Set libthread-db debugging."), _("\
+Show libthread-db debugging."), _("\
+When non-zero, libthread-db debugging is enabled."),
+                           NULL,
+                           show_libthread_db_debug,
+                           &setdebuglist, &showdebuglist);
+
   /* Add ourselves to objfile event chain.  */
   observer_attach_new_objfile (thread_db_new_objfile);
+
+  /* Add ourselves to inferior_created event chain.
+     This is needed to handle debugging statically linked programs where
+     the new_objfile observer won't get called for libpthread.  */
+  observer_attach_inferior_created (thread_db_inferior_created);
 }
This page took 0.036899 seconds and 4 git commands to generate.