From 1edb66d856c82c389edfd7610143236a68c76846 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Thu, 27 May 2021 23:37:03 -0400 Subject: [PATCH] gdb: make thread_info::suspend private, add getters / setters A following patch will want to take some action when a pending wait status is set on or removed from a thread. Add a getter and a setter on thread_info for the pending waitstatus, so that we can add some code in the setter later. The thing is, the pending wait status field is in the thread_suspend_state, along with other fields that we need to backup before and restore after the thread does an inferior function call. Therefore, make the thread_suspend_state member private (thread_info::suspend becomes thread_info::m_suspend), and add getters / setters for all of its fields: - pending wait status - stop signal - stop reason - stop pc For the pending wait status, add the additional has_pending_waitstatus and clear_pending_waitstatus methods. I think this makes the thread_info interface a bit nicer, because we now access the fields as: thread->stop_pc () rather than thread->suspend.stop_pc The stop_pc field being in the `suspend` structure is an implementation detail of thread_info that callers don't need to be aware of. For the backup / restore of the thread_suspend_state structure, add save_suspend_to and restore_suspend_from methods. You might wonder why `save_suspend_to`, as opposed to a simple getter like thread_suspend_state &suspend (); I want to make it clear that this is to be used only for backing up and restoring the suspend state, _not_ to access fields like: thread->suspend ()->stop_pc Adding some getters / setters allows adding some assertions. I find that this helps understand how things are supposed to work. Add: - When getting the pending status (pending_waitstatus method), ensure that there is a pending status. - When setting a pending status (set_pending_waitstatus method), ensure there is no pending status. There is one case I found where this wasn't true - in remote_target::process_initial_stop_replies - which needed adjustments to respect that contract. I think it's because process_initial_stop_replies is kind of (ab)using the thread_info::suspend::waitstatus to store some statuses temporarily, for its internal use (statuses it doesn't intent on leaving pending). process_initial_stop_replies pulls out stop replies received during the initial connection using target_wait. It always stores the received event in `evthread->suspend.waitstatus`. But it only sets waitstatus_pending_p, if it deems the event interesting enough to leave pending, to be reported to the core: if (ws.kind != TARGET_WAITKIND_STOPPED || ws.value.sig != GDB_SIGNAL_0) evthread->suspend.waitstatus_pending_p = 1; It later uses this flag a bit below, to choose which thread to make the "selected" one: if (selected == NULL && thread->suspend.waitstatus_pending_p) selected = thread; And ultimately that's used if the user-visible mode is all-stop, so that we print the stop for that interesting thread: /* In all-stop, we only print the status of one thread, and leave others with their status pending. */ if (!non_stop) { thread_info *thread = selected; if (thread == NULL) thread = lowest_stopped; if (thread == NULL) thread = first; print_one_stopped_thread (thread); } But in any case (all-stop or non-stop), print_one_stopped_thread needs to access the waitstatus value of these threads that don't have a pending waitstatus (those that had TARGET_WAITKIND_STOPPED + GDB_SIGNAL_0). This doesn't work with the assertions I've put. So, change the code to only set the thread's wait status if it is an interesting one that we are going to leave pending. If the thread stopped due to a non-interesting event (TARGET_WAITKIND_STOPPED + GDB_SIGNAL_0), don't store it. Adjust print_one_stopped_thread to understand that if a thread has no pending waitstatus, it's because it stopped with TARGET_WAITKIND_STOPPED + GDB_SIGNAL_0. The call to set_last_target_status also uses the pending waitstatus. However, given that the pending waitstatus for the thread may have been cleared in print_one_stopped_thread (and that there might not even be a pending waitstatus in the first place, as explained above), it is no longer possible to do it at this point. To fix that, move the call to set_last_target_status in print_one_stopped_thread. I think this will preserve the existing behavior, because set_last_target_status is currently using the current thread's wait status. And the current thread is the last one for which print_one_stopped_thread is called. So by calling set_last_target_status in print_one_stopped_thread, we'll get the same result. set_last_target_status will possibly be called multiple times, but only the last call will matter. It just means possibly more calls to set_last_target_status, but those are cheap. Change-Id: Iedab9653238eaf8231abcf0baa20145acc8b77a7 --- gdb/breakpoint.c | 2 +- gdb/elf-none-tdep.c | 2 +- gdb/fbsd-tdep.c | 6 +- gdb/gcore.c | 4 +- gdb/gdbthread.h | 92 +++++++++++- gdb/infcmd.c | 33 ++-- gdb/inflow.c | 2 +- gdb/infrun.c | 315 ++++++++++++++++++--------------------- gdb/linux-fork.c | 3 +- gdb/linux-nat.c | 12 +- gdb/linux-tdep.c | 2 +- gdb/python/py-inferior.c | 2 +- gdb/record-btrace.c | 3 +- gdb/record-full.c | 3 +- gdb/remote.c | 66 ++++---- gdb/thread.c | 25 +++- 16 files changed, 332 insertions(+), 240 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 3288fee3548..7fd23348a8e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -407,7 +407,7 @@ breakpoints_should_be_inserted_now (void) /* Don't remove breakpoints yet if, even though all threads are stopped, we still have events to process. */ for (thread_info *tp : all_non_exited_threads ()) - if (tp->resumed () && tp->suspend.waitstatus_pending_p) + if (tp->resumed () && tp->has_pending_waitstatus ()) return 1; } return 0; diff --git a/gdb/elf-none-tdep.c b/gdb/elf-none-tdep.c index 4cbb664607e..52a6281290f 100644 --- a/gdb/elf-none-tdep.c +++ b/gdb/elf-none-tdep.c @@ -92,7 +92,7 @@ elf_none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, that stopped SIGNALLED_THR. */ gdb_signal stop_signal; if (signalled_thr != nullptr) - stop_signal = signalled_thr->suspend.stop_signal; + stop_signal = signalled_thr->stop_signal (); else stop_signal = GDB_SIGNAL_0; diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c index 5cb6fa31500..eb792c36a54 100644 --- a/gdb/fbsd-tdep.c +++ b/gdb/fbsd-tdep.c @@ -634,7 +634,7 @@ fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf, static int find_signalled_thread (struct thread_info *info, void *data) { - if (info->suspend.stop_signal != GDB_SIGNAL_0 + if (info->stop_signal () != GDB_SIGNAL_0 && info->ptid.pid () == inferior_ptid.pid ()) return 1; @@ -708,7 +708,7 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) In case there's more than one signalled thread, prefer the current thread, if it is signalled. */ curr_thr = inferior_thread (); - if (curr_thr->suspend.stop_signal != GDB_SIGNAL_0) + if (curr_thr->stop_signal () != GDB_SIGNAL_0) signalled_thr = curr_thr; else { @@ -717,7 +717,7 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) signalled_thr = curr_thr; } - enum gdb_signal stop_signal = signalled_thr->suspend.stop_signal; + enum gdb_signal stop_signal = signalled_thr->stop_signal (); gcore_elf_build_thread_register_notes (gdbarch, signalled_thr, stop_signal, obfd, ¬e_data, note_size); for (thread_info *thr : current_inferior ()->non_exited_threads ()) diff --git a/gdb/gcore.c b/gdb/gcore.c index 8e504f3008a..dccb77052ba 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -586,11 +586,11 @@ gcore_find_signalled_thread () { thread_info *curr_thr = inferior_thread (); if (curr_thr->state != THREAD_EXITED - && curr_thr->suspend.stop_signal != GDB_SIGNAL_0) + && curr_thr->stop_signal () != GDB_SIGNAL_0) return curr_thr; for (thread_info *thr : current_inferior ()->non_exited_threads ()) - if (thr->suspend.stop_signal != GDB_SIGNAL_0) + if (thr->stop_signal () != GDB_SIGNAL_0) return thr; /* Default to the current thread, unless it has exited. */ diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index babdd071133..e9d1bbedfb9 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -310,9 +310,91 @@ public: See `struct thread_control_state'. */ thread_control_state control; - /* State of inferior thread to restore after GDB is done with an inferior - call. See `struct thread_suspend_state'. */ - thread_suspend_state suspend; + /* Save M_SUSPEND to SUSPEND. */ + + void save_suspend_to (thread_suspend_state &suspend) const + { + suspend = m_suspend; + } + + /* Restore M_SUSPEND from SUSPEND. */ + + void restore_suspend_from (const thread_suspend_state &suspend) + { + m_suspend = suspend; + } + + /* Return this thread's stop PC. */ + + CORE_ADDR stop_pc () const + { + return m_suspend.stop_pc; + } + + /* Set this thread's stop PC. */ + + void set_stop_pc (CORE_ADDR stop_pc) + { + m_suspend.stop_pc = stop_pc; + } + + /* Return true if this thread has a pending wait status. */ + + bool has_pending_waitstatus () const + { + return m_suspend.waitstatus_pending_p; + } + + /* Get this thread's pending wait status. + + May only be called if has_pending_waitstatus returns true. */ + + const target_waitstatus &pending_waitstatus () const + { + gdb_assert (this->has_pending_waitstatus ()); + + return m_suspend.waitstatus; + } + + /* Set this thread's pending wait status. + + May only be called if has_pending_waitstatus returns false. */ + + void set_pending_waitstatus (const target_waitstatus &ws); + + /* Clear this thread's pending wait status. + + May only be called if has_pending_waitstatus returns true. */ + + void clear_pending_waitstatus (); + + /* Return this thread's stop signal. */ + + gdb_signal stop_signal () const + { + return m_suspend.stop_signal; + } + + /* Set this thread's stop signal. */ + + void set_stop_signal (gdb_signal sig) + { + m_suspend.stop_signal = sig; + } + + /* Return this thread's stop reason. */ + + target_stop_reason stop_reason () const + { + return m_suspend.stop_reason; + } + + /* Set this thread's stop reason. */ + + void set_stop_reason (target_stop_reason reason) + { + m_suspend.stop_reason = reason; + } int current_line = 0; struct symtab *current_symtab = NULL; @@ -400,6 +482,10 @@ private: we should not process that wait status if we didn't try to let the thread run. */ bool m_resumed = false; + + /* State of inferior thread to restore after GDB is done with an inferior + call. See `struct thread_suspend_state'. */ + thread_suspend_state m_suspend; }; /* A gdb::ref_ptr pointer to a thread_info. */ diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 8190ba36565..0a5edef6982 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -298,11 +298,11 @@ post_create_inferior (int from_tty) missing registers info), ignore it. */ thread_info *thr = inferior_thread (); - thr->suspend.stop_pc = 0; + thr->set_stop_pc (0); try { regcache *rc = get_thread_regcache (thr); - thr->suspend.stop_pc = regcache_read_pc (rc); + thr->set_stop_pc (regcache_read_pc (rc)); } catch (const gdb_exception_error &ex) { @@ -534,9 +534,10 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how) if (run_how == RUN_STOP_AT_FIRST_INSN) { thread_info *thr = inferior_thread (); - thr->suspend.waitstatus_pending_p = 1; - thr->suspend.waitstatus.kind = TARGET_WAITKIND_STOPPED; - thr->suspend.waitstatus.value.sig = GDB_SIGNAL_0; + target_waitstatus ws; + ws.kind = TARGET_WAITKIND_STOPPED; + ws.value.sig = GDB_SIGNAL_0; + thr->set_pending_waitstatus (ws); } /* Start the target running. Do not use -1 continuation as it would skip @@ -1223,15 +1224,15 @@ signal_command (const char *signum_exp, int from_tty) if (tp == current) continue; - if (tp->suspend.stop_signal != GDB_SIGNAL_0 - && signal_pass_state (tp->suspend.stop_signal)) + if (tp->stop_signal () != GDB_SIGNAL_0 + && signal_pass_state (tp->stop_signal ())) { if (!must_confirm) printf_unfiltered (_("Note:\n")); printf_unfiltered (_(" Thread %s previously stopped with signal %s, %s.\n"), print_thread_id (tp), - gdb_signal_to_name (tp->suspend.stop_signal), - gdb_signal_to_string (tp->suspend.stop_signal)); + gdb_signal_to_name (tp->stop_signal ()), + gdb_signal_to_string (tp->stop_signal ())); must_confirm = 1; } } @@ -1294,7 +1295,7 @@ queue_signal_command (const char *signum_exp, int from_tty) error (_("Signal handling set to not pass this signal to the program.")); tp = inferior_thread (); - tp->suspend.stop_signal = oursig; + tp->set_stop_signal (oursig); } /* Data for the FSM that manages the until (with no argument) @@ -1914,7 +1915,7 @@ info_program_command (const char *args, int from_tty) target_files_info (); printf_filtered (_("Program stopped at %s.\n"), - paddress (target_gdbarch (), tp->suspend.stop_pc)); + paddress (target_gdbarch (), tp->stop_pc ())); if (tp->control.stop_step) printf_filtered (_("It stopped after being stepped.\n")); else if (stat != 0) @@ -1933,11 +1934,11 @@ info_program_command (const char *args, int from_tty) stat = bpstat_num (&bs, &num); } } - else if (tp->suspend.stop_signal != GDB_SIGNAL_0) + else if (tp->stop_signal () != GDB_SIGNAL_0) { printf_filtered (_("It stopped with signal %s, %s.\n"), - gdb_signal_to_name (tp->suspend.stop_signal), - gdb_signal_to_string (tp->suspend.stop_signal)); + gdb_signal_to_name (tp->stop_signal ()), + gdb_signal_to_string (tp->stop_signal ())); } if (from_tty) @@ -2425,7 +2426,7 @@ proceed_after_attach (inferior *inf) for (thread_info *thread : inf->non_exited_threads ()) if (!thread->executing && !thread->stop_requested - && thread->suspend.stop_signal == GDB_SIGNAL_0) + && thread->stop_signal () == GDB_SIGNAL_0) { switch_to_thread (thread); clear_proceed_status (0); @@ -2500,7 +2501,7 @@ attach_post_wait (int from_tty, enum attach_post_wait_mode mode) proceed_after_attach (inferior); else { - if (inferior_thread ()->suspend.stop_signal == GDB_SIGNAL_0) + if (inferior_thread ()->stop_signal () == GDB_SIGNAL_0) { clear_proceed_status (0); proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); diff --git a/gdb/inflow.c b/gdb/inflow.c index f9917d6a81c..97045063215 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -530,7 +530,7 @@ child_interrupt (struct target_ops *self) resumed = thr; break; } - if (thr->suspend.waitstatus_pending_p) + if (thr->has_pending_waitstatus ()) resumed = thr; } diff --git a/gdb/infrun.c b/gdb/infrun.c index 0da3bc27942..6c652ea3677 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -899,7 +899,7 @@ proceed_after_vfork_done (struct thread_info *thread, && thread->state == THREAD_RUNNING && !thread->executing && !thread->stop_requested - && thread->suspend.stop_signal == GDB_SIGNAL_0) + && thread->stop_signal () == GDB_SIGNAL_0) { infrun_debug_printf ("resuming vfork parent thread %s", target_pid_to_str (thread->ptid).c_str ()); @@ -2151,7 +2151,7 @@ do_target_resume (ptid_t resume_ptid, bool step, enum gdb_signal sig) /* Avoid confusing the next resume, if the next stop/resume happens to apply to another thread. */ - tp->suspend.stop_signal = GDB_SIGNAL_0; + tp->set_stop_signal (GDB_SIGNAL_0); /* Advise target which signals may be handled silently. @@ -2209,13 +2209,13 @@ resume_1 (enum gdb_signal sig) gdb_assert (!tp->stop_requested); gdb_assert (!thread_is_in_step_over_chain (tp)); - if (tp->suspend.waitstatus_pending_p) + if (tp->has_pending_waitstatus ()) { infrun_debug_printf ("thread %s has pending wait " "status %s (currently_stepping=%d).", target_pid_to_str (tp->ptid).c_str (), - target_waitstatus_to_string (&tp->suspend.waitstatus).c_str (), + target_waitstatus_to_string (&tp->pending_waitstatus ()).c_str (), currently_stepping (tp)); tp->inf->process_target ()->threads_executing = true; @@ -2231,7 +2231,7 @@ resume_1 (enum gdb_signal sig) target_pid_to_str (tp->ptid).c_str ()); } - tp->suspend.stop_signal = GDB_SIGNAL_0; + tp->set_stop_signal (GDB_SIGNAL_0); if (target_can_async_p ()) { @@ -2617,31 +2617,31 @@ clear_proceed_status_thread (struct thread_info *tp) /* If we're starting a new sequence, then the previous finished single-step is no longer relevant. */ - if (tp->suspend.waitstatus_pending_p) + if (tp->has_pending_waitstatus ()) { - if (tp->suspend.stop_reason == TARGET_STOPPED_BY_SINGLE_STEP) + if (tp->stop_reason () == TARGET_STOPPED_BY_SINGLE_STEP) { infrun_debug_printf ("pending event of %s was a finished step. " "Discarding.", target_pid_to_str (tp->ptid).c_str ()); - tp->suspend.waitstatus_pending_p = 0; - tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON; + tp->clear_pending_waitstatus (); + tp->set_stop_reason (TARGET_STOPPED_BY_NO_REASON); } else { infrun_debug_printf ("thread %s has pending wait status %s (currently_stepping=%d).", target_pid_to_str (tp->ptid).c_str (), - target_waitstatus_to_string (&tp->suspend.waitstatus).c_str (), + target_waitstatus_to_string (&tp->pending_waitstatus ()).c_str (), currently_stepping (tp)); } } /* If this signal should not be seen by program, give it zero. Used for debugging signals. */ - if (!signal_pass_state (tp->suspend.stop_signal)) - tp->suspend.stop_signal = GDB_SIGNAL_0; + if (!signal_pass_state (tp->stop_signal ())) + tp->set_stop_signal (GDB_SIGNAL_0); delete tp->thread_fsm; tp->thread_fsm = NULL; @@ -2802,7 +2802,7 @@ maybe_set_commit_resumed_all_targets () resuming more threads. */ bool has_thread_with_pending_status = false; for (thread_info *thread : all_non_exited_threads (proc_target)) - if (thread->resumed () && thread->suspend.waitstatus_pending_p) + if (thread->resumed () && thread->has_pending_waitstatus ()) { has_thread_with_pending_status = true; break; @@ -3095,7 +3095,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) if (addr == (CORE_ADDR) -1) { - if (pc == cur_thr->suspend.stop_pc + if (pc == cur_thr->stop_pc () && breakpoint_here_p (aspace, pc) == ordinary_breakpoint_here && execution_direction != EXEC_REVERSE) /* There is a breakpoint at the address we will resume at, @@ -3120,7 +3120,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) } if (siggnal != GDB_SIGNAL_DEFAULT) - cur_thr->suspend.stop_signal = siggnal; + cur_thr->set_stop_signal (siggnal); /* If an exception is thrown from this point on, make sure to propagate GDB's knowledge of the executing state to the @@ -3241,7 +3241,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) { infrun_debug_printf ("[%s] resumed", target_pid_to_str (tp->ptid).c_str ()); - gdb_assert (tp->executing || tp->suspend.waitstatus_pending_p); + gdb_assert (tp->executing || tp->has_pending_waitstatus ()); continue; } @@ -3386,11 +3386,12 @@ infrun_thread_stop_requested (ptid_t ptid) know about that yet, queue a pending event, as if the thread had just stopped now. Unless the thread already had a pending event. */ - if (!tp->suspend.waitstatus_pending_p) + if (!tp->has_pending_waitstatus ()) { - tp->suspend.waitstatus_pending_p = 1; - tp->suspend.waitstatus.kind = TARGET_WAITKIND_STOPPED; - tp->suspend.waitstatus.value.sig = GDB_SIGNAL_0; + target_waitstatus ws; + ws.kind = TARGET_WAITKIND_STOPPED; + ws.value.sig = GDB_SIGNAL_0; + tp->set_pending_waitstatus (ws); } /* Clear the inline-frame state, since we're re-processing the @@ -3505,7 +3506,7 @@ random_pending_event_thread (inferior *inf, ptid_t waiton_ptid) { return (tp->ptid.matches (waiton_ptid) && tp->resumed () - && tp->suspend.waitstatus_pending_p); + && tp->has_pending_waitstatus ()); }; /* First see how many events we have. Count only resumed threads @@ -3566,13 +3567,13 @@ do_target_wait_1 (inferior *inf, ptid_t ptid, /* We have a specific thread to check. */ tp = find_thread_ptid (inf, ptid); gdb_assert (tp != NULL); - if (!tp->suspend.waitstatus_pending_p) + if (!tp->has_pending_waitstatus ()) tp = NULL; } if (tp != NULL - && (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT - || tp->suspend.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)) + && (tp->stop_reason () == TARGET_STOPPED_BY_SW_BREAKPOINT + || tp->stop_reason () == TARGET_STOPPED_BY_HW_BREAKPOINT)) { struct regcache *regcache = get_thread_regcache (tp); struct gdbarch *gdbarch = regcache->arch (); @@ -3581,11 +3582,11 @@ do_target_wait_1 (inferior *inf, ptid_t ptid, pc = regcache_read_pc (regcache); - if (pc != tp->suspend.stop_pc) + if (pc != tp->stop_pc ()) { infrun_debug_printf ("PC of %s changed. was=%s, now=%s", target_pid_to_str (tp->ptid).c_str (), - paddress (gdbarch, tp->suspend.stop_pc), + paddress (gdbarch, tp->stop_pc ()), paddress (gdbarch, pc)); discard = 1; } @@ -3603,8 +3604,11 @@ do_target_wait_1 (inferior *inf, ptid_t ptid, infrun_debug_printf ("pending event of %s cancelled.", target_pid_to_str (tp->ptid).c_str ()); - tp->suspend.waitstatus.kind = TARGET_WAITKIND_SPURIOUS; - tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON; + tp->clear_pending_waitstatus (); + target_waitstatus ws; + ws.kind = TARGET_WAITKIND_SPURIOUS; + tp->set_pending_waitstatus (ws); + tp->set_stop_reason (TARGET_STOPPED_BY_NO_REASON); } } @@ -3612,13 +3616,13 @@ do_target_wait_1 (inferior *inf, ptid_t ptid, { infrun_debug_printf ("Using pending wait status %s for %s.", target_waitstatus_to_string - (&tp->suspend.waitstatus).c_str (), + (&tp->pending_waitstatus ()).c_str (), target_pid_to_str (tp->ptid).c_str ()); /* Now that we've selected our final event LWP, un-adjust its PC if it was a software breakpoint (and the target doesn't always adjust the PC itself). */ - if (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT + if (tp->stop_reason () == TARGET_STOPPED_BY_SW_BREAKPOINT && !target_supports_stopped_by_sw_breakpoint ()) { struct regcache *regcache; @@ -3638,9 +3642,9 @@ do_target_wait_1 (inferior *inf, ptid_t ptid, } } - tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON; - *status = tp->suspend.waitstatus; - tp->suspend.waitstatus_pending_p = 0; + tp->set_stop_reason (TARGET_STOPPED_BY_NO_REASON); + *status = tp->pending_waitstatus (); + tp->clear_pending_waitstatus (); /* Wake up the event loop again, until all pending events are processed. */ @@ -4289,7 +4293,7 @@ context_switch (execution_control_state *ecs) static void adjust_pc_after_break (struct thread_info *thread, - struct target_waitstatus *ws) + const target_waitstatus *ws) { struct regcache *regcache; struct gdbarch *gdbarch; @@ -4517,7 +4521,7 @@ handle_syscall_event (struct execution_control_state *ecs) regcache = get_thread_regcache (ecs->event_thread); syscall_number = ecs->ws.value.syscall_number; - ecs->event_thread->suspend.stop_pc = regcache_read_pc (regcache); + ecs->event_thread->set_stop_pc (regcache_read_pc (regcache)); if (catch_syscall_enabled () > 0 && catching_syscall_number (syscall_number) > 0) @@ -4526,7 +4530,7 @@ handle_syscall_event (struct execution_control_state *ecs) ecs->event_thread->control.stop_bpstat = bpstat_stop_status (regcache->aspace (), - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), ecs->event_thread, &ecs->ws); if (handle_stop_requested (ecs)) @@ -4561,7 +4565,7 @@ fill_in_stop_func (struct gdbarch *gdbarch, /* Don't care about return value; stop_func_start and stop_func_name will both be 0 if it doesn't work. */ - find_pc_partial_function_sym (ecs->event_thread->suspend.stop_pc, + find_pc_partial_function_sym (ecs->event_thread->stop_pc (), &gsi, &ecs->stop_func_start, &ecs->stop_func_end, @@ -4714,8 +4718,7 @@ save_waitstatus (struct thread_info *tp, const target_waitstatus *ws) tp->ptid.tid ()); /* Record for later. */ - tp->suspend.waitstatus = *ws; - tp->suspend.waitstatus_pending_p = 1; + tp->set_pending_waitstatus (*ws); if (ws->kind == TARGET_WAITKIND_STOPPED && ws->value.sig == GDB_SIGNAL_TRAP) @@ -4724,48 +4727,28 @@ save_waitstatus (struct thread_info *tp, const target_waitstatus *ws) const address_space *aspace = regcache->aspace (); CORE_ADDR pc = regcache_read_pc (regcache); - adjust_pc_after_break (tp, &tp->suspend.waitstatus); + adjust_pc_after_break (tp, &tp->pending_waitstatus ()); scoped_restore_current_thread restore_thread; switch_to_thread (tp); if (target_stopped_by_watchpoint ()) - { - tp->suspend.stop_reason - = TARGET_STOPPED_BY_WATCHPOINT; - } + tp->set_stop_reason (TARGET_STOPPED_BY_WATCHPOINT); else if (target_supports_stopped_by_sw_breakpoint () && target_stopped_by_sw_breakpoint ()) - { - tp->suspend.stop_reason - = TARGET_STOPPED_BY_SW_BREAKPOINT; - } + tp->set_stop_reason (TARGET_STOPPED_BY_SW_BREAKPOINT); else if (target_supports_stopped_by_hw_breakpoint () && target_stopped_by_hw_breakpoint ()) - { - tp->suspend.stop_reason - = TARGET_STOPPED_BY_HW_BREAKPOINT; - } + tp->set_stop_reason (TARGET_STOPPED_BY_HW_BREAKPOINT); else if (!target_supports_stopped_by_hw_breakpoint () - && hardware_breakpoint_inserted_here_p (aspace, - pc)) - { - tp->suspend.stop_reason - = TARGET_STOPPED_BY_HW_BREAKPOINT; - } + && hardware_breakpoint_inserted_here_p (aspace, pc)) + tp->set_stop_reason (TARGET_STOPPED_BY_HW_BREAKPOINT); else if (!target_supports_stopped_by_sw_breakpoint () - && software_breakpoint_inserted_here_p (aspace, - pc)) - { - tp->suspend.stop_reason - = TARGET_STOPPED_BY_SW_BREAKPOINT; - } + && software_breakpoint_inserted_here_p (aspace, pc)) + tp->set_stop_reason (TARGET_STOPPED_BY_SW_BREAKPOINT); else if (!thread_has_single_step_breakpoints_set (tp) && currently_stepping (tp)) - { - tp->suspend.stop_reason - = TARGET_STOPPED_BY_SINGLE_STEP; - } + tp->set_stop_reason (TARGET_STOPPED_BY_SINGLE_STEP); } } @@ -4906,9 +4889,7 @@ handle_one (const wait_one_event &event) && event.ws.value.sig == GDB_SIGNAL_0) { /* We caught the event that we intended to catch, so - there's no event pending. */ - t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE; - t->suspend.waitstatus_pending_p = 0; + there's no event to save as pending. */ if (displaced_step_finish (t, GDB_SIGNAL_0) == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED) @@ -4949,12 +4930,11 @@ handle_one (const wait_one_event &event) } regcache = get_thread_regcache (t); - t->suspend.stop_pc = regcache_read_pc (regcache); + t->set_stop_pc (regcache_read_pc (regcache)); infrun_debug_printf ("saved stop_pc=%s for %s " "(currently_stepping=%d)", - paddress (target_gdbarch (), - t->suspend.stop_pc), + paddress (target_gdbarch (), t->stop_pc ()), target_pid_to_str (t->ptid).c_str (), currently_stepping (t)); } @@ -5190,8 +5170,7 @@ handle_no_resumed (struct execution_control_state *ecs) } if (!ignore_event - && (thread->executing - || thread->suspend.waitstatus_pending_p)) + && (thread->executing || thread->has_pending_waitstatus ())) { /* Either there were no unwaited-for children left in the target at some point, but there are now, or some target @@ -5352,7 +5331,7 @@ handle_inferior_event (struct execution_control_state *ecs) ecs->event_thread->control.stop_bpstat = bpstat_stop_status (regcache->aspace (), - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), ecs->event_thread, &ecs->ws); if (handle_stop_requested (ecs)) @@ -5369,7 +5348,7 @@ handle_inferior_event (struct execution_control_state *ecs) gdb of events. This allows the user to get control and place breakpoints in initializer routines for dynamically loaded objects (among other things). */ - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); if (stop_on_solib_events) { /* Make sure we print "Stopped due to solib-event" in @@ -5590,12 +5569,12 @@ handle_inferior_event (struct execution_control_state *ecs) and not immediately. */ ecs->event_thread->pending_follow = ecs->ws; - ecs->event_thread->suspend.stop_pc - = regcache_read_pc (get_thread_regcache (ecs->event_thread)); + ecs->event_thread->set_stop_pc + (regcache_read_pc (get_thread_regcache (ecs->event_thread))); ecs->event_thread->control.stop_bpstat = bpstat_stop_status (get_current_regcache ()->aspace (), - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), ecs->event_thread, &ecs->ws); if (handle_stop_requested (ecs)) @@ -5610,7 +5589,7 @@ handle_inferior_event (struct execution_control_state *ecs) bool follow_child = (follow_fork_mode_string == follow_fork_mode_child); - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); process_stratum_target *targ = ecs->event_thread->inf->process_target (); @@ -5702,12 +5681,12 @@ handle_inferior_event (struct execution_control_state *ecs) execd thread for that case (this is a nop otherwise). */ ecs->event_thread = inferior_thread (); - ecs->event_thread->suspend.stop_pc - = regcache_read_pc (get_thread_regcache (ecs->event_thread)); + ecs->event_thread->set_stop_pc + (regcache_read_pc (get_thread_regcache (ecs->event_thread))); ecs->event_thread->control.stop_bpstat = bpstat_stop_status (get_current_regcache ()->aspace (), - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), ecs->event_thread, &ecs->ws); /* Note that this may be referenced from inside @@ -5721,7 +5700,7 @@ handle_inferior_event (struct execution_control_state *ecs) /* If no catchpoint triggered for this, then keep going. */ if (!bpstat_causes_stop (ecs->event_thread->control.stop_bpstat)) { - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); keep_going (ecs); return; } @@ -5758,8 +5737,8 @@ handle_inferior_event (struct execution_control_state *ecs) infrun_debug_printf ("stopped"); delete_just_stopped_threads_single_step_breakpoints (); - ecs->event_thread->suspend.stop_pc - = regcache_read_pc (get_thread_regcache (inferior_thread ())); + ecs->event_thread->set_stop_pc + (regcache_read_pc (get_thread_regcache (inferior_thread ()))); if (handle_stop_requested (ecs)) return; @@ -5809,7 +5788,7 @@ restart_threads (struct thread_info *event_thread) { infrun_debug_printf ("restart threads: [%s] resumed", target_pid_to_str (tp->ptid).c_str ()); - gdb_assert (tp->executing || tp->suspend.waitstatus_pending_p); + gdb_assert (tp->executing || tp->has_pending_waitstatus ()); continue; } @@ -5822,7 +5801,7 @@ restart_threads (struct thread_info *event_thread) } - if (tp->suspend.waitstatus_pending_p) + if (tp->has_pending_waitstatus ()) { infrun_debug_printf ("restart threads: [%s] has pending status", target_pid_to_str (tp->ptid).c_str ()); @@ -5870,8 +5849,7 @@ static int resumed_thread_with_pending_status (struct thread_info *tp, void *arg) { - return (tp->resumed () - && tp->suspend.waitstatus_pending_p); + return tp->resumed () && tp->has_pending_waitstatus (); } /* Called when we get an event that may finish an in-line or @@ -5883,8 +5861,7 @@ resumed_thread_with_pending_status (struct thread_info *tp, static int finish_step_over (struct execution_control_state *ecs) { - displaced_step_finish (ecs->event_thread, - ecs->event_thread->suspend.stop_signal); + displaced_step_finish (ecs->event_thread, ecs->event_thread->stop_signal ()); bool had_step_over_info = step_over_info_valid_p (); @@ -5961,12 +5938,11 @@ finish_step_over (struct execution_control_state *ecs) gdb_assert (!tp->executing); regcache = get_thread_regcache (tp); - tp->suspend.stop_pc = regcache_read_pc (regcache); + tp->set_stop_pc (regcache_read_pc (regcache)); infrun_debug_printf ("saved stop_pc=%s for %s " "(currently_stepping=%d)", - paddress (target_gdbarch (), - tp->suspend.stop_pc), + paddress (target_gdbarch (), tp->stop_pc ()), target_pid_to_str (tp->ptid).c_str (), currently_stepping (tp)); @@ -5999,7 +5975,7 @@ handle_signal_stop (struct execution_control_state *ecs) gdb_assert (ecs->ws.kind == TARGET_WAITKIND_STOPPED); - ecs->event_thread->suspend.stop_signal = ecs->ws.value.sig; + ecs->event_thread->set_stop_signal (ecs->ws.value.sig); /* Do we need to clean up the state of a thread that has completed a displaced single-step? (Doing so usually affects @@ -6011,11 +5987,11 @@ handle_signal_stop (struct execution_control_state *ecs) the user wanted this thread to be stopped, pretend we got a SIG0 (generic unsignaled stop). */ if (ecs->event_thread->stop_requested - && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + && ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP) + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); - ecs->event_thread->suspend.stop_pc - = regcache_read_pc (get_thread_regcache (ecs->event_thread)); + ecs->event_thread->set_stop_pc + (regcache_read_pc (get_thread_regcache (ecs->event_thread))); context_switch (ecs); @@ -6027,9 +6003,8 @@ handle_signal_stop (struct execution_control_state *ecs) struct regcache *regcache = get_thread_regcache (ecs->event_thread); struct gdbarch *reg_gdbarch = regcache->arch (); - infrun_debug_printf ("stop_pc=%s", - paddress (reg_gdbarch, - ecs->event_thread->suspend.stop_pc)); + infrun_debug_printf + ("stop_pc=%s", paddress (reg_gdbarch, ecs->event_thread->stop_pc ())); if (target_stopped_by_watchpoint ()) { CORE_ADDR addr; @@ -6077,13 +6052,13 @@ handle_signal_stop (struct execution_control_state *ecs) GDB_SIGNAL_0, meaning: stopped for no particular reason other than GDB's request. */ if (stop_soon == STOP_QUIETLY_NO_SIGSTOP - && (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_STOP - || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP - || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0)) + && (ecs->event_thread->stop_signal () == GDB_SIGNAL_STOP + || ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP + || ecs->event_thread->stop_signal () == GDB_SIGNAL_0)) { stop_print_frame = true; stop_waiting (ecs); - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); return; } @@ -6092,7 +6067,7 @@ handle_signal_stop (struct execution_control_state *ecs) gdbarch = get_frame_arch (frame); /* Pull the single step breakpoints out of the target. */ - if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) + if (ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP) { struct regcache *regcache; CORE_ADDR pc; @@ -6124,7 +6099,7 @@ handle_signal_stop (struct execution_control_state *ecs) } delete_just_stopped_threads_single_step_breakpoints (); - if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP + if (ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP && ecs->event_thread->control.trap_expected && ecs->event_thread->stepping_over_watchpoint) stopped_by_watchpoint = 0; @@ -6201,16 +6176,16 @@ handle_signal_stop (struct execution_control_state *ecs) skip_inline_frames call would break things. Fortunately that's an extremely unlikely scenario. */ if (!pc_at_non_inline_function (aspace, - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), &ecs->ws) - && !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP + && !(ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP && ecs->event_thread->control.trap_expected && pc_at_non_inline_function (aspace, ecs->event_thread->prev_pc, &ecs->ws))) { stop_chain = build_bpstat_chain (aspace, - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), &ecs->ws); skip_inline_frames (ecs->event_thread, stop_chain); @@ -6221,7 +6196,7 @@ handle_signal_stop (struct execution_control_state *ecs) } } - if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP + if (ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP && ecs->event_thread->control.trap_expected && gdbarch_single_step_through_delay_p (gdbarch) && currently_stepping (ecs->event_thread)) @@ -6262,7 +6237,7 @@ handle_signal_stop (struct execution_control_state *ecs) handles this event. */ ecs->event_thread->control.stop_bpstat = bpstat_stop_status (get_current_regcache ()->aspace (), - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), ecs->event_thread, &ecs->ws, stop_chain); /* Following in case break condition called a @@ -6277,7 +6252,7 @@ handle_signal_stop (struct execution_control_state *ecs) simply make sure to ignore it if `stopped_by_watchpoint' is set. */ - if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP + if (ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP && !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat, GDB_SIGNAL_TRAP) && stopped_by_watchpoint) @@ -6309,14 +6284,14 @@ handle_signal_stop (struct execution_control_state *ecs) /* See if the breakpoints module can explain the signal. */ random_signal = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat, - ecs->event_thread->suspend.stop_signal); + ecs->event_thread->stop_signal ()); /* Maybe this was a trap for a software breakpoint that has since been removed. */ if (random_signal && target_stopped_by_sw_breakpoint ()) { if (gdbarch_program_breakpoint_here_p (gdbarch, - ecs->event_thread->suspend.stop_pc)) + ecs->event_thread->stop_pc ())) { struct regcache *regcache; int decr_pc; @@ -6335,7 +6310,7 @@ handle_signal_stop (struct execution_control_state *ecs) (record_full_gdb_operation_disable_set ()); regcache_write_pc (regcache, - ecs->event_thread->suspend.stop_pc + decr_pc); + ecs->event_thread->stop_pc () + decr_pc); } } else @@ -6358,7 +6333,7 @@ handle_signal_stop (struct execution_control_state *ecs) /* If not, perhaps stepping/nexting can. */ if (random_signal) - random_signal = !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP + random_signal = !(ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP && currently_stepping (ecs->event_thread)); /* Perhaps the thread hit a single-step breakpoint of _another_ @@ -6385,7 +6360,7 @@ handle_signal_stop (struct execution_control_state *ecs) if (random_signal) { /* Signal not for debugging purposes. */ - enum gdb_signal stop_signal = ecs->event_thread->suspend.stop_signal; + enum gdb_signal stop_signal = ecs->event_thread->stop_signal (); infrun_debug_printf ("random signal (%s)", gdb_signal_to_symbol_string (stop_signal)); @@ -6397,7 +6372,7 @@ handle_signal_stop (struct execution_control_state *ecs) to remain stopped. */ if (stop_soon != NO_STOP_QUIETLY || ecs->event_thread->stop_requested - || signal_stop_state (ecs->event_thread->suspend.stop_signal)) + || signal_stop_state (ecs->event_thread->stop_signal ())) { stop_waiting (ecs); return; @@ -6406,19 +6381,19 @@ handle_signal_stop (struct execution_control_state *ecs) /* Notify observers the signal has "handle print" set. Note we returned early above if stopping; normal_stop handles the printing in that case. */ - if (signal_print[ecs->event_thread->suspend.stop_signal]) + if (signal_print[ecs->event_thread->stop_signal ()]) { /* The signal table tells us to print about this signal. */ target_terminal::ours_for_output (); - gdb::observers::signal_received.notify (ecs->event_thread->suspend.stop_signal); + gdb::observers::signal_received.notify (ecs->event_thread->stop_signal ()); target_terminal::inferior (); } /* Clear the signal if it should not be passed. */ - if (signal_program[ecs->event_thread->suspend.stop_signal] == 0) - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + if (signal_program[ecs->event_thread->stop_signal ()] == 0) + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); - if (ecs->event_thread->prev_pc == ecs->event_thread->suspend.stop_pc + if (ecs->event_thread->prev_pc == ecs->event_thread->stop_pc () && ecs->event_thread->control.trap_expected && ecs->event_thread->control.step_resume_breakpoint == NULL) { @@ -6446,8 +6421,8 @@ handle_signal_stop (struct execution_control_state *ecs) return; } - if (ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0 - && (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc, + if (ecs->event_thread->stop_signal () != GDB_SIGNAL_0 + && (pc_in_thread_step_range (ecs->event_thread->stop_pc (), ecs->event_thread) || ecs->event_thread->control.step_range_end == 1) && frame_id_eq (get_stack_frame_id (frame), @@ -6665,7 +6640,7 @@ process_event_stop_test (struct execution_control_state *ecs) return; } fill_in_stop_func (gdbarch, ecs); - if (ecs->event_thread->suspend.stop_pc == ecs->stop_func_start + if (ecs->event_thread->stop_pc () == ecs->stop_func_start && execution_direction == EXEC_REVERSE) { /* We are stepping over a function call in reverse, and just @@ -6789,7 +6764,7 @@ process_event_stop_test (struct execution_control_state *ecs) through a function epilogue and therefore must detect when the current-frame changes in the middle of a line. */ - if (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc, + if (pc_in_thread_step_range (ecs->event_thread->stop_pc (), ecs->event_thread) && (execution_direction != EXEC_REVERSE || frame_id_eq (get_frame_id (frame), @@ -6808,7 +6783,7 @@ process_event_stop_test (struct execution_control_state *ecs) /* When stepping backward, stop at beginning of line range (unless it's the function entry point, in which case keep going back to the call point). */ - CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc; + CORE_ADDR stop_pc = ecs->event_thread->stop_pc (); if (stop_pc == ecs->event_thread->control.step_range_start && stop_pc != ecs->stop_func_start && execution_direction == EXEC_REVERSE) @@ -6835,11 +6810,10 @@ process_event_stop_test (struct execution_control_state *ecs) if (execution_direction != EXEC_REVERSE && ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE - && in_solib_dynsym_resolve_code (ecs->event_thread->suspend.stop_pc)) + && in_solib_dynsym_resolve_code (ecs->event_thread->stop_pc ())) { CORE_ADDR pc_after_resolver = - gdbarch_skip_solib_resolver (gdbarch, - ecs->event_thread->suspend.stop_pc); + gdbarch_skip_solib_resolver (gdbarch, ecs->event_thread->stop_pc ()); infrun_debug_printf ("stepped into dynsym resolve code"); @@ -6862,7 +6836,7 @@ process_event_stop_test (struct execution_control_state *ecs) /* Step through an indirect branch thunk. */ if (ecs->event_thread->control.step_over_calls != STEP_OVER_NONE && gdbarch_in_indirect_branch_thunk (gdbarch, - ecs->event_thread->suspend.stop_pc)) + ecs->event_thread->stop_pc ())) { infrun_debug_printf ("stepped into indirect branch thunk"); keep_going (ecs); @@ -6890,12 +6864,12 @@ process_event_stop_test (struct execution_control_state *ecs) call check below as on some targets return trampolines look like subroutine calls (MIPS16 return thunks). */ if (gdbarch_in_solib_return_trampoline (gdbarch, - ecs->event_thread->suspend.stop_pc, + ecs->event_thread->stop_pc (), ecs->stop_func_name) && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE) { /* Determine where this trampoline returns. */ - CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc; + CORE_ADDR stop_pc = ecs->event_thread->stop_pc (); CORE_ADDR real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc); @@ -6947,9 +6921,9 @@ process_event_stop_test (struct execution_control_state *ecs) && (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id, outer_frame_id) || (ecs->event_thread->control.step_start_function - != find_pc_function (ecs->event_thread->suspend.stop_pc))))) + != find_pc_function (ecs->event_thread->stop_pc ()))))) { - CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc; + CORE_ADDR stop_pc = ecs->event_thread->stop_pc (); CORE_ADDR real_stop_pc; infrun_debug_printf ("stepped into subroutine"); @@ -7107,7 +7081,7 @@ process_event_stop_test (struct execution_control_state *ecs) if (execution_direction == EXEC_REVERSE && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE) { - CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc; + CORE_ADDR stop_pc = ecs->event_thread->stop_pc (); if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc) || (ecs->stop_func_start == 0 @@ -7140,7 +7114,7 @@ process_event_stop_test (struct execution_control_state *ecs) stack of inlined frames, even if GDB actually believes that it is in a more outer frame. This is checked for below by calls to inline_skipped_frames. */ - stop_pc_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0); + stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0); /* NOTE: tausq/2004-05-24: This if block used to be done before all the trampoline processing logic, however, there are some trampolines @@ -7267,7 +7241,7 @@ process_event_stop_test (struct execution_control_state *ecs) } bool refresh_step_info = true; - if ((ecs->event_thread->suspend.stop_pc == stop_pc_sal.pc) + if ((ecs->event_thread->stop_pc () == stop_pc_sal.pc) && (ecs->event_thread->current_line != stop_pc_sal.line || ecs->event_thread->current_symtab != stop_pc_sal.symtab)) { @@ -7362,7 +7336,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs) /* Check if the current thread is blocked on an incomplete step-over, interrupted by a random signal. */ if (ecs->event_thread->control.trap_expected - && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_TRAP) + && ecs->event_thread->stop_signal () != GDB_SIGNAL_TRAP) { infrun_debug_printf ("need to finish step-over of [%s]", @@ -7407,8 +7381,8 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs) ecs->event_thread->control.trap_expected = 0; /* Likewise, clear the signal if it should not be passed. */ - if (!signal_program[ecs->event_thread->suspend.stop_signal]) - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + if (!signal_program[ecs->event_thread->stop_signal ()]) + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); if (restart_stepped_thread (ecs->target, ecs->ptid)) { @@ -7441,7 +7415,7 @@ restart_stepped_thread (process_stratum_target *resume_target, if (tp->state == THREAD_EXITED) continue; - if (tp->suspend.waitstatus_pending_p) + if (tp->has_pending_waitstatus ()) continue; /* Ignore threads of processes the caller is not @@ -7465,7 +7439,7 @@ restart_stepped_thread (process_stratum_target *resume_target, if (tp->state == THREAD_EXITED) continue; - if (tp->suspend.waitstatus_pending_p) + if (tp->has_pending_waitstatus ()) continue; /* Ignore threads of processes the caller is not @@ -7516,7 +7490,7 @@ restart_after_all_stop_detach (process_stratum_target *proc_target) /* If we have a pending event to process, skip resuming the target and go straight to processing it. */ - if (thr->resumed () && thr->suspend.waitstatus_pending_p) + if (thr->resumed () && thr->has_pending_waitstatus ()) return; } @@ -7583,7 +7557,7 @@ keep_going_stepped_thread (struct thread_info *tp) reset_ecs (ecs, tp); switch_to_thread (tp); - tp->suspend.stop_pc = regcache_read_pc (get_thread_regcache (tp)); + tp->set_stop_pc (regcache_read_pc (get_thread_regcache (tp))); frame = get_current_frame (); /* If the PC of the thread we were trying to single-step has @@ -7599,13 +7573,13 @@ keep_going_stepped_thread (struct thread_info *tp) This prevents us continuously moving the single-step breakpoint forward, one instruction at a time, overstepping. */ - if (tp->suspend.stop_pc != tp->prev_pc) + if (tp->stop_pc () != tp->prev_pc) { ptid_t resume_ptid; infrun_debug_printf ("expected thread advanced also (%s -> %s)", paddress (target_gdbarch (), tp->prev_pc), - paddress (target_gdbarch (), tp->suspend.stop_pc)); + paddress (target_gdbarch (), tp->stop_pc ())); /* Clear the info of the previous step-over, as it's no longer valid (if the thread was trying to step over a breakpoint, it @@ -7619,7 +7593,7 @@ keep_going_stepped_thread (struct thread_info *tp) insert_single_step_breakpoint (get_frame_arch (frame), get_frame_address_space (frame), - tp->suspend.stop_pc); + tp->stop_pc ()); tp->set_resumed (true); resume_ptid = internal_resume_ptid (tp->control.stepping_command); @@ -7660,7 +7634,7 @@ handle_step_into_function (struct gdbarch *gdbarch, fill_in_stop_func (gdbarch, ecs); compunit_symtab *cust - = find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc); + = find_pc_compunit_symtab (ecs->event_thread->stop_pc ()); if (cust != NULL && compunit_language (cust) != language_asm) ecs->stop_func_start = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start); @@ -7700,7 +7674,7 @@ handle_step_into_function (struct gdbarch *gdbarch, ecs->stop_func_start); } - if (ecs->stop_func_start == ecs->event_thread->suspend.stop_pc) + if (ecs->stop_func_start == ecs->event_thread->stop_pc ()) { /* We are already there: stop now. */ end_stepping_range (ecs); @@ -7739,15 +7713,15 @@ handle_step_into_function_backward (struct gdbarch *gdbarch, fill_in_stop_func (gdbarch, ecs); - cust = find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc); + cust = find_pc_compunit_symtab (ecs->event_thread->stop_pc ()); if (cust != NULL && compunit_language (cust) != language_asm) ecs->stop_func_start = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start); - stop_func_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0); + stop_func_sal = find_pc_line (ecs->event_thread->stop_pc (), 0); /* OK, we're just going to keep stepping here. */ - if (stop_func_sal.pc == ecs->event_thread->suspend.stop_pc) + if (stop_func_sal.pc == ecs->event_thread->stop_pc ()) { /* We're there already. Just stop stepping now. */ end_stepping_range (ecs); @@ -8054,7 +8028,7 @@ keep_going_pass_signal (struct execution_control_state *ecs) non-signal event (e.g., a fork); or took a signal which we are supposed to pass through to the inferior. Simply continue. */ - resume (ecs->event_thread->suspend.stop_signal); + resume (ecs->event_thread->stop_signal ()); } else if (step_over_info_valid_p ()) { @@ -8145,7 +8119,7 @@ keep_going_pass_signal (struct execution_control_state *ecs) ecs->event_thread->control.trap_expected = (remove_bp || remove_wps); - resume (ecs->event_thread->suspend.stop_signal); + resume (ecs->event_thread->stop_signal ()); } prepare_to_wait (ecs); @@ -8159,11 +8133,11 @@ static void keep_going (struct execution_control_state *ecs) { if (ecs->event_thread->control.trap_expected - && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) + && ecs->event_thread->stop_signal () == GDB_SIGNAL_TRAP) ecs->event_thread->control.trap_expected = 0; - if (!signal_program[ecs->event_thread->suspend.stop_signal]) - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + if (!signal_program[ecs->event_thread->stop_signal ()]) + ecs->event_thread->set_stop_signal (GDB_SIGNAL_0); keep_going_pass_signal (ecs); } @@ -8349,7 +8323,7 @@ print_stop_location (struct target_waitstatus *ws) && frame_id_eq (tp->control.step_frame_id, get_frame_id (get_current_frame ())) && (tp->control.step_start_function - == find_pc_function (tp->suspend.stop_pc))) + == find_pc_function (tp->stop_pc ()))) { /* Finished step, just print source line. */ source_flag = SRC_LINE; @@ -8545,7 +8519,7 @@ normal_stop (void) update_thread_list (); if (last.kind == TARGET_WAITKIND_STOPPED && stopped_by_random_signal) - gdb::observers::signal_received.notify (inferior_thread ()->suspend.stop_signal); + gdb::observers::signal_received.notify (inferior_thread ()->stop_signal ()); /* As with the notification of thread events, we want to delay notifying the user that we've switched thread context until @@ -9134,9 +9108,10 @@ public: infcall_suspend_state (struct gdbarch *gdbarch, const struct thread_info *tp, struct regcache *regcache) - : m_thread_suspend (tp->suspend), - m_registers (new readonly_detached_regcache (*regcache)) + : m_registers (new readonly_detached_regcache (*regcache)) { + tp->save_suspend_to (m_thread_suspend); + gdb::unique_xmalloc_ptr siginfo_data; if (gdbarch_get_siginfo_type_p (gdbarch)) @@ -9175,7 +9150,7 @@ public: struct thread_info *tp, struct regcache *regcache) const { - tp->suspend = m_thread_suspend; + tp->restore_suspend_from (m_thread_suspend); if (m_siginfo_gdbarch == gdbarch) { @@ -9225,7 +9200,7 @@ save_infcall_suspend_state () any stop signal information. The stop signal is not useful when starting an inferior function call, and run_inferior_call will not use the signal due to its `proceed' call with GDB_SIGNAL_0. */ - tp->suspend.stop_signal = GDB_SIGNAL_0; + tp->set_stop_signal (GDB_SIGNAL_0); return inf_state; } diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c index b162466f810..1559ad9fd71 100644 --- a/gdb/linux-fork.c +++ b/gdb/linux-fork.c @@ -224,8 +224,7 @@ fork_load_infrun_state (struct fork_info *fp) registers_changed (); reinit_frame_cache (); - inferior_thread ()->suspend.stop_pc - = regcache_read_pc (get_current_regcache ()); + inferior_thread ()->set_stop_pc (regcache_read_pc (get_current_regcache ())); nullify_last_target_wait_ptid (); /* Now restore the file positions of open file descriptors. */ diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index f206b874929..dbdae284881 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1301,10 +1301,10 @@ get_detach_signal (struct lwp_info *lp) if (target_is_non_stop_p () && !tp->executing) { - if (tp->suspend.waitstatus_pending_p) - signo = tp->suspend.waitstatus.value.sig; + if (tp->has_pending_waitstatus ()) + signo = tp->pending_waitstatus ().value.sig; else - signo = tp->suspend.stop_signal; + signo = tp->stop_signal (); } else if (!target_is_non_stop_p ()) { @@ -1315,7 +1315,7 @@ get_detach_signal (struct lwp_info *lp) if (last_target == linux_target && lp->ptid.lwp () == last_ptid.lwp ()) - signo = tp->suspend.stop_signal; + signo = tp->stop_signal (); } } @@ -1631,8 +1631,8 @@ linux_nat_resume_callback (struct lwp_info *lp, struct lwp_info *except) thread = find_thread_ptid (linux_target, lp->ptid); if (thread != NULL) { - signo = thread->suspend.stop_signal; - thread->suspend.stop_signal = GDB_SIGNAL_0; + signo = thread->stop_signal (); + thread->set_stop_signal (GDB_SIGNAL_0); } } diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 927e69bf1e1..8c0885ed5b4 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -2017,7 +2017,7 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) thread_info *signalled_thr = gcore_find_signalled_thread (); gdb_signal stop_signal; if (signalled_thr != nullptr) - stop_signal = signalled_thr->suspend.stop_signal; + stop_signal = signalled_thr->stop_signal (); else stop_signal = GDB_SIGNAL_0; diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index 39efa804d80..cfbc2f6574f 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -96,7 +96,7 @@ python_on_normal_stop (struct bpstats *bs, int print_frame) if (inferior_ptid == null_ptid) return; - stop_signal = inferior_thread ()->suspend.stop_signal; + stop_signal = inferior_thread ()->stop_signal (); gdbpy_enter enter_py (get_current_arch (), current_language); diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index bf899ebeb24..85e357e604a 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -2795,8 +2795,7 @@ record_btrace_set_replay (struct thread_info *tp, /* Start anew from the new replay position. */ record_btrace_clear_histories (btinfo); - inferior_thread ()->suspend.stop_pc - = regcache_read_pc (get_current_regcache ()); + inferior_thread ()->set_stop_pc (regcache_read_pc (get_current_regcache ())); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); } diff --git a/gdb/record-full.c b/gdb/record-full.c index 9e157c6e048..f5c4244f0ed 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -1993,8 +1993,7 @@ record_full_goto_entry (struct record_full_entry *p) registers_changed (); reinit_frame_cache (); - inferior_thread ()->suspend.stop_pc - = regcache_read_pc (get_current_regcache ()); + inferior_thread ()->set_stop_pc (regcache_read_pc (get_current_regcache ())); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); } diff --git a/gdb/remote.c b/gdb/remote.c index b908a5bfce5..6d674c8139f 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -766,6 +766,7 @@ public: /* Remote specific methods. */ void remote_notice_new_inferior (ptid_t currthread, bool executing); + void print_one_stopped_thread (thread_info *thread); void process_initial_stop_replies (int from_tty); thread_info *remote_add_thread (ptid_t ptid, bool running, bool executing); @@ -4479,20 +4480,36 @@ remote_target::add_current_inferior_and_thread (const char *wait_status) /* Print info about a thread that was found already stopped on connection. */ -static void -print_one_stopped_thread (struct thread_info *thread) +void +remote_target::print_one_stopped_thread (thread_info *thread) { - struct target_waitstatus *ws = &thread->suspend.waitstatus; + target_waitstatus ws; + + /* If there is a pending waitstatus, use it. If there isn't it's because + the thread's stop was reported with TARGET_WAITKIND_STOPPED / GDB_SIGNAL_0 + and process_initial_stop_replies decided it wasn't interesting to save + and report to the core. */ + if (thread->has_pending_waitstatus ()) + { + ws = thread->pending_waitstatus (); + thread->clear_pending_waitstatus (); + } + else + { + ws.kind = TARGET_WAITKIND_STOPPED; + ws.value.sig = GDB_SIGNAL_0; + } switch_to_thread (thread); - thread->suspend.stop_pc = get_frame_pc (get_current_frame ()); + thread->set_stop_pc (get_frame_pc (get_current_frame ())); set_current_sal_from_frame (get_current_frame ()); - thread->suspend.waitstatus_pending_p = 0; + /* For "info program". */ + set_last_target_status (this, thread->ptid, ws); - if (ws->kind == TARGET_WAITKIND_STOPPED) + if (ws.kind == TARGET_WAITKIND_STOPPED) { - enum gdb_signal sig = ws->value.sig; + enum gdb_signal sig = ws.value.sig; if (signal_print_state (sig)) gdb::observers::signal_received.notify (sig); @@ -4513,6 +4530,9 @@ remote_target::process_initial_stop_replies (int from_tty) struct thread_info *lowest_stopped = NULL; struct thread_info *first = NULL; + /* This is only used when the target is non-stop. */ + gdb_assert (target_is_non_stop_p ()); + /* Consume the initial pending events. */ while (pending_stop_replies-- > 0) { @@ -4557,15 +4577,13 @@ remote_target::process_initial_stop_replies (int from_tty) instead of signal 0. Suppress it. */ if (sig == GDB_SIGNAL_TRAP) sig = GDB_SIGNAL_0; - evthread->suspend.stop_signal = sig; + evthread->set_stop_signal (sig); ws.value.sig = sig; } - evthread->suspend.waitstatus = ws; - if (ws.kind != TARGET_WAITKIND_STOPPED || ws.value.sig != GDB_SIGNAL_0) - evthread->suspend.waitstatus_pending_p = 1; + evthread->set_pending_waitstatus (ws); set_executing (this, event_ptid, false); set_running (this, event_ptid, false); @@ -4619,8 +4637,7 @@ remote_target::process_initial_stop_replies (int from_tty) else if (thread->state != THREAD_STOPPED) continue; - if (selected == NULL - && thread->suspend.waitstatus_pending_p) + if (selected == nullptr && thread->has_pending_waitstatus ()) selected = thread; if (lowest_stopped == NULL @@ -4644,11 +4661,6 @@ remote_target::process_initial_stop_replies (int from_tty) print_one_stopped_thread (thread); } - - /* For "info program". */ - thread_info *thread = inferior_thread (); - if (thread->state == THREAD_STOPPED) - set_last_target_status (this, inferior_ptid, thread->suspend.waitstatus); } /* Start the remote connection and sync state. */ @@ -6260,11 +6272,11 @@ remote_target::append_pending_thread_resumptions (char *p, char *endp, { for (thread_info *thread : all_non_exited_threads (this, ptid)) if (inferior_ptid != thread->ptid - && thread->suspend.stop_signal != GDB_SIGNAL_0) + && thread->stop_signal () != GDB_SIGNAL_0) { p = append_resumption (p, endp, thread->ptid, - 0, thread->suspend.stop_signal); - thread->suspend.stop_signal = GDB_SIGNAL_0; + 0, thread->stop_signal ()); + thread->set_stop_signal (GDB_SIGNAL_0); resume_clear_thread_private_info (thread); } @@ -7202,7 +7214,7 @@ struct notif_client notif_client_stop = -1 if we want to check all threads. */ static int -is_pending_fork_parent (struct target_waitstatus *ws, int event_pid, +is_pending_fork_parent (const target_waitstatus *ws, int event_pid, ptid_t thread_ptid) { if (ws->kind == TARGET_WAITKIND_FORKED @@ -7218,11 +7230,11 @@ is_pending_fork_parent (struct target_waitstatus *ws, int event_pid, /* Return the thread's pending status used to determine whether the thread is a fork parent stopped at a fork event. */ -static struct target_waitstatus * +static const target_waitstatus * thread_pending_fork_status (struct thread_info *thread) { - if (thread->suspend.waitstatus_pending_p) - return &thread->suspend.waitstatus; + if (thread->has_pending_waitstatus ()) + return &thread->pending_waitstatus (); else return &thread->pending_follow; } @@ -7232,7 +7244,7 @@ thread_pending_fork_status (struct thread_info *thread) static int is_pending_fork_parent_thread (struct thread_info *thread) { - struct target_waitstatus *ws = thread_pending_fork_status (thread); + const target_waitstatus *ws = thread_pending_fork_status (thread); int pid = -1; return is_pending_fork_parent (ws, pid, thread->ptid); @@ -7254,7 +7266,7 @@ remote_target::remove_new_fork_children (threads_listing_context *context) fork child threads from the CONTEXT list. */ for (thread_info *thread : all_non_exited_threads (this)) { - struct target_waitstatus *ws = thread_pending_fork_status (thread); + const target_waitstatus *ws = thread_pending_fork_status (thread); if (is_pending_fork_parent (ws, pid, thread->ptid)) context->remove_thread (ws->value.related_pid); diff --git a/gdb/thread.c b/gdb/thread.c index c6c63b742db..289d33c74c3 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -275,7 +275,7 @@ thread_info::thread_info (struct inferior *inf_, ptid_t ptid_) /* Nothing to follow yet. */ memset (&this->pending_follow, 0, sizeof (this->pending_follow)); this->pending_follow.kind = TARGET_WAITKIND_SPURIOUS; - this->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE; + this->m_suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE; } thread_info::~thread_info () @@ -295,6 +295,27 @@ thread_info::deletable () const /* See gdbthread.h. */ +void +thread_info::set_pending_waitstatus (const target_waitstatus &ws) +{ + gdb_assert (!this->has_pending_waitstatus ()); + + m_suspend.waitstatus = ws; + m_suspend.waitstatus_pending_p = 1; +} + +/* See gdbthread.h. */ + +void +thread_info::clear_pending_waitstatus () +{ + gdb_assert (this->has_pending_waitstatus ()); + + m_suspend.waitstatus_pending_p = 0; +} + +/* See gdbthread.h. */ + int thread_is_in_step_over_chain (struct thread_info *tp) { @@ -771,7 +792,7 @@ set_executing_thread (thread_info *thr, bool executing) { thr->executing = executing; if (executing) - thr->suspend.stop_pc = ~(CORE_ADDR) 0; + thr->set_stop_pc (~(CORE_ADDR) 0); } void -- 2.30.2