summaryrefslogtreecommitdiff
path: root/gdb/gdbserver/thread-db.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/gdbserver/thread-db.c')
-rw-r--r--gdb/gdbserver/thread-db.c148
1 files changed, 86 insertions, 62 deletions
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c
index 76900014eea..4962f96eeff 100644
--- a/gdb/gdbserver/thread-db.c
+++ b/gdb/gdbserver/thread-db.c
@@ -35,15 +35,37 @@ static int thread_db_use_events;
#include <stdint.h>
-/* Structure that identifies the child process for the
- <proc_service.h> interface. */
-static struct ps_prochandle proc_handle;
+static int find_one_thread (ptid_t);
+static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
-/* Connection to the libthread_db library. */
-static td_thragent_t *thread_agent;
+static void
+fixup_proc_handle (void)
+{
+ ptid_t inferior_ptid;
+ struct process_info_private *proc = current_process ()->private;
-static int find_one_thread (int);
-static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
+ /* FIXME drow/2004-10-16: This is the "overall process ID", which
+ 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. */
+
+ /* We're actually passing the current lwp to proc_services. This is
+ because in non-stop mode, the tgid process may be running at this
+ point --- linux doesn't allow reading memory through running
+ LWPs. At this point, I'm not sure if it's useful to actually
+ have a proc_handle.pid instead of just making proc_services
+ return current_inferior->id.pid directly. */
+
+ inferior_ptid = ((struct inferior_list_entry *)current_inferior)->id;
+
+ proc->proc_handle.pid = ptid_get_lwp (inferior_ptid);
+}
static char *
thread_db_err_str (td_err_e err)
@@ -136,16 +158,18 @@ thread_db_create_event (CORE_ADDR where)
{
td_event_msg_t msg;
td_err_e err;
- struct process_info *process;
+ struct lwp_info *lwp;
if (debug_threads)
fprintf (stderr, "Thread creation event.\n");
+ fixup_proc_handle ();
+
/* 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 = td_ta_event_getmsg (thread_agent, &msg);
+ err = td_ta_event_getmsg (current_process()->private->thread_agent, &msg);
if (err != TD_OK)
fprintf (stderr, "thread getmsg err: %s\n",
thread_db_err_str (err));
@@ -153,9 +177,9 @@ thread_db_create_event (CORE_ADDR where)
/* 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. */
- process = get_thread_process (current_inferior);
- if (process->thread_known == 0)
- find_one_thread (process->lwpid);
+ lwp = get_thread_lwp (current_inferior);
+ if (lwp->thread_known == 0)
+ find_one_thread (lwp->head.id);
/* msg.event == TD_EVENT_CREATE */
@@ -181,6 +205,7 @@ thread_db_enable_reporting ()
td_thr_events_t events;
td_notify_t notify;
td_err_e err;
+ struct process_info_private *proc = current_process()->private;
/* Set the process wide mask saying which events we're interested in. */
td_event_emptyset (&events);
@@ -192,7 +217,7 @@ thread_db_enable_reporting ()
td_event_addset (&events, TD_DEATH);
#endif
- err = td_ta_set_event (thread_agent, &events);
+ err = td_ta_set_event (proc->thread_agent, &events);
if (err != TD_OK)
{
warning ("Unable to set global thread event mask: %s",
@@ -201,13 +226,14 @@ thread_db_enable_reporting ()
}
/* Get address for thread creation breakpoint. */
- err = td_ta_event_addr (thread_agent, TD_CREATE, &notify);
+ err = td_ta_event_addr (proc->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;
}
+
set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
thread_db_create_event);
@@ -216,7 +242,7 @@ thread_db_enable_reporting ()
with actual thread deaths (via wait). */
/* Get address for thread death breakpoint. */
- err = td_ta_event_addr (thread_agent, TD_DEATH, &notify);
+ err = td_ta_event_addr (proc->thread_agent, TD_DEATH, &notify);
if (err != TD_OK)
{
warning ("Unable to get location for thread death breakpoint: %s",
@@ -231,21 +257,22 @@ thread_db_enable_reporting ()
}
static int
-find_one_thread (int lwpid)
+find_one_thread (ptid_t ptid)
{
td_thrhandle_t th;
td_thrinfo_t ti;
td_err_e err;
struct thread_info *inferior;
- struct process_info *process;
+ struct lwp_info *lwp;
+ int lwpid = ptid_get_lwp (ptid);
- inferior = (struct thread_info *) find_inferior_id (&all_threads, lwpid);
- process = get_thread_process (inferior);
- if (process->thread_known)
+ inferior = (struct thread_info *) find_inferior_id (&all_threads, ptid);
+ lwp = get_thread_lwp (inferior);
+ if (lwp->thread_known)
return 1;
/* Get information about this thread. */
- err = td_ta_map_lwp2thr (thread_agent, process->lwpid, &th);
+ err = td_ta_map_lwp2thr (current_process()->private->thread_agent, lwpid, &th);
if (err != TD_OK)
error ("Cannot get thread handle for LWP %d: %s",
lwpid, thread_db_err_str (err));
@@ -259,10 +286,10 @@ find_one_thread (int lwpid)
fprintf (stderr, "Found thread %ld (LWP %d)\n",
ti.ti_tid, ti.ti_lid);
- if (process->lwpid != ti.ti_lid)
+ if (lwpid != ti.ti_lid)
{
warning ("PID mismatch! Expected %ld, got %ld",
- (long) process->lwpid, (long) ti.ti_lid);
+ (long) lwpid, (long) ti.ti_lid);
return 0;
}
@@ -279,9 +306,9 @@ find_one_thread (int lwpid)
if (ti.ti_tid == 0)
return 0;
- process->thread_known = 1;
- process->tid = ti.ti_tid;
- process->th = th;
+ lwp->thread_known = 1;
+ lwp->tid = ti.ti_tid;
+ lwp->th = th;
return 1;
}
@@ -290,32 +317,27 @@ static void
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
{
td_err_e err;
- struct thread_info *inferior;
- struct process_info *process;
+ struct lwp_info *lwp;
- inferior = (struct thread_info *) find_inferior_id (&all_threads,
- ti_p->ti_lid);
- if (inferior != NULL)
+ lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
+ if (lwp != NULL)
return;
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);
- inferior = (struct thread_info *) find_inferior_id (&all_threads,
- ti_p->ti_lid);
- if (inferior == NULL)
+ linux_attach_lwp (ti_p->ti_lid, 0);
+ lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
+ if (lwp == NULL)
{
warning ("Could not attach to thread %ld (LWP %d)\n",
ti_p->ti_tid, ti_p->ti_lid);
return;
}
- process = inferior_target_data (inferior);
-
- process->tid = ti_p->ti_tid;
- process->thread_known = 1;
- process->th = *th_p;
+ lwp->tid = ti_p->ti_tid;
+ lwp->thread_known = 1;
+ lwp->th = *th_p;
if (thread_db_use_events)
{
@@ -349,15 +371,22 @@ static void
thread_db_find_new_threads (void)
{
td_err_e err;
+ ptid_t ptid = ((struct inferior_list_entry *)current_inferior)->id;
/* This function is only called when we first initialize thread_db.
First locate the initial thread. If it is not ready for
debugging yet, then stop. */
- if (find_one_thread (all_threads.head->id) == 0)
+ /* Is there any harm done in using the current inferior for
+ this? */
+ if (find_one_thread (ptid) == 0)
return;
+ /* Make sure we give thread_db the right lwp to talk to. */
+ fixup_proc_handle ();
+
/* Iterate over all user-space threads to discover new threads. */
- err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
+ err = td_ta_thr_iter (current_process()->private->thread_agent,
+ find_new_threads_callback, NULL,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
if (err != TD_OK)
@@ -386,18 +415,21 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
#if HAVE_TD_THR_TLS_GET_ADDR
psaddr_t addr;
td_err_e err;
- struct process_info *process;
+ struct lwp_info *lwp;
+
+ /* Make sure we give thread_db the right lwp to talk to. */
+ fixup_proc_handle ();
- process = get_thread_process (thread);
- if (!process->thread_known)
- find_one_thread (process->lwpid);
- if (!process->thread_known)
+ lwp = get_thread_lwp (thread);
+ if (!lwp->thread_known)
+ find_one_thread (lwp->head.id);
+ if (!lwp->thread_known)
return TD_NOTHR;
/* 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 = td_thr_tls_get_addr (&process->th, (psaddr_t) (uintptr_t) load_module,
+ err = td_thr_tls_get_addr (&lwp->th, (psaddr_t) (uintptr_t) load_module,
offset, &addr);
if (err == TD_OK)
{
@@ -415,25 +447,17 @@ int
thread_db_init (int use_events)
{
int err;
+ struct process_info *proc = current_process ();
+ struct process_info_private *priv = proc->private;
- /* FIXME drow/2004-10-16: This is the "overall process ID", which
- 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. */
- proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
+ fixup_proc_handle ();
/* Allow new symbol lookups. */
- all_symbols_looked_up = 0;
+ proc->all_symbols_looked_up = 0;
thread_db_use_events = use_events;
- err = td_ta_new (&proc_handle, &thread_agent);
+ err = td_ta_new (&priv->proc_handle, &priv->thread_agent);
switch (err)
{
case TD_NOLIBTHREAD:
@@ -447,7 +471,7 @@ thread_db_init (int use_events)
return 0;
thread_db_find_new_threads ();
thread_db_look_up_symbols ();
- all_symbols_looked_up = 1;
+ proc->all_symbols_looked_up = 1;
return 1;
default: