/* libthread_db assisted debugging support, generic parts.
- Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GDB.
/* This module's target vector. */
static struct target_ops thread_db_ops;
-/* The target vector that we call for things this module can't handle. */
-static struct target_ops *target_beneath;
-
/* Non-zero if we're using this module's target vector. */
static int using_thread_db;
static CORE_ADDR td_death_bp_addr;
/* Prototypes for local functions. */
-static void thread_db_find_new_threads (void);
+static void thread_db_find_new_threads_1 (void);
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p);
static void detach_thread (ptid_t ptid);
thread_db_err_str (err));
/* Fill the cache. */
- thread_ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, 0);
+ thread_ptid = ptid_build (GET_PID (proc_handle.ptid), ti.ti_lid, 0);
thread_info = find_thread_pid (thread_ptid);
/* In the case of a zombie thread, don't continue. We don't want to
{
/* New thread. Attach to it now (why wait?). */
if (!have_threads ())
- thread_db_find_new_threads ();
+ thread_db_find_new_threads_1 ();
else
attach_thread (thread_ptid, thp, &ti);
thread_info = find_thread_pid (thread_ptid);
gdb_assert (GET_LWP (ptid) != 0);
/* Access an lwp we know is stopped. */
- proc_handle.pid = GET_LWP (ptid);
+ proc_handle.ptid = 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"),
gdb_assert (GET_LWP (ptid) != 0);
/* Access an lwp we know is stopped. */
- proc_handle.pid = GET_LWP (ptid);
+ proc_handle.ptid = 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 ();
+ thread_db_find_new_threads_1 ();
err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
if (err != TD_OK)
return 1;
}
-void
-thread_db_init (struct target_ops *target)
-{
- target_beneath = target;
-}
-
static void *
verbose_dlsym (void *handle, const char *name)
{
td_err_e err;
/* Access an lwp we know is stopped. */
- proc_handle.pid = GET_LWP (inferior_ptid);
+ proc_handle.ptid = inferior_ptid;
/* Get the breakpoint address for thread EVENT. */
err = td_ta_event_addr_p (thread_agent, event, ¬ify);
return;
/* Initialize the structure that identifies the child process. */
- proc_handle.pid = GET_PID (inferior_ptid);
+ proc_handle.ptid = inferior_ptid;
/* Now attempt to open a connection to the thread library. */
err = td_ta_new_p (&proc_handle, &thread_agent);
using_thread_db = 1;
enable_thread_event_reporting ();
- thread_db_find_new_threads ();
+ thread_db_find_new_threads_1 ();
break;
default:
}
static void
-thread_db_detach (char *args, int from_tty)
+thread_db_detach (struct target_ops *ops, char *args, int from_tty)
{
+ struct target_ops *target_beneath = find_target_beneath (ops);
+
disable_thread_event_reporting ();
- target_beneath->to_detach (args, from_tty);
+ /* Forget about the child's process ID. We shouldn't need it
+ anymore. */
+ proc_handle.ptid = null_ptid;
- /* Should this be done by detach_command? */
- target_mourn_inferior ();
+ /* Detach thread_db target ops. */
+ unpush_target (&thread_db_ops);
+ using_thread_db = 0;
+
+ target_beneath->to_detach (target_beneath, args, from_tty);
}
/* Check if PID is currently stopped at the location of a thread event
return;
/* Access an lwp we know is stopped. */
- proc_handle.pid = GET_LWP (ptid);
+ proc_handle.ptid = 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 ();
+ thread_db_find_new_threads_1 ();
/* 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.
}
static ptid_t
-thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+thread_db_wait (struct target_ops *ops,
+ ptid_t ptid, struct target_waitstatus *ourstatus)
{
- ptid = target_beneath->to_wait (ptid, ourstatus);
+ struct target_ops *beneath = find_target_beneath (ops);
+
+ ptid = beneath->to_wait (beneath, 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)
{
/* If we do not know about the main thread yet, this would be a good time to
find it. */
if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ())
- thread_db_find_new_threads ();
+ thread_db_find_new_threads_1 ();
if (ourstatus->kind == TARGET_WAITKIND_STOPPED
&& ourstatus->value.sig == TARGET_SIGNAL_TRAP)
}
static void
-thread_db_mourn_inferior (void)
+thread_db_mourn_inferior (struct target_ops *ops)
{
+ struct target_ops *target_beneath = find_target_beneath (ops);
+
/* Forget about the child's process ID. We shouldn't need it
anymore. */
- proc_handle.pid = 0;
+ proc_handle.ptid = null_ptid;
- 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;
}
-static int
-thread_db_can_async_p (void)
-{
- return target_beneath->to_can_async_p ();
-}
-
-static int
-thread_db_is_async_p (void)
-{
- return target_beneath->to_is_async_p ();
-}
-
-static void
-thread_db_async (void (*callback) (enum inferior_event_type event_type,
- void *context), void *context)
-{
- return target_beneath->to_async (callback, context);
-}
-
-static int
-thread_db_async_mask (int mask)
-{
- return target_beneath->to_async_mask (mask);
-}
-
static int
find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
{
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
return 0; /* A zombie -- ignore. */
- ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, 0);
+ ptid = ptid_build (GET_PID (proc_handle.ptid), ti.ti_lid, 0);
if (ti.ti_tid == 0)
{
PTID. */
static void
-thread_db_find_new_threads (void)
+thread_db_find_new_threads_1 (void)
{
td_err_e err;
struct lwp_info *lp;
return;
/* Access an lwp we know is stopped. */
- proc_handle.pid = GET_LWP (ptid);
+ proc_handle.ptid = 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,
error (_("Cannot find new threads: %s"), thread_db_err_str (err));
}
+static void
+thread_db_find_new_threads (struct target_ops *ops)
+{
+ thread_db_find_new_threads_1 ();
+}
+
static char *
-thread_db_pid_to_str (ptid_t ptid)
+thread_db_pid_to_str (struct target_ops *ops, ptid_t ptid)
{
struct thread_info *thread_info = find_thread_pid (ptid);
+ struct target_ops *beneath;
if (thread_info != NULL && thread_info->private != NULL)
{
return buf;
}
- if (target_beneath->to_pid_to_str (ptid))
- return target_beneath->to_pid_to_str (ptid);
+ beneath = find_target_beneath (ops);
+ if (beneath->to_pid_to_str (beneath, ptid))
+ return beneath->to_pid_to_str (beneath, ptid);
return normal_pid_to_str (ptid);
}
is stored at OFFSET within the thread local storage for thread PTID. */
static CORE_ADDR
-thread_db_get_thread_local_address (ptid_t ptid,
+thread_db_get_thread_local_address (struct target_ops *ops,
+ ptid_t ptid,
CORE_ADDR lm,
CORE_ADDR offset)
{
struct thread_info *thread_info;
+ struct target_ops *beneath;
/* If we have not discovered any threads yet, check now. */
if (!have_threads ())
- thread_db_find_new_threads ();
+ thread_db_find_new_threads_1 ();
/* Find the matching thread. */
thread_info = find_thread_pid (ptid);
: (CORE_ADDR) (uintptr_t) address);
}
- if (target_beneath->to_get_thread_local_address)
- return target_beneath->to_get_thread_local_address (ptid, lm, offset);
+ beneath = find_target_beneath (ops);
+ if (beneath->to_get_thread_local_address)
+ return beneath->to_get_thread_local_address (beneath, ptid, lm, offset);
else
throw_error (TLS_GENERIC_ERROR,
_("TLS not supported on this target"));
{
struct thread_info *thread_info;
- thread_db_find_new_threads ();
+ thread_db_find_new_threads_1 ();
thread_info = iterate_over_threads (thread_db_find_thread_from_tid, &thread);
gdb_assert (thread_info != NULL);
thread_db_ops.to_get_thread_local_address
= thread_db_get_thread_local_address;
thread_db_ops.to_extra_thread_info = thread_db_extra_thread_info;
- thread_db_ops.to_can_async_p = thread_db_can_async_p;
- 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;
}
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_thread_db;
+
void
_initialize_thread_db (void)
{