diff options
author | Antoine Tremblay <antoine.tremblay@ericsson.com> | 2015-12-10 10:44:08 -0500 |
---|---|---|
committer | Antoine Tremblay <antoine.tremblay@ericsson.com> | 2015-12-10 10:46:29 -0500 |
commit | c2c2a31fdb228d41ce3db62b268efea04bd39c18 (patch) | |
tree | fd18945dad5df37691b0dd44408fe67f3da4554e | |
parent | 47f8114261a50dcb44bd3be355b705e37d920944 (diff) | |
download | gdb-c2c2a31fdb228d41ce3db62b268efea04bd39c18.zip gdb-c2c2a31fdb228d41ce3db62b268efea04bd39c18.tar.gz gdb-c2c2a31fdb228d41ce3db62b268efea04bd39c18.tar.bz2 |
Remove support for thread events without PTRACE_EVENT_CLONE in GDB
Before, on systems that did not support PTRACE_EVENT_CLONE, both GDB and
GDBServer coordinated with libthread_db.so to insert breakpoints at magic
locations in libpthread.so, in order to break at thread creation and
thread death.
Support for thread events was removed from GDBServer as patch:
https://sourceware.org/ml/gdb-patches/2015-11/msg00466.html
This patch removes support for thread events in GDB.
No regressions found on Ubuntu 14.04 x86_64.
gdb/ChangeLog:
* breakpoint.c (remove_thread_event_breakpoints): Remove.
* breakpoint.h (remove_thread_event_breakpoints): Remove
declaration.
* linux-nat.c (in_pid_list_p): Remove.
(lin_lwp_attach_lwp): Remove.
* linux-nat.h (lin_lwp_attach_lwp): Remove declaration.
* linux-thread-db.c (thread_db_use_events): Remove.
(struct thread_db_info) <td_create_bp_addr>: Remove.
<td_death_bp_addr>: Likewise.
<td_ta_event_addr_p>: Likewise.
<td_ta_set_event_p>: Likewise.
<td_ta_clear_event_p>: Likewise.
<td_ta_event_getmsg_p>: Likewise.
<td_thr_event_enable_p>: Likewise.
(attach_thread): Likewise.
(detach_thread): Likewise.
(have_threads_callback): Likewise.
(have_threads): Likewise.
(enable_thread_event): Likewise.
(enable_thread_event_reporting): Likewise.
(try_thread_db_load_1): Remove td_ta_event_addr, td_ta_set_event,
td_ta_clear_event, td_ta_event_getmsg, td_thr_event_enable
initializations.
(try_thread_db_load_1): Remove enable_thread_event_reporting call.
(disable_thread_event_reporting): Remove.
(record_thread): Adapt to thread_db_use_event removal.
(detach_thread): Remove.
(thread_db_detach): Adapt to thread_db_use_event removal.
(check_event): Remove.
(thread_db_wait): Adapt to thread events support removal.
(thread_db_mourn_inferior): Likewise.
(find_new_threads_callback): Likewise.
(find_new_threads_once): Likewise.
(thread_db_update_thread_list): Likewise.
-rw-r--r-- | gdb/ChangeLog | 37 | ||||
-rw-r--r-- | gdb/breakpoint.c | 11 | ||||
-rw-r--r-- | gdb/breakpoint.h | 2 | ||||
-rw-r--r-- | gdb/linux-nat.c | 144 | ||||
-rw-r--r-- | gdb/linux-nat.h | 2 | ||||
-rw-r--r-- | gdb/linux-thread-db.c | 437 |
6 files changed, 46 insertions, 587 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1151dc8..65354bf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,40 @@ +2015-12-10 Antoine Tremblay <antoine.tremblay@ericsson.com> + + * breakpoint.c (remove_thread_event_breakpoints): Remove. + * breakpoint.h (remove_thread_event_breakpoints): Remove + declaration. + * linux-nat.c (in_pid_list_p): Remove. + (lin_lwp_attach_lwp): Remove. + * linux-nat.h (lin_lwp_attach_lwp): Remove declaration. + * linux-thread-db.c (thread_db_use_events): Remove. + (struct thread_db_info) <td_create_bp_addr>: Remove. + <td_death_bp_addr>: Likewise. + <td_ta_event_addr_p>: Likewise. + <td_ta_set_event_p>: Likewise. + <td_ta_clear_event_p>: Likewise. + <td_ta_event_getmsg_p>: Likewise. + <td_thr_event_enable_p>: Likewise. + (attach_thread): Likewise. + (detach_thread): Likewise. + (have_threads_callback): Likewise. + (have_threads): Likewise. + (enable_thread_event): Likewise. + (enable_thread_event_reporting): Likewise. + (try_thread_db_load_1): Remove td_ta_event_addr, td_ta_set_event, + td_ta_clear_event, td_ta_event_getmsg, td_thr_event_enable + initializations. + (try_thread_db_load_1): Remove enable_thread_event_reporting call. + (disable_thread_event_reporting): Remove. + (record_thread): Adapt to thread_db_use_event removal. + (detach_thread): Remove. + (thread_db_detach): Adapt to thread_db_use_event removal. + (check_event): Remove. + (thread_db_wait): Adapt to thread events support removal. + (thread_db_mourn_inferior): Likewise. + (find_new_threads_callback): Likewise. + (find_new_threads_once): Likewise. + (thread_db_update_thread_list): Likewise. + 2015-12-10 Andrew Burgess <andrew.burgess@embecosm.com> * dwarf2read.c (dwarf2_ranges_read): Unify and fix base address diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index bc6b2ef..f105042 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -7765,17 +7765,6 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) return b; } -void -remove_thread_event_breakpoints (void) -{ - struct breakpoint *b, *b_tmp; - - ALL_BREAKPOINTS_SAFE (b, b_tmp) - if (b->type == bp_thread_event - && b->loc->pspace == current_program_space) - delete_breakpoint (b); -} - struct lang_and_radix { enum language lang; diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index ee8b2e0..7079b75 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1498,8 +1498,6 @@ extern void remove_solib_event_breakpoints (void); delete at next stop disposition. */ extern void remove_solib_event_breakpoints_at_next_stop (void); -extern void remove_thread_event_breakpoints (void); - extern void disable_breakpoints_in_shlibs (void); /* This function returns TRUE if ep is a catchpoint. */ diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 9bc1324..95192f6 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -345,17 +345,6 @@ add_to_pid_list (struct simple_pid_list **listp, int pid, int status) } static int -in_pid_list_p (struct simple_pid_list *list, int pid) -{ - struct simple_pid_list *p; - - for (p = list; p != NULL; p = p->next) - if (p->pid == pid) - return 1; - return 0; -} - -static int pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp) { struct simple_pid_list **p; @@ -1044,139 +1033,6 @@ linux_nat_post_attach_wait (ptid_t ptid, int first, int *cloned, return status; } -/* Attach to the LWP specified by PID. Return 0 if successful, -1 if - the new LWP could not be attached, or 1 if we're already auto - attached to this thread, but haven't processed the - PTRACE_EVENT_CLONE event of its parent thread, so we just ignore - its existance, without considering it an error. */ - -int -lin_lwp_attach_lwp (ptid_t ptid) -{ - struct lwp_info *lp; - int lwpid; - - gdb_assert (ptid_lwp_p (ptid)); - - lp = find_lwp_pid (ptid); - lwpid = ptid_get_lwp (ptid); - - /* We assume that we're already attached to any LWP that is already - in our list of LWPs. If we're not seeing exit events from threads - and we've had PID wraparound since we last tried to stop all threads, - this assumption might be wrong; fortunately, this is very unlikely - to happen. */ - if (lp == NULL) - { - int status, cloned = 0, signalled = 0; - - if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) < 0) - { - if (linux_supports_tracefork ()) - { - /* If we haven't stopped all threads when we get here, - we may have seen a thread listed in thread_db's list, - but not processed the PTRACE_EVENT_CLONE yet. If - that's the case, ignore this new thread, and let - normal event handling discover it later. */ - if (in_pid_list_p (stopped_pids, lwpid)) - { - /* We've already seen this thread stop, but we - haven't seen the PTRACE_EVENT_CLONE extended - event yet. */ - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "LLAL: attach failed, but already seen " - "this thread %s stop\n", - target_pid_to_str (ptid)); - return 1; - } - else - { - int new_pid; - int status; - - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "LLAL: attach failed, and haven't seen " - "this thread %s stop yet\n", - target_pid_to_str (ptid)); - - /* We may or may not be attached to the LWP already. - Try waitpid on it. If that errors, we're not - attached to the LWP yet. Otherwise, we're - already attached. */ - gdb_assert (lwpid > 0); - new_pid = my_waitpid (lwpid, &status, WNOHANG); - if (new_pid == -1 && errno == ECHILD) - new_pid = my_waitpid (lwpid, &status, __WCLONE | WNOHANG); - if (new_pid != -1) - { - if (new_pid == 0) - { - /* The child hasn't stopped for its initial - SIGSTOP stop yet. */ - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "LLAL: child hasn't " - "stopped yet\n"); - } - else if (WIFSTOPPED (status)) - { - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "LLAL: adding to stopped_pids\n"); - add_to_pid_list (&stopped_pids, lwpid, status); - } - return 1; - } - } - } - - /* If we fail to attach to the thread, issue a warning, - but continue. One way this can happen is if thread - creation is interrupted; as of Linux kernel 2.6.19, a - bug may place threads in the thread list and then fail - to create them. */ - warning (_("Can't attach %s: %s"), target_pid_to_str (ptid), - safe_strerror (errno)); - return -1; - } - - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n", - target_pid_to_str (ptid)); - - status = linux_nat_post_attach_wait (ptid, 0, &cloned, &signalled); - if (!WIFSTOPPED (status)) - return 1; - - lp = add_lwp (ptid); - lp->stopped = 1; - lp->last_resume_kind = resume_stop; - lp->cloned = cloned; - lp->signalled = signalled; - if (WSTOPSIG (status) != SIGSTOP) - { - lp->resumed = 1; - lp->status = status; - } - - target_post_attach (ptid_get_lwp (lp->ptid)); - - if (debug_linux_nat) - { - fprintf_unfiltered (gdb_stdlog, - "LLAL: waitpid %s received %s\n", - target_pid_to_str (ptid), - status_to_str (status)); - } - } - - return 0; -} - static void linux_nat_create_inferior (struct target_ops *ops, char *exec_file, char *allargs, char **env, diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h index f7b45f7..f5ec74e 100644 --- a/gdb/linux-nat.h +++ b/gdb/linux-nat.h @@ -141,8 +141,6 @@ extern void lin_thread_get_thread_signals (sigset_t *mask); void linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigset_t *ignored); -extern int lin_lwp_attach_lwp (ptid_t ptid); - /* For linux_stop_lwp see nat/linux-nat.h. */ /* Stop all LWPs, synchronously. (Any events that trigger while LWPs diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index 229bb0b..8a80ca3 100644 --- a/gdb/linux-thread-db.c +++ b/gdb/linux-thread-db.c @@ -78,16 +78,6 @@ static char *libthread_db_search_path; by the "set auto-load libthread-db" command. */ static int auto_load_thread_db = 1; -/* Returns true if we need to use thread_db thread create/death event - breakpoints to learn about threads. */ - -static int -thread_db_use_events (void) -{ - /* Not necessary if the kernel supports clone events. */ - return !linux_supports_traceclone (); -} - /* "show" command for the auto_load_thread_db configuration variable. */ static void @@ -161,30 +151,14 @@ struct thread_db_info be able to ignore such stale entries. */ int need_stale_parent_threads_check; - /* Location of the thread creation event breakpoint. The code at - this location in the child process will be called by the pthread - library whenever a new thread is created. By setting a special - breakpoint at this location, GDB can detect when a new thread is - created. We obtain this location via the td_ta_event_addr - call. */ - CORE_ADDR td_create_bp_addr; - - /* Location of the thread death event breakpoint. */ - CORE_ADDR td_death_bp_addr; - /* Pointers to the libthread_db functions. */ td_init_ftype *td_init_p; td_ta_new_ftype *td_ta_new_p; td_ta_map_lwp2thr_ftype *td_ta_map_lwp2thr_p; td_ta_thr_iter_ftype *td_ta_thr_iter_p; - td_ta_event_addr_ftype *td_ta_event_addr_p; - td_ta_set_event_ftype *td_ta_set_event_p; - td_ta_clear_event_ftype *td_ta_clear_event_p; - td_ta_event_getmsg_ftype * td_ta_event_getmsg_p; td_thr_validate_ftype *td_thr_validate_p; td_thr_get_info_ftype *td_thr_get_info_p; - td_thr_event_enable_ftype *td_thr_event_enable_p; td_thr_tls_get_addr_ftype *td_thr_tls_get_addr_p; td_thr_tlsbase_ftype *td_thr_tlsbase_p; }; @@ -273,12 +247,6 @@ delete_thread_db_info (int pid) xfree (info); } -/* Prototypes for local functions. */ -static int attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, - const td_thrinfo_t *ti_p); -static void detach_thread (ptid_t ptid); - - /* Use "struct private_thread_info" to cache thread state. This is a substantial optimization. */ @@ -359,30 +327,7 @@ thread_db_err_str (td_err_e err) return buf; } } - -/* 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 *args) -{ - int pid = * (int *) args; - - if (ptid_get_pid (thread->ptid) != pid) - return 0; - - return thread->priv != NULL; -} - -static int -have_threads (ptid_t ptid) -{ - int pid = ptid_get_pid (ptid); - - return iterate_over_threads (have_threads_callback, &pid) != NULL; -} - /* Fetch the user-level thread id of PTID. */ static struct thread_info * @@ -455,37 +400,6 @@ verbose_dlsym (void *handle, const char *name) return sym; } -static td_err_e -enable_thread_event (td_event_e event, CORE_ADDR *bp) -{ - td_notify_t notify; - td_err_e err; - struct thread_db_info *info; - - info = get_thread_db_info (ptid_get_pid (inferior_ptid)); - - /* Access an lwp we know is stopped. */ - info->proc_handle.ptid = inferior_ptid; - - /* Get the breakpoint address for thread EVENT. */ - err = info->td_ta_event_addr_p (info->thread_agent, event, ¬ify); - if (err != TD_OK) - return err; - - /* Set up the breakpoint. */ - gdb_assert (exec_bfd); - (*bp) = (gdbarch_convert_from_func_ptr_addr - (target_gdbarch (), - /* Do proper sign extension for the target. */ - (bfd_get_sign_extend_vma (exec_bfd) > 0 - ? (CORE_ADDR) (intptr_t) notify.u.bptaddr - : (CORE_ADDR) (uintptr_t) notify.u.bptaddr), - ¤t_target)); - create_thread_event_breakpoint (target_gdbarch (), *bp); - - return TD_OK; -} - /* Verify inferior's '\0'-terminated symbol VER_SYMBOL starts with "%d.%d" and return 1 if this version is lower (and not equal) to VER_MAJOR_MIN.VER_MINOR_MIN. Return 0 in all other cases. */ @@ -517,68 +431,6 @@ inferior_has_bug (const char *ver_symbol, int ver_major_min, int ver_minor_min) return retval; } -static void -enable_thread_event_reporting (void) -{ - td_thr_events_t events; - td_err_e err; - struct thread_db_info *info; - - info = get_thread_db_info (ptid_get_pid (inferior_ptid)); - - /* We cannot use the thread event reporting facility if these - functions aren't available. */ - if (info->td_ta_event_addr_p == NULL - || info->td_ta_set_event_p == NULL - || info->td_ta_event_getmsg_p == NULL - || info->td_thr_event_enable_p == NULL) - return; - - /* Set the process wide mask saying which events we're interested in. */ - td_event_emptyset (&events); - td_event_addset (&events, TD_CREATE); - - /* There is a bug fixed between linuxthreads 2.1.3 and 2.2 by - commit 2e4581e4fba917f1779cd0a010a45698586c190a - * manager.c (pthread_exited): Correctly report event as TD_REAP - instead of TD_DEATH. Fix comments. - where event reporting facility is broken for TD_DEATH events, - so don't enable it if we have glibc but a lower version. */ - if (!inferior_has_bug ("__linuxthreads_version", 2, 2)) - td_event_addset (&events, TD_DEATH); - - err = info->td_ta_set_event_p (info->thread_agent, &events); - if (err != TD_OK) - { - warning (_("Unable to set global thread event mask: %s"), - thread_db_err_str (err)); - return; - } - - /* Delete previous thread event breakpoints, if any. */ - remove_thread_event_breakpoints (); - info->td_create_bp_addr = 0; - info->td_death_bp_addr = 0; - - /* Set up the thread creation event. */ - err = enable_thread_event (TD_CREATE, &info->td_create_bp_addr); - if (err != TD_OK) - { - warning (_("Unable to get location for thread creation breakpoint: %s"), - thread_db_err_str (err)); - return; - } - - /* Set up the thread death event. */ - err = enable_thread_event (TD_DEATH, &info->td_death_bp_addr); - if (err != TD_OK) - { - warning (_("Unable to get location for thread death breakpoint: %s"), - thread_db_err_str (err)); - return; - } -} - /* Similar as thread_db_find_new_threads_1, but try to silently ignore errors if appropriate. @@ -716,11 +568,6 @@ try_thread_db_load_1 (struct thread_db_info *info) CHK (TDB_VERBOSE_DLSYM (info, td_thr_get_info)); /* These are not essential. */ - TDB_DLSYM (info, td_ta_event_addr); - TDB_DLSYM (info, td_ta_set_event); - TDB_DLSYM (info, td_ta_clear_event); - TDB_DLSYM (info, td_ta_event_getmsg); - TDB_DLSYM (info, td_thr_event_enable); TDB_DLSYM (info, td_thr_tls_get_addr); TDB_DLSYM (info, td_thr_tlsbase); @@ -784,10 +631,6 @@ try_thread_db_load_1 (struct thread_db_info *info) if (thread_db_list->next == NULL) push_target (&thread_db_ops); - /* Enable event reporting, but not when debugging a core file. */ - if (target_has_execution && thread_db_use_events ()) - enable_thread_event_reporting (); - return 1; } @@ -1096,23 +939,6 @@ thread_db_load (void) } static void -disable_thread_event_reporting (struct thread_db_info *info) -{ - if (info->td_ta_clear_event_p != NULL) - { - td_thr_events_t events; - - /* Set the process wide mask saying we aren't interested in any - events anymore. */ - td_event_fillset (&events); - info->td_ta_clear_event_p (info->thread_agent, &events); - } - - info->td_create_bp_addr = 0; - info->td_death_bp_addr = 0; -} - -static void check_thread_signals (void) { if (!thread_signals) @@ -1219,75 +1045,6 @@ update_thread_state (struct private_thread_info *priv, || ti_p->ti_state == TD_THR_ZOMBIE); } -/* Attach to a new thread. This function is called when we receive a - TD_CREATE event or when we iterate over all threads and find one - that wasn't already in our list. Returns true on success. */ - -static int -attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, - const td_thrinfo_t *ti_p) -{ - struct thread_info *tp; - struct thread_db_info *info; - - /* If we're being called after a TD_CREATE event, we may already - know about this thread. There are two ways this can happen. We - may have iterated over all threads between the thread creation - and the TD_CREATE event, for instance when the user has issued - the `info threads' command before the SIGTRAP for hitting the - thread creation breakpoint was reported. Alternatively, the - thread may have exited and a new one been created with the same - thread ID. In the first case we don't need to do anything; in - the second case we should discard information about the dead - thread and attach to the new one. */ - tp = find_thread_ptid (ptid); - if (tp != NULL) - { - /* If tp->priv is NULL, then GDB is already attached to this - thread, but we do not know anything about it. We can learn - about it here. This can only happen if we have some other - way besides libthread_db to notice new threads (i.e. - PTRACE_EVENT_CLONE); assume the same mechanism notices thread - exit, so this can not be a stale thread recreated with the - same ID. */ - if (tp->priv != NULL) - { - if (!tp->priv->dying) - return 0; - - delete_thread (ptid); - tp = NULL; - } - } - - /* Under GNU/Linux, we have to attach to each and every thread. */ - if (target_has_execution - && tp == NULL) - { - int res; - - res = lin_lwp_attach_lwp (ptid_build (ptid_get_pid (ptid), - ti_p->ti_lid, 0)); - if (res < 0) - { - /* Error, stop iterating. */ - return 0; - } - else if (res > 0) - { - /* Pretend this thread doesn't exist yet, and keep - iterating. */ - return 1; - } - - /* Otherwise, we sucessfully attached to the thread. */ - } - - info = get_thread_db_info (ptid_get_pid (ptid)); - record_thread (info, tp, ptid, th_p, ti_p); - return 1; -} - /* Record a new thread in GDB's thread list. Creates the thread's private info. If TP is NULL or TP is marked as having exited, creates a new thread. Otherwise, uses TP. */ @@ -1323,16 +1080,6 @@ record_thread (struct thread_db_info *info, else tp->priv = priv; - /* Enable thread event reporting for this thread, except when - debugging a core file. */ - if (target_has_execution && thread_db_use_events () && new_thread) - { - err = info->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)); - } - if (target_has_execution) check_thread_signals (); @@ -1340,24 +1087,6 @@ record_thread (struct thread_db_info *info, } static void -detach_thread (ptid_t ptid) -{ - struct thread_info *thread_info; - - /* Don't delete the thread now, because it still reports as active - until it has executed a few instructions after the event - breakpoint - if we deleted it now, "info threads" would cause us - to re-attach to it. Just mark it as having had a TD_DEATH - event. This means that we won't delete it from our thread list - until we notice that it's dead (via prune_threads), or until - something re-uses its thread ID. We'll report the thread exit - when the underlying LWP dies. */ - thread_info = find_thread_ptid (ptid); - gdb_assert (thread_info != NULL && thread_info->priv != NULL); - thread_info->priv->dying = 1; -} - -static void thread_db_detach (struct target_ops *ops, const char *args, int from_tty) { struct target_ops *target_beneath = find_target_beneath (ops); @@ -1366,21 +1095,7 @@ thread_db_detach (struct target_ops *ops, const char *args, int from_tty) info = get_thread_db_info (ptid_get_pid (inferior_ptid)); if (info) - { - if (target_has_execution && thread_db_use_events ()) - { - disable_thread_event_reporting (info); - - /* Delete the old thread event breakpoints. Note that - unlike when mourning, we can remove them here because - there's still a live inferior to poke at. In any case, - GDB will not try to insert anything in the inferior when - removing a breakpoint. */ - remove_thread_event_breakpoints (); - } - - delete_thread_db_info (ptid_get_pid (inferior_ptid)); - } + delete_thread_db_info (ptid_get_pid (inferior_ptid)); target_beneath->to_detach (target_beneath, args, from_tty); @@ -1392,101 +1107,6 @@ thread_db_detach (struct target_ops *ops, const char *args, int from_tty) unpush_target (&thread_db_ops); } -/* Check if PID is currently stopped at the location of a thread event - breakpoint location. If it is, read the event message and act upon - the event. */ - -static void -check_event (ptid_t ptid) -{ - struct regcache *regcache = get_thread_regcache (ptid); - struct gdbarch *gdbarch = get_regcache_arch (regcache); - td_event_msg_t msg; - td_thrinfo_t ti; - td_err_e err; - CORE_ADDR stop_pc; - int loop = 0; - struct thread_db_info *info; - - info = get_thread_db_info (ptid_get_pid (ptid)); - - /* Bail out early if we're not at a thread event breakpoint. */ - stop_pc = regcache_read_pc (regcache); - if (!target_supports_stopped_by_sw_breakpoint ()) - stop_pc -= gdbarch_decr_pc_after_break (gdbarch); - - if (stop_pc != info->td_create_bp_addr - && stop_pc != info->td_death_bp_addr) - return; - - /* Access an lwp we know is stopped. */ - info->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 (ptid)) - thread_db_find_new_threads_1 (ptid); - - /* 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. - We have to call td_ta_event_getmsg() to get - the latest message. Since we have no way of correlating whether - the event message we get back corresponds to our breakpoint, we must - loop and read all event messages, processing them appropriately. - This guarantees we will process the correct message before continuing - from the breakpoint. - - Currently, death events are not enabled. If they are enabled, - the death event can use the td_thr_event_getmsg() interface to - get the message specifically for that lwp and avoid looping - below. */ - - loop = 1; - - do - { - err = info->td_ta_event_getmsg_p (info->thread_agent, &msg); - if (err != TD_OK) - { - if (err == TD_NOMSG) - return; - - error (_("Cannot get thread event message: %s"), - thread_db_err_str (err)); - } - - err = info->td_thr_get_info_p (msg.th_p, &ti); - if (err != TD_OK) - error (_("Cannot get thread info: %s"), thread_db_err_str (err)); - - ptid = ptid_build (ptid_get_pid (ptid), ti.ti_lid, 0); - - switch (msg.event) - { - case TD_CREATE: - /* Call attach_thread whether or not we already know about a - thread with this thread ID. */ - attach_thread (ptid, msg.th_p, &ti); - - break; - - case TD_DEATH: - - if (!in_thread_list (ptid)) - error (_("Spurious thread death event.")); - - detach_thread (ptid); - - break; - - default: - error (_("Spurious thread event.")); - } - } - while (loop); -} - static ptid_t thread_db_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *ourstatus, @@ -1518,17 +1138,9 @@ thread_db_wait (struct target_ops *ops, if (!thread_db_list) unpush_target (&thread_db_ops); - /* Thread event breakpoints are deleted by - update_breakpoints_after_exec. */ - return ptid; } - if (ourstatus->kind == TARGET_WAITKIND_STOPPED - && ourstatus->value.sig == GDB_SIGNAL_TRAP) - /* Check for a thread event. */ - check_event (ptid); - /* Fill in the thread's user-level thread id and status. */ thread_from_lwp (ptid); @@ -1544,10 +1156,6 @@ thread_db_mourn_inferior (struct target_ops *ops) 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. */ if (!thread_db_list) unpush_target (ops); @@ -1595,21 +1203,12 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data) /* 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. */ + be yet. */ /* In that case, we're not stopped in a fork syscall and don't need this glibc bug workaround. */ info->need_stale_parent_threads_check = 0; - if (target_has_execution && thread_db_use_events ()) - { - err = info->td_thr_event_enable_p (th_p, 1); - if (err != TD_OK) - error (_("Cannot enable thread event reporting for LWP %d: %s"), - (int) ti.ti_lid, thread_db_err_str (err)); - } - return 0; } @@ -1627,24 +1226,7 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data) ptid = ptid_build (info->pid, ti.ti_lid, 0); tp = find_thread_ptid (ptid); if (tp == NULL || tp->priv == NULL) - { - if (attach_thread (ptid, th_p, &ti)) - cb_data->new_threads += 1; - else - /* Problem attaching this thread; perhaps it exited before we - could attach it? - This could mean that the thread list inside glibc itself is in - inconsistent state, and libthread_db could go on looping forever - (observed with glibc-2.3.6). To prevent that, terminate - iteration: thread_db_find_new_threads_2 will retry. */ - return 1; - } - else if (target_has_execution && !thread_db_use_events ()) - { - /* Need to update this if not using the libthread_db events - (particularly, the TD_DEATH event). */ - update_thread_state (tp->priv, &ti); - } + thread_from_lwp (ptid); return 0; } @@ -1663,7 +1245,7 @@ find_new_threads_once (struct thread_db_info *info, int iteration, data.new_threads = 0; /* See comment in thread_db_update_thread_list. */ - gdb_assert (!target_has_execution || thread_db_use_events ()); + gdb_assert (!target_has_execution); TRY { @@ -1789,12 +1371,11 @@ thread_db_update_thread_list (struct target_ops *ops) it. In the latter case, it's possible that a thread exits just at the exact time that causes GDB to get stuck in an infinite loop. To avoid pausing all threads whenever the core wants to - refresh the thread list, if the kernel supports clone events - (meaning we're always already attached to all LWPs), we use - thread_from_lwp immediately when we see an LWP stop. That uses - thread_db entry points that do not walk libpthread's thread list, - so should be safe, as well as more efficient. */ - if (target_has_execution && !thread_db_use_events ()) + refresh the thread list, use thread_from_lwp immediately when we + see an LWP stop. That uses thread_db entry points that do not + walk libpthread's thread list, so should be safe, as well as + more efficient. */ + if (target_has_execution) ops->beneath->to_update_thread_list (ops->beneath); else thread_db_update_thread_list_td_ta_thr_iter (ops); |