diff options
Diffstat (limited to 'gdb/gdbserver/thread-db.c')
-rw-r--r-- | gdb/gdbserver/thread-db.c | 148 |
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, ¬ify); + err = td_ta_event_addr (proc->thread_agent, TD_CREATE, ¬ify); 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, ¬ify); + err = td_ta_event_addr (proc->thread_agent, TD_DEATH, ¬ify); 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: |