From 4105de343e714e0096723905ada442f1524776a6 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Wed, 27 Jun 2007 11:52:02 +0000 Subject: [PATCH] * linux-thread-db.c (thread_db_attach): Delete. (thread_db_detach): Typo fix. Call target_mourn_inferior instead of fixing up proc_handle. (have_threads_callback, have_threads): New functions. (thread_db_wait): Remove dead proc_handle.pid check. Only translate PTIDs if we have registered threads. Check for new threads if we have none. (thread_db_create_inferior, thread_db_post_startup_inferior): Delete. (find_new_threads_callback): Only enable event reporting if TID == 0. (same_ptid_callback): New. (thread_db_get_thread_local_address): Check for new threads. (init_thread_db_ops): Don't set to_attach, to_create_inferior, or to_post_startup_inferior. * thread-db.c (thread_db_find_new_threads): Add prototype. (thread_db_create_event): Check for the main thread before adding a new thread. (maybe_attach_thread): Only enable event reporting if TID == 0. (thread_db_get_tls_address): Check for new threads. --- gdb/ChangeLog | 16 +++++ gdb/gdbserver/ChangeLog | 8 +++ gdb/gdbserver/thread-db.c | 29 +++++++++ gdb/linux-thread-db.c | 146 +++++++++++++++++++++++++--------------------- 4 files changed, 133 insertions(+), 66 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e9ea35b..ca29274 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2007-06-27 Daniel Jacobowitz + + * linux-thread-db.c (thread_db_attach): Delete. + (thread_db_detach): Typo fix. Call target_mourn_inferior + instead of fixing up proc_handle. + (have_threads_callback, have_threads): New functions. + (thread_db_wait): Remove dead proc_handle.pid check. Only + translate PTIDs if we have registered threads. Check for new + threads if we have none. + (thread_db_create_inferior, thread_db_post_startup_inferior): Delete. + (find_new_threads_callback): Only enable event reporting if TID == 0. + (same_ptid_callback): New. + (thread_db_get_thread_local_address): Check for new threads. + (init_thread_db_ops): Don't set to_attach, to_create_inferior, + or to_post_startup_inferior. + 2007-06-22 Ulrich Weigand * infrun.c (adjust_pc_after_break): Do not assume software single-step diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 1b96c68..0f25df7 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2007-06-27 Daniel Jacobowitz + + * thread-db.c (thread_db_find_new_threads): Add prototype. + (thread_db_create_event): Check for the main thread before adding + a new thread. + (maybe_attach_thread): Only enable event reporting if TID == 0. + (thread_db_get_tls_address): Check for new threads. + 2007-06-20 Daniel Jacobowitz * linux-low.c (linux_create_inferior): Try execv before execvp. diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c index ec70400..f3b8561 100644 --- a/gdb/gdbserver/thread-db.c +++ b/gdb/gdbserver/thread-db.c @@ -41,6 +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_new_threads_callback (const td_thrhandle_t *th_p, void *data); static char * @@ -135,6 +136,8 @@ 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"); @@ -150,6 +153,14 @@ thread_db_create_event (CORE_ADDR where) fprintf (stderr, "thread getmsg err: %s\n", thread_db_err_str (err)); + /* 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); + if (process->thread_known == 0) + thread_db_find_new_threads (); + /* msg.event == TD_EVENT_CREATE */ find_new_threads_callback (msg.th_p, NULL); @@ -232,8 +243,24 @@ maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p) { 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; @@ -332,6 +359,8 @@ 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 (); + if (!process->thread_known) return TD_NOTHR; /* Note the cast through uintptr_t: this interface only works if diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index eb7bb80..460e044 100644 --- a/gdb/linux-thread-db.c +++ b/gdb/linux-thread-db.c @@ -220,6 +220,21 @@ thread_db_err_str (td_err_e err) } } +/* Return 1 if any threads have been registered. There may be none if + the threading library is not fully initialized yet. */ + +static int +have_threads_callback (struct thread_info *thread, void *dummy) +{ + return 1; +} + +static int +have_threads (void) +{ + return iterate_over_threads (have_threads_callback, NULL) != NULL; +} + /* A callback function for td_ta_thr_iter, which we use to map all threads to LWPs. @@ -707,23 +722,6 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, } static void -thread_db_attach (char *args, int from_tty) -{ - target_beneath->to_attach (args, from_tty); - - /* Destroy thread info; it's no longer valid. */ - init_thread_list (); - - /* The child process is now the actual multi-threaded - program. Snatch its process ID... */ - proc_handle.pid = GET_PID (inferior_ptid); - - /* ...and perform the remaining initialization steps. */ - enable_thread_event_reporting (); - thread_db_find_new_threads (); -} - -static void detach_thread (ptid_t ptid, int verbose) { struct thread_info *thread_info; @@ -749,14 +747,13 @@ thread_db_detach (char *args, int from_tty) disable_thread_event_reporting (); /* There's no need to save & restore inferior_ptid here, since the - inferior is supposed to be survive this function call. */ + inferior is not supposed to survive this function call. */ inferior_ptid = lwp_from_thread (inferior_ptid); - /* Forget about the child's process ID. We shouldn't need it - anymore. */ - proc_handle.pid = 0; - target_beneath->to_detach (args, from_tty); + + /* Should this be done by detach_command? */ + target_mourn_inferior (); } static int @@ -877,12 +874,6 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus) ptid = target_beneath->to_wait (ptid, ourstatus); - if (proc_handle.pid == 0) - /* The current child process isn't the actual multi-threaded - program yet, so don't try to do any special thread-specific - post-processing and bail out early. */ - return ptid; - if (ourstatus->kind == TARGET_WAITKIND_EXITED || ourstatus->kind == TARGET_WAITKIND_SIGNALLED) return pid_to_ptid (-1); @@ -896,23 +887,32 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus) return pid_to_ptid (GET_PID (ptid)); } + /* 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 (); + if (ourstatus->kind == TARGET_WAITKIND_STOPPED && ourstatus->value.sig == TARGET_SIGNAL_TRAP) /* Check for a thread event. */ check_event (ptid); - if (!ptid_equal (trap_ptid, null_ptid)) - trap_ptid = thread_from_lwp (trap_ptid); + if (have_threads ()) + { + /* Change ptids back into the higher level PID + TID format. If + the thread is dead and no longer on the thread list, we will + get back a dead ptid. This can occur if the thread death + 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; + } - /* Change the ptid back into the higher level PID + TID format. - If the thread is dead and no longer on the thread list, we will - get back a dead ptid. This can occur if the thread death event - gets postponed by other simultaneous events. In such a case, - we want to just ignore the event and continue on. */ - ptid = thread_from_lwp (ptid); - if (GET_PID (ptid) == -1) - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - return ptid; } @@ -926,30 +926,6 @@ thread_db_kill (void) } static void -thread_db_create_inferior (char *exec_file, char *allargs, char **env, - int from_tty) -{ - unpush_target (&thread_db_ops); - using_thread_db = 0; - target_beneath->to_create_inferior (exec_file, allargs, env, from_tty); -} - -static void -thread_db_post_startup_inferior (ptid_t ptid) -{ - if (proc_handle.pid == 0) - { - /* The child process is now the actual multi-threaded - program. Snatch its process ID... */ - proc_handle.pid = GET_PID (ptid); - - /* ...and perform the remaining initialization steps. */ - enable_thread_event_reporting (); - thread_db_find_new_threads (); - } -} - -static void thread_db_mourn_inferior (void) { /* Forget about the child's process ID. We shouldn't need it @@ -984,6 +960,22 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data) ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid); + if (ti.ti_tid == 0) + { + /* A thread ID of zero means that this is the main thread, but + glibc has not yet initialized thread-local storage and the + pthread library. We do not know what the thread's TID will + be yet. Just enable event reporting and otherwise ignore + it. */ + + err = td_thr_event_enable_p (th_p, 1); + if (err != TD_OK) + error (_("Cannot enable thread event reporting for %s: %s"), + target_pid_to_str (ptid), thread_db_err_str (err)); + + return 0; + } + if (!in_thread_list (ptid)) attach_thread (ptid, th_p, &ti, 1); @@ -1040,6 +1032,16 @@ thread_db_extra_thread_info (struct thread_info *info) return NULL; } +/* Return 1 if this thread has the same LWP as the passed PTID. */ + +static int +same_ptid_callback (struct thread_info *thread, void *arg) +{ + ptid_t *ptid_p = arg; + + return GET_LWP (thread->ptid) == GET_LWP (*ptid_p); +} + /* Get the address of the thread local variable in load module LM which is stored at OFFSET within the thread local storage for thread PTID. */ @@ -1048,6 +1050,21 @@ thread_db_get_thread_local_address (ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset) { + /* If we have not discovered any threads yet, check now. */ + if (!is_thread (ptid) && !have_threads ()) + thread_db_find_new_threads (); + + /* Try to find a matching thread if we still have the LWP ID instead + of the thread ID. */ + if (!is_thread (ptid)) + { + struct thread_info *thread; + + thread = iterate_over_threads (same_ptid_callback, &ptid); + if (thread != NULL) + ptid = thread->ptid; + } + if (is_thread (ptid)) { td_err_e err; @@ -1107,13 +1124,10 @@ init_thread_db_ops (void) thread_db_ops.to_shortname = "multi-thread"; thread_db_ops.to_longname = "multi-threaded child process."; thread_db_ops.to_doc = "Threads and pthreads support."; - thread_db_ops.to_attach = thread_db_attach; thread_db_ops.to_detach = thread_db_detach; thread_db_ops.to_resume = thread_db_resume; thread_db_ops.to_wait = thread_db_wait; thread_db_ops.to_kill = thread_db_kill; - thread_db_ops.to_create_inferior = thread_db_create_inferior; - thread_db_ops.to_post_startup_inferior = thread_db_post_startup_inferior; thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior; thread_db_ops.to_find_new_threads = thread_db_find_new_threads; thread_db_ops.to_pid_to_str = thread_db_pid_to_str; -- 2.7.4