* infrun.c (handle_inferior_event): On a TARGET_WAITKIND_EXITED or
[deliverable/binutils-gdb.git] / gdb / linux-thread-db.c
index c7aaf6065d87a70e2263e3a704bc9c6d81d8bba6..cf0dd6a8ff5b5814e5a674ea253a51e6a064bde2 100644 (file)
@@ -283,7 +283,10 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *infop)
   if (thread_info == NULL)
     {
       /* New thread.  Attach to it now (why wait?).  */
-      attach_thread (thread_ptid, thp, &ti);
+      if (!have_threads ())
+       thread_db_find_new_threads ();
+      else
+       attach_thread (thread_ptid, thp, &ti);
       thread_info = find_thread_pid (thread_ptid);
       gdb_assert (thread_info != NULL);
     }
@@ -308,6 +311,8 @@ thread_from_lwp (ptid_t ptid)
      LWP.  */
   gdb_assert (GET_LWP (ptid) != 0);
 
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
   err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
   if (err != TD_OK)
     error (_("Cannot find user-level thread for LWP %ld: %s"),
@@ -332,6 +337,48 @@ thread_from_lwp (ptid_t ptid)
 }
 \f
 
+/* Attach to lwp PTID, doing whatever else is required to have this
+   LWP under the debugger's control --- e.g., enabling event
+   reporting.  Returns true on success.  */
+int
+thread_db_attach_lwp (ptid_t ptid)
+{
+  td_thrhandle_t th;
+  td_thrinfo_t ti;
+  td_err_e err;
+
+  if (!using_thread_db)
+    return 0;
+
+  /* This ptid comes from linux-nat.c, which should always fill in the
+     LWP.  */
+  gdb_assert (GET_LWP (ptid) != 0);
+
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
+
+  /* If we have only looked at the first thread before libpthread was
+     initialized, we may not know its thread ID yet.  Make sure we do
+     before we add another thread to the list.  */
+  if (!have_threads ())
+    thread_db_find_new_threads ();
+
+  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+  if (err != TD_OK)
+    /* Cannot find user-level thread.  */
+    return 0;
+
+  err = td_thr_get_info_p (&th, &ti);
+  if (err != TD_OK)
+    {
+      warning (_("Cannot get thread info: %s"), thread_db_err_str (err));
+      return 0;
+    }
+
+  attach_thread (ptid, &th, &ti);
+  return 1;
+}
+
 void
 thread_db_init (struct target_ops *target)
 {
@@ -418,6 +465,9 @@ enable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp)
   td_notify_t notify;
   td_err_e err;
 
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (inferior_ptid);
+
   /* Get the breakpoint address for thread EVENT.  */
   err = td_ta_event_addr_p (thread_agent, event, &notify);
   if (err != TD_OK)
@@ -730,11 +780,11 @@ detach_thread (ptid_t ptid)
 }
 
 static void
-thread_db_detach (char *args, int from_tty)
+thread_db_detach (struct target_ops *ops, char *args, int from_tty)
 {
   disable_thread_event_reporting ();
 
-  target_beneath->to_detach (args, from_tty);
+  target_beneath->to_detach (target_beneath, args, from_tty);
 
   /* Should this be done by detach_command?  */
   target_mourn_inferior ();
@@ -761,6 +811,15 @@ check_event (ptid_t ptid)
   if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
     return;
 
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
+
+  /* If we have only looked at the first thread before libpthread was
+     initialized, we may not know its thread ID yet.  Make sure we do
+     before we add another thread to the list.  */
+  if (!have_threads ())
+    thread_db_find_new_threads ();
+
   /* If we are at a create breakpoint, we do not know what new lwp
      was created and cannot specifically locate the event message for it.
      We have to call td_ta_event_getmsg() to get
@@ -823,16 +882,14 @@ check_event (ptid_t ptid)
 static ptid_t
 thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 {
-  extern ptid_t trap_ptid;
-
   ptid = target_beneath->to_wait (ptid, ourstatus);
 
   if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
     return ptid;
 
   if (ourstatus->kind == TARGET_WAITKIND_EXITED
-    || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
-    return pid_to_ptid (-1);
+      || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
+    return ptid;
 
   if (ourstatus->kind == TARGET_WAITKIND_EXECD)
     {
@@ -840,7 +897,7 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
       unpush_target (&thread_db_ops);
       using_thread_db = 0;
 
-      return pid_to_ptid (GET_PID (ptid));
+      return ptid;
     }
 
   /* If we do not know about the main thread yet, this would be a good time to
@@ -861,9 +918,6 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
         event gets postponed by other simultaneous events.  In such a
         case, we want to just ignore the event and continue on.  */
 
-      if (!ptid_equal (trap_ptid, null_ptid))
-       trap_ptid = thread_from_lwp (trap_ptid);
-
       ptid = thread_from_lwp (ptid);
       if (GET_PID (ptid) == -1)
        ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
@@ -873,20 +927,20 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 }
 
 static void
-thread_db_mourn_inferior (void)
+thread_db_mourn_inferior (struct target_ops *ops)
 {
   /* Forget about the child's process ID.  We shouldn't need it
      anymore.  */
   proc_handle.pid = 0;
 
-  target_beneath->to_mourn_inferior ();
+  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.  */
-  unpush_target (&thread_db_ops);
+  unpush_target (ops);
   using_thread_db = 0;
 }
 
@@ -956,11 +1010,27 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
   return 0;
 }
 
+/* Search for new threads, accessing memory through stopped thread
+   PTID.  */
+
 static void
 thread_db_find_new_threads (void)
 {
   td_err_e err;
+  struct lwp_info *lp;
+  ptid_t ptid;
 
+  /* In linux, we can only read memory through a stopped lwp.  */
+  ALL_LWPS (lp, ptid)
+    if (lp->stopped)
+      break;
+
+  if (!lp)
+    /* There is no stopped thread.  Bail out.  */
+    return;
+
+  /* Access an lwp we know is stopped.  */
+  proc_handle.pid = GET_LWP (ptid);
   /* Iterate over all user-space threads to discover new threads.  */
   err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
                          TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
@@ -1073,6 +1143,35 @@ thread_db_get_thread_local_address (ptid_t ptid,
                 _("TLS not supported on this target"));
 }
 
+/* Callback routine used to find a thread based on the TID part of
+   its PTID.  */
+
+static int
+thread_db_find_thread_from_tid (struct thread_info *thread, void *data)
+{
+  long *tid = (long *) data;
+
+  if (thread->private->tid == *tid)
+    return 1;
+
+  return 0;
+}
+
+/* Implement the to_get_ada_task_ptid target method for this target.  */
+
+static ptid_t
+thread_db_get_ada_task_ptid (long lwp, long thread)
+{
+  struct thread_info *thread_info;
+
+  thread_db_find_new_threads ();
+  thread_info = iterate_over_threads (thread_db_find_thread_from_tid, &thread);
+
+  gdb_assert (thread_info != NULL);
+
+  return (thread_info->ptid);
+}
+
 static void
 init_thread_db_ops (void)
 {
@@ -1093,6 +1192,7 @@ init_thread_db_ops (void)
   thread_db_ops.to_is_async_p = thread_db_is_async_p;
   thread_db_ops.to_async = thread_db_async;
   thread_db_ops.to_async_mask = thread_db_async_mask;
+  thread_db_ops.to_get_ada_task_ptid = thread_db_get_ada_task_ptid;
   thread_db_ops.to_magic = OPS_MAGIC;
 }
 
This page took 0.026816 seconds and 4 git commands to generate.