diff options
-rw-r--r-- | gdb/infrun.c | 15 | ||||
-rw-r--r-- | gdb/remote.c | 9 | ||||
-rw-r--r-- | gdb/target/target.c | 1 | ||||
-rw-r--r-- | gdb/target/target.h | 4 |
4 files changed, 24 insertions, 5 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index e1e761c..0a189d0 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2516,24 +2516,29 @@ do_target_resume (ptid_t resume_ptid, bool step, enum gdb_signal sig) else target_pass_signals (signal_pass); - /* Request that the target report thread-{created,cloned} events in - the following situations: + /* Request that the target report thread-{created,cloned,exited} + events in the following situations: - If we are performing an in-line step-over-breakpoint, then we will remove a breakpoint from the target and only run the current thread. We don't want any new thread (spawned by the - step) to start running, as it might miss the breakpoint. + step) to start running, as it might miss the breakpoint. We + need to clear the step-over state if the stepped thread exits, + so we also enable thread-exit events. - If we are stepping over a breakpoint out of line (displaced stepping) then we won't remove a breakpoint from the target, but, if the step spawns a new clone thread, then we will need to fixup the $pc address in the clone child too, so we need it - to start stopped. + to start stopped. We need to release the displaced stepping + buffer if the stepped thread exits, so we also enable + thread-exit events. */ if (step_over_info_valid_p () || displaced_step_in_progress_thread (tp)) { - gdb_thread_options options = GDB_THREAD_OPTION_CLONE; + gdb_thread_options options + = GDB_THREAD_OPTION_CLONE | GDB_THREAD_OPTION_EXIT; if (target_supports_set_thread_options (options)) tp->set_thread_options (options); else diff --git a/gdb/remote.c b/gdb/remote.c index eb537fc..ce5adda 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -4206,6 +4206,15 @@ remote_target::update_thread_list () if (has_single_non_exited_thread (tp->inf)) continue; + /* Do not remove the thread if we've requested to be + notified of its exit. For example, the thread may be + displaced stepping, infrun will need to handle the + exit event, and displaced stepping info is recorded + in the thread object. If we deleted the thread now, + we'd lose that info. */ + if ((tp->thread_options () & GDB_THREAD_OPTION_EXIT) != 0) + continue; + /* Not found. */ delete_thread (tp); } diff --git a/gdb/target/target.c b/gdb/target/target.c index 3af7d73..58d0f63 100644 --- a/gdb/target/target.c +++ b/gdb/target/target.c @@ -196,6 +196,7 @@ to_string (gdb_thread_options options) { static constexpr gdb_thread_options::string_mapping mapping[] = { MAP_ENUM_FLAG (GDB_THREAD_OPTION_CLONE), + MAP_ENUM_FLAG (GDB_THREAD_OPTION_EXIT), }; return options.to_string (mapping); } diff --git a/gdb/target/target.h b/gdb/target/target.h index 2691f92..bad4daa 100644 --- a/gdb/target/target.h +++ b/gdb/target/target.h @@ -34,6 +34,10 @@ enum gdb_thread_option : unsigned /* Tell the target to report TARGET_WAITKIND_THREAD_CLONED events for the thread. */ GDB_THREAD_OPTION_CLONE = 1 << 0, + + /* Tell the target to report TARGET_WAITKIND_THREAD_EXIT events for + the thread. */ + GDB_THREAD_OPTION_EXIT = 1 << 1, }; DEF_ENUM_FLAGS_TYPE (enum gdb_thread_option, gdb_thread_options); |