static int
have_threads_callback (struct thread_info *thread, void *dummy)
{
- return 1;
+ return thread->private != NULL;
}
static int
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);
}
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"),
}
\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)
{
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, ¬ify);
if (err != TD_OK)
}
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 ();
static void
check_event (ptid_t ptid)
{
+ struct regcache *regcache = get_thread_regcache (ptid);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
td_event_msg_t msg;
td_thrinfo_t ti;
td_err_e err;
int loop = 0;
/* Bail out early if we're not at a thread event breakpoint. */
- stop_pc = read_pc_pid (ptid) - gdbarch_decr_pc_after_break (current_gdbarch);
+ stop_pc = regcache_read_pc (regcache)
+ - gdbarch_decr_pc_after_break (gdbarch);
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
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)
{
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
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;
}
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;
}
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,
_("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)
{
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;
}