mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 09:58:19 +08:00
Factor out after-stop event handling code from stop_all_threads
This moves the code handling an event out of wait_one to a separate function, to be used in another context in a following patch. gdb/ChangeLog: * infrun.c (handle_one): New function, factored out from ... (stop_all_threads): ... here.
This commit is contained in:
@ -1,3 +1,8 @@
|
|||||||
|
2021-02-03 Pedro Alves <pedro@palves.net>
|
||||||
|
|
||||||
|
* infrun.c (handle_one): New function, factored out from ...
|
||||||
|
(stop_all_threads): ... here.
|
||||||
|
|
||||||
2021-02-03 Pedro Alves <pedro@palves.net>
|
2021-02-03 Pedro Alves <pedro@palves.net>
|
||||||
|
|
||||||
* remote.c (remote_notif_stop_ack): Don't error out on
|
* remote.c (remote_notif_stop_ack): Don't error out on
|
||||||
|
288
gdb/infrun.c
288
gdb/infrun.c
@ -4560,6 +4560,156 @@ mark_non_executing_threads (process_stratum_target *target,
|
|||||||
set_resumed (target, mark_ptid, false);
|
set_resumed (target, mark_ptid, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle one event after stopping threads. If the eventing thread
|
||||||
|
reports back any interesting event, we leave it pending. If the
|
||||||
|
eventing thread was in the middle of a displaced step, we
|
||||||
|
cancel/finish it. Returns true if there are no resumed threads
|
||||||
|
left in the target (thus there's no point in waiting further),
|
||||||
|
false otherwise. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
handle_one (const wait_one_event &event)
|
||||||
|
{
|
||||||
|
infrun_debug_printf
|
||||||
|
("%s %s", target_waitstatus_to_string (&event.ws).c_str (),
|
||||||
|
target_pid_to_str (event.ptid).c_str ());
|
||||||
|
|
||||||
|
if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
|
||||||
|
{
|
||||||
|
/* All resumed threads exited. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
|
||||||
|
|| event.ws.kind == TARGET_WAITKIND_EXITED
|
||||||
|
|| event.ws.kind == TARGET_WAITKIND_SIGNALLED)
|
||||||
|
{
|
||||||
|
/* One thread/process exited/signalled. */
|
||||||
|
|
||||||
|
thread_info *t = nullptr;
|
||||||
|
|
||||||
|
/* The target may have reported just a pid. If so, try
|
||||||
|
the first non-exited thread. */
|
||||||
|
if (event.ptid.is_pid ())
|
||||||
|
{
|
||||||
|
int pid = event.ptid.pid ();
|
||||||
|
inferior *inf = find_inferior_pid (event.target, pid);
|
||||||
|
for (thread_info *tp : inf->non_exited_threads ())
|
||||||
|
{
|
||||||
|
t = tp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is no available thread, the event would
|
||||||
|
have to be appended to a per-inferior event list,
|
||||||
|
which does not exist (and if it did, we'd have
|
||||||
|
to adjust run control command to be able to
|
||||||
|
resume such an inferior). We assert here instead
|
||||||
|
of going into an infinite loop. */
|
||||||
|
gdb_assert (t != nullptr);
|
||||||
|
|
||||||
|
infrun_debug_printf
|
||||||
|
("using %s", target_pid_to_str (t->ptid).c_str ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = find_thread_ptid (event.target, event.ptid);
|
||||||
|
/* Check if this is the first time we see this thread.
|
||||||
|
Don't bother adding if it individually exited. */
|
||||||
|
if (t == nullptr
|
||||||
|
&& event.ws.kind != TARGET_WAITKIND_THREAD_EXITED)
|
||||||
|
t = add_thread (event.target, event.ptid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t != nullptr)
|
||||||
|
{
|
||||||
|
/* Set the threads as non-executing to avoid
|
||||||
|
another stop attempt on them. */
|
||||||
|
switch_to_thread_no_regs (t);
|
||||||
|
mark_non_executing_threads (event.target, event.ptid,
|
||||||
|
event.ws);
|
||||||
|
save_waitstatus (t, &event.ws);
|
||||||
|
t->stop_requested = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread_info *t = find_thread_ptid (event.target, event.ptid);
|
||||||
|
if (t == NULL)
|
||||||
|
t = add_thread (event.target, event.ptid);
|
||||||
|
|
||||||
|
t->stop_requested = 0;
|
||||||
|
t->executing = 0;
|
||||||
|
t->resumed = false;
|
||||||
|
t->control.may_range_step = 0;
|
||||||
|
|
||||||
|
/* This may be the first time we see the inferior report
|
||||||
|
a stop. */
|
||||||
|
inferior *inf = find_inferior_ptid (event.target, event.ptid);
|
||||||
|
if (inf->needs_setup)
|
||||||
|
{
|
||||||
|
switch_to_thread_no_regs (t);
|
||||||
|
setup_inferior (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.ws.kind == TARGET_WAITKIND_STOPPED
|
||||||
|
&& 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;
|
||||||
|
|
||||||
|
if (displaced_step_finish (t, GDB_SIGNAL_0)
|
||||||
|
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
|
||||||
|
{
|
||||||
|
/* Add it back to the step-over queue. */
|
||||||
|
infrun_debug_printf
|
||||||
|
("displaced-step of %s canceled",
|
||||||
|
target_pid_to_str (t->ptid).c_str ());
|
||||||
|
|
||||||
|
t->control.trap_expected = 0;
|
||||||
|
global_thread_step_over_chain_enqueue (t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum gdb_signal sig;
|
||||||
|
struct regcache *regcache;
|
||||||
|
|
||||||
|
infrun_debug_printf
|
||||||
|
("target_wait %s, saving status for %d.%ld.%ld",
|
||||||
|
target_waitstatus_to_string (&event.ws).c_str (),
|
||||||
|
t->ptid.pid (), t->ptid.lwp (), t->ptid.tid ());
|
||||||
|
|
||||||
|
/* Record for later. */
|
||||||
|
save_waitstatus (t, &event.ws);
|
||||||
|
|
||||||
|
sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
|
||||||
|
? event.ws.value.sig : GDB_SIGNAL_0);
|
||||||
|
|
||||||
|
if (displaced_step_finish (t, sig)
|
||||||
|
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
|
||||||
|
{
|
||||||
|
/* Add it back to the step-over queue. */
|
||||||
|
t->control.trap_expected = 0;
|
||||||
|
global_thread_step_over_chain_enqueue (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
regcache = get_thread_regcache (t);
|
||||||
|
t->suspend.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),
|
||||||
|
target_pid_to_str (t->ptid).c_str (),
|
||||||
|
currently_stepping (t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* See infrun.h. */
|
/* See infrun.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -4673,145 +4823,9 @@ stop_all_threads (void)
|
|||||||
for (int i = 0; i < waits_needed; i++)
|
for (int i = 0; i < waits_needed; i++)
|
||||||
{
|
{
|
||||||
wait_one_event event = wait_one ();
|
wait_one_event event = wait_one ();
|
||||||
|
if (handle_one (event))
|
||||||
infrun_debug_printf
|
|
||||||
("%s %s", target_waitstatus_to_string (&event.ws).c_str (),
|
|
||||||
target_pid_to_str (event.ptid).c_str ());
|
|
||||||
|
|
||||||
if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
|
|
||||||
{
|
|
||||||
/* All resumed threads exited. */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
|
|
||||||
|| event.ws.kind == TARGET_WAITKIND_EXITED
|
|
||||||
|| event.ws.kind == TARGET_WAITKIND_SIGNALLED)
|
|
||||||
{
|
|
||||||
/* One thread/process exited/signalled. */
|
|
||||||
|
|
||||||
thread_info *t = nullptr;
|
|
||||||
|
|
||||||
/* The target may have reported just a pid. If so, try
|
|
||||||
the first non-exited thread. */
|
|
||||||
if (event.ptid.is_pid ())
|
|
||||||
{
|
|
||||||
int pid = event.ptid.pid ();
|
|
||||||
inferior *inf = find_inferior_pid (event.target, pid);
|
|
||||||
for (thread_info *tp : inf->non_exited_threads ())
|
|
||||||
{
|
|
||||||
t = tp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there is no available thread, the event would
|
|
||||||
have to be appended to a per-inferior event list,
|
|
||||||
which does not exist (and if it did, we'd have
|
|
||||||
to adjust run control command to be able to
|
|
||||||
resume such an inferior). We assert here instead
|
|
||||||
of going into an infinite loop. */
|
|
||||||
gdb_assert (t != nullptr);
|
|
||||||
|
|
||||||
infrun_debug_printf
|
|
||||||
("using %s", target_pid_to_str (t->ptid).c_str ());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t = find_thread_ptid (event.target, event.ptid);
|
|
||||||
/* Check if this is the first time we see this thread.
|
|
||||||
Don't bother adding if it individually exited. */
|
|
||||||
if (t == nullptr
|
|
||||||
&& event.ws.kind != TARGET_WAITKIND_THREAD_EXITED)
|
|
||||||
t = add_thread (event.target, event.ptid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t != nullptr)
|
|
||||||
{
|
|
||||||
/* Set the threads as non-executing to avoid
|
|
||||||
another stop attempt on them. */
|
|
||||||
switch_to_thread_no_regs (t);
|
|
||||||
mark_non_executing_threads (event.target, event.ptid,
|
|
||||||
event.ws);
|
|
||||||
save_waitstatus (t, &event.ws);
|
|
||||||
t->stop_requested = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
thread_info *t = find_thread_ptid (event.target, event.ptid);
|
|
||||||
if (t == NULL)
|
|
||||||
t = add_thread (event.target, event.ptid);
|
|
||||||
|
|
||||||
t->stop_requested = 0;
|
|
||||||
t->executing = 0;
|
|
||||||
t->resumed = false;
|
|
||||||
t->control.may_range_step = 0;
|
|
||||||
|
|
||||||
/* This may be the first time we see the inferior report
|
|
||||||
a stop. */
|
|
||||||
inferior *inf = find_inferior_ptid (event.target, event.ptid);
|
|
||||||
if (inf->needs_setup)
|
|
||||||
{
|
|
||||||
switch_to_thread_no_regs (t);
|
|
||||||
setup_inferior (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.ws.kind == TARGET_WAITKIND_STOPPED
|
|
||||||
&& 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;
|
|
||||||
|
|
||||||
if (displaced_step_finish (t, GDB_SIGNAL_0)
|
|
||||||
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
|
|
||||||
{
|
|
||||||
/* Add it back to the step-over queue. */
|
|
||||||
infrun_debug_printf
|
|
||||||
("displaced-step of %s canceled: adding back to "
|
|
||||||
"the step-over queue",
|
|
||||||
target_pid_to_str (t->ptid).c_str ());
|
|
||||||
|
|
||||||
t->control.trap_expected = 0;
|
|
||||||
global_thread_step_over_chain_enqueue (t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
enum gdb_signal sig;
|
|
||||||
struct regcache *regcache;
|
|
||||||
|
|
||||||
infrun_debug_printf
|
|
||||||
("target_wait %s, saving status for %d.%ld.%ld",
|
|
||||||
target_waitstatus_to_string (&event.ws).c_str (),
|
|
||||||
t->ptid.pid (), t->ptid.lwp (), t->ptid.tid ());
|
|
||||||
|
|
||||||
/* Record for later. */
|
|
||||||
save_waitstatus (t, &event.ws);
|
|
||||||
|
|
||||||
sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
|
|
||||||
? event.ws.value.sig : GDB_SIGNAL_0);
|
|
||||||
|
|
||||||
if (displaced_step_finish (t, sig)
|
|
||||||
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
|
|
||||||
{
|
|
||||||
/* Add it back to the step-over queue. */
|
|
||||||
t->control.trap_expected = 0;
|
|
||||||
global_thread_step_over_chain_enqueue (t);
|
|
||||||
}
|
|
||||||
|
|
||||||
regcache = get_thread_regcache (t);
|
|
||||||
t->suspend.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),
|
|
||||||
target_pid_to_str (t->ptid).c_str (),
|
|
||||||
currently_stepping (t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user