diff options
Diffstat (limited to 'gdb/gdbserver/thread-db.c')
-rw-r--r-- | gdb/gdbserver/thread-db.c | 110 |
1 files changed, 70 insertions, 40 deletions
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c index f3b85617ff8..5566e0e8129 100644 --- a/gdb/gdbserver/thread-db.c +++ b/gdb/gdbserver/thread-db.c @@ -41,7 +41,7 @@ static struct ps_prochandle proc_handle; /* Connection to the libthread_db library. */ static td_thragent_t *thread_agent; -static void thread_db_find_new_threads (void); +static int find_first_thread (void); static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data); static char * @@ -135,15 +135,11 @@ thread_db_create_event (CORE_ADDR where) { td_event_msg_t msg; td_err_e err; - struct inferior_linux_data *tdata; - struct thread_info *inferior; struct process_info *process; if (debug_threads) fprintf (stderr, "Thread creation event.\n"); - tdata = inferior_target_data (current_inferior); - /* FIXME: This assumes we don't get another event. In the LinuxThreads implementation, this is safe, because all events come from the manager thread @@ -156,10 +152,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. */ - inferior = (struct thread_info *) all_threads.head; - process = get_thread_process (inferior); + process = get_thread_process (current_inferior); if (process->thread_known == 0) - thread_db_find_new_threads (); + find_first_thread (); /* msg.event == TD_EVENT_CREATE */ @@ -230,43 +225,73 @@ thread_db_enable_reporting () return 1; } -static void -maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p) +static int +find_first_thread (void) { + td_thrhandle_t th; + td_thrinfo_t ti; td_err_e err; struct thread_info *inferior; struct process_info *process; - /* If we are attaching to our first thread, things are a little - different. */ - if (all_threads.head == all_threads.tail) + inferior = (struct thread_info *) all_threads.head; + process = get_thread_process (inferior); + if (process->thread_known) + return 1; + + /* Get information about the one thread we know we have. */ + err = td_ta_map_lwp2thr (thread_agent, process->lwpid, &th); + if (err != TD_OK) + error ("Cannot get first thread handle: %s", thread_db_err_str (err)); + + err = td_thr_get_info (&th, &ti); + if (err != TD_OK) + error ("Cannot get first thread info: %s", thread_db_err_str (err)); + + if (debug_threads) + fprintf (stderr, "Found first thread %ld (LWP %d)\n", + ti.ti_tid, ti.ti_lid); + + if (process->lwpid != ti.ti_lid) + fatal ("PID mismatch! Expected %ld, got %ld", + (long) process->lwpid, (long) ti.ti_lid); + + /* If the new thread ID is zero, a final thread ID will be available + later. Do not enable thread debugging yet. */ + if (ti.ti_tid == 0) { - inferior = (struct thread_info *) all_threads.head; - process = get_thread_process (inferior); - - if (process->thread_known == 0) - { - /* If the new thread ID is zero, a final thread ID will be - available later. Do not enable thread debugging yet. */ - if (ti_p->ti_tid == 0) - { - err = td_thr_event_enable (th_p, 1); - if (err != TD_OK) - error ("Cannot enable thread event reporting for %d: %s", - ti_p->ti_lid, thread_db_err_str (err)); - return; - } - - if (process->lwpid != ti_p->ti_lid) - fatal ("PID mismatch! Expected %ld, got %ld", - (long) process->lwpid, (long) ti_p->ti_lid); - - /* Switch to indexing the threads list by TID. */ - change_inferior_id (&all_threads, ti_p->ti_tid); - goto found; - } + err = td_thr_event_enable (&th, 1); + if (err != TD_OK) + error ("Cannot enable thread event reporting for %d: %s", + ti.ti_lid, thread_db_err_str (err)); + return 0; } - + + /* Switch to indexing the threads list by TID. */ + change_inferior_id (&all_threads, ti.ti_tid); + + new_thread_notify (ti.ti_tid); + + process->tid = ti.ti_tid; + process->lwpid = ti.ti_lid; + process->thread_known = 1; + process->th = th; + + err = td_thr_event_enable (&th, 1); + if (err != TD_OK) + error ("Cannot enable thread event reporting for %d: %s", + ti.ti_lid, thread_db_err_str (err)); + + return 1; +} + +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; + inferior = (struct thread_info *) find_inferior_id (&all_threads, ti_p->ti_tid); if (inferior != NULL) @@ -287,7 +312,6 @@ maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p) process = inferior_target_data (inferior); -found: new_thread_notify (ti_p->ti_tid); process->tid = ti_p->ti_tid; @@ -325,6 +349,12 @@ thread_db_find_new_threads (void) { td_err_e err; + /* 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_first_thread () == 0) + return; + /* Iterate over all user-space threads to discover new threads. */ err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, @@ -359,7 +389,7 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset, process = get_thread_process (thread); if (!process->thread_known) - thread_db_find_new_threads (); + find_first_thread (); if (!process->thread_known) return TD_NOTHR; |