Remove the global stop_signal in favour of a per-thread

stop_signal.

	* inferior.h (stop_signal): Delete.
	* gdbthread.h (save_infrun_state, load_infrun_state): Remove
	stop_signal argument.
	* thread.c (load_infrun_state, save_infrun_state): Remove
	stop_signal argument.  Don't reference it.

	* infcmd.c (stop_signal): Delete.
	(program_info): Adjust.
	* infrun.c (resume): Clear stop_signal.
	(proceed): Adjust.  Pass the last stop_signal to the thread we're
	resuming.
	(context_switch): Don't context-switch stop_signal.
	(handle_inferior_event, keep_going): Adjust.
	(save_inferior_status, restore_inferior_status): Adjust.

	* fbsd-nat.c: Include "gdbthread.h".
	(find_signalled_thread, find_stop_signal): New.
	(fbsd_make_corefile_notes): Use it.
	* fork-child.c (startup_inferior): Adjust.

	* linux-nat.c (get_pending_status): Adjust.
	(linux_nat_do_thread_registers): Adjust.
	(find_signalled_thread, find_stop_signal): New.
	(linux_nat_do_thread_registers): Add stop_signal parameter.
	(struct linux_nat_corefile_thread_data): Add stop_signal member.
	(linux_nat_corefile_thread_callback): Pass stop_signal.
	(linux_nat_do_registers): Delete.
	(linux_nat_make_corefile_notes): Use find_stop_signal.  Assume
	there's always a thread.

	* procfs.c (find_signalled_thread, find_stop_signal): New.
	(find_stop_signal): New.
	(procfs_do_thread_registers): Add stop_signal parameter.
	(struct procfs_corefile_thread_data): Add stop_signal member.
	(procfs_corefile_thread_callback): Pass args->stop_signal.
	(procfs_make_note_section): Find the last stop_signal.

	* solib-irix.c: Include gdbthread.h.
	(irix_solib_create_inferior_hook): Adjust.
	* solib-osf.c: Include gdbthread.h.
	(osf_solib_create_inferior_hook): Adjust.
	* solib-sunos.c: Include gdbthread.h.
	(sunos_solib_create_inferior_hook): Adjust.
	* solib-svr4.c: Include gdbthread.h.
	(svr4_solib_create_inferior_hook): Adjust.

	* win32-nat.c (do_initial_win32_stuff): Adjust.
This commit is contained in:
Pedro Alves 2008-09-08 21:51:18 +00:00
parent 32400bebb2
commit 2020b7abd8
16 changed files with 274 additions and 131 deletions

View file

@ -1078,6 +1078,10 @@ a command like `return' or `jump' to continue execution."));
}
target_resume (resume_ptid, step, sig);
/* Avoid confusing the next resume, if the next stop/resume
happens to apply to another thread. */
tp->stop_signal = TARGET_SIGNAL_0;
}
discard_cleanups (old_cleanups);
@ -1182,6 +1186,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
struct thread_info *tp;
CORE_ADDR pc = regcache_read_pc (regcache);
int oneproc = 0;
enum target_signal stop_signal;
if (step > 0)
step_start_function = find_pc_function (pc);
@ -1256,12 +1261,37 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
if (! tp->trap_expected || use_displaced_stepping (gdbarch))
insert_breakpoints ();
if (!non_stop)
{
/* Pass the last stop signal to the thread we're resuming,
irrespective of whether the current thread is the thread that
got the last event or not. This was historically GDB's
behaviour before keeping a stop_signal per thread. */
struct thread_info *last_thread;
ptid_t last_ptid;
struct target_waitstatus last_status;
get_last_target_status (&last_ptid, &last_status);
if (!ptid_equal (inferior_ptid, last_ptid)
&& !ptid_equal (last_ptid, null_ptid)
&& !ptid_equal (last_ptid, minus_one_ptid))
{
last_thread = find_thread_pid (last_ptid);
if (last_thread)
{
tp->stop_signal = last_thread->stop_signal;
last_thread->stop_signal = TARGET_SIGNAL_0;
}
}
}
if (siggnal != TARGET_SIGNAL_DEFAULT)
stop_signal = siggnal;
tp->stop_signal = siggnal;
/* If this signal should not be seen by program,
give it zero. Used for debugging signals. */
else if (!signal_program[stop_signal])
stop_signal = TARGET_SIGNAL_0;
else if (!signal_program[tp->stop_signal])
tp->stop_signal = TARGET_SIGNAL_0;
annotate_starting ();
@ -1300,7 +1330,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
init_infwait_state ();
/* Resume inferior. */
resume (oneproc || step || bpstat_should_step (), stop_signal);
resume (oneproc || step || bpstat_should_step (), tp->stop_signal);
/* Wait for it to stop (if not standalone)
and in any case decode why it stopped, and act accordingly. */
@ -1355,9 +1385,6 @@ init_wait_for_inferior (void)
breakpoint_init_inferior (inf_starting);
/* Don't confuse first call to proceed(). */
stop_signal = TARGET_SIGNAL_0;
/* The first resume is not following a fork/vfork/exec. */
pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */
@ -1712,15 +1739,13 @@ context_switch (ptid_t ptid)
save_infrun_state (inferior_ptid,
cmd_continuation, intermediate_continuation,
stop_step,
step_multi,
stop_signal);
step_multi);
/* Load infrun state for the new thread. */
load_infrun_state (ptid,
&cmd_continuation, &intermediate_continuation,
&stop_step,
&step_multi,
&stop_signal);
&step_multi);
}
switch_to_thread (ptid);
@ -2023,7 +2048,6 @@ handle_inferior_event (struct execution_control_state *ecs)
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
stop_print_frame = 0;
stop_signal = ecs->ws.value.sig;
target_terminal_ours (); /* Must do this before mourn anyway */
/* Note: By definition of TARGET_WAITKIND_SIGNALLED, we shouldn't
@ -2033,7 +2057,7 @@ handle_inferior_event (struct execution_control_state *ecs)
may be needed. */
target_mourn_inferior ();
print_stop_reason (SIGNAL_EXITED, stop_signal);
print_stop_reason (SIGNAL_EXITED, ecs->ws.value.sig);
singlestep_breakpoints_inserted_p = 0;
stop_stepping (ecs);
return;
@ -2044,7 +2068,6 @@ handle_inferior_event (struct execution_control_state *ecs)
case TARGET_WAITKIND_VFORKED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
stop_signal = TARGET_SIGNAL_TRAP;
pending_follow.kind = ecs->ws.kind;
pending_follow.fork_event.parent_pid = ecs->ptid;
@ -2065,17 +2088,16 @@ handle_inferior_event (struct execution_control_state *ecs)
/* If no catchpoint triggered for this, then keep going. */
if (ecs->random_signal)
{
stop_signal = TARGET_SIGNAL_0;
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
keep_going (ecs);
return;
}
ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
goto process_event_stop_test;
case TARGET_WAITKIND_EXECD:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
stop_signal = TARGET_SIGNAL_TRAP;
pending_follow.execd_pathname =
savestring (ecs->ws.value.execd_pathname,
strlen (ecs->ws.value.execd_pathname));
@ -2109,10 +2131,11 @@ handle_inferior_event (struct execution_control_state *ecs)
/* If no catchpoint triggered for this, then keep going. */
if (ecs->random_signal)
{
stop_signal = TARGET_SIGNAL_0;
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
keep_going (ecs);
return;
}
ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
goto process_event_stop_test;
/* Be careful not to try to gather much state about a thread
@ -2139,7 +2162,7 @@ handle_inferior_event (struct execution_control_state *ecs)
case TARGET_WAITKIND_STOPPED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
stop_signal = ecs->ws.value.sig;
ecs->event_thread->stop_signal = ecs->ws.value.sig;
break;
/* We had an event in the inferior, but we are not interested
@ -2182,7 +2205,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
/* Do we need to clean up the state of a thread that has completed a
displaced single-step? (Doing so usually affects the PC, so do
it here, before we set stop_pc.) */
displaced_step_fixup (ecs->ptid, stop_signal);
if (ecs->ws.kind == TARGET_WAITKIND_STOPPED)
displaced_step_fixup (ecs->ptid, ecs->event_thread->stop_signal);
stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
@ -2216,7 +2240,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
/* We've either finished single-stepping past the single-step
breakpoint, or stopped for some other reason. It would be nice if
we could tell, but we can't reliably. */
if (stop_signal == TARGET_SIGNAL_TRAP)
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
@ -2245,7 +2269,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
/* If we stopped for some other reason than single-stepping, ignore
the fact that we were supposed to switch back. */
if (stop_signal == TARGET_SIGNAL_TRAP)
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
{
struct thread_info *tp;
@ -2279,7 +2303,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
another thread. If so, then step that thread past the breakpoint,
and continue it. */
if (stop_signal == TARGET_SIGNAL_TRAP)
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
{
int thread_hop_needed = 0;
@ -2333,6 +2357,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
if (new_singlestep_pc != singlestep_pc)
{
enum target_signal stop_signal;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: unexpected thread,"
" but expected thread advanced also\n");
@ -2341,8 +2367,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
singlestep_ptid. Don't swap here, since that's
the context we want to use. Just fudge our
state and continue. */
stop_signal = ecs->event_thread->stop_signal;
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
ecs->ptid = singlestep_ptid;
ecs->event_thread = find_thread_pid (ecs->ptid);
ecs->event_thread->stop_signal = stop_signal;
stop_pc = new_singlestep_pc;
}
else
@ -2498,7 +2527,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
ecs->random_signal = 0;
stopped_by_random_signal = 0;
if (stop_signal == TARGET_SIGNAL_TRAP
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
&& ecs->event_thread->trap_expected
&& gdbarch_single_step_through_delay_p (current_gdbarch)
&& currently_stepping (ecs->event_thread))
@ -2555,16 +2584,16 @@ targets should add new threads to the thread list themselves in non-stop mode.")
If we're doing a displaced step past a breakpoint, then the
breakpoint is always inserted at the original instruction;
non-standard signals can't be explained by the breakpoint. */
if (stop_signal == TARGET_SIGNAL_TRAP
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
|| (! ecs->event_thread->trap_expected
&& breakpoint_inserted_here_p (stop_pc)
&& (stop_signal == TARGET_SIGNAL_ILL
|| stop_signal == TARGET_SIGNAL_SEGV
|| stop_signal == TARGET_SIGNAL_EMT))
&& (ecs->event_thread->stop_signal == TARGET_SIGNAL_ILL
|| ecs->event_thread->stop_signal == TARGET_SIGNAL_SEGV
|| ecs->event_thread->stop_signal == TARGET_SIGNAL_EMT))
|| stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
|| stop_soon == STOP_QUIETLY_REMOTE)
{
if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
@ -2596,11 +2625,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
(e.g. gdbserver). We already rely on SIGTRAP being our
signal, so this is no exception. */
if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
&& (stop_signal == TARGET_SIGNAL_STOP
|| stop_signal == TARGET_SIGNAL_TRAP))
&& (ecs->event_thread->stop_signal == TARGET_SIGNAL_STOP
|| ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP))
{
stop_stepping (ecs);
stop_signal = TARGET_SIGNAL_0;
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
return;
}
@ -2631,7 +2660,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
be necessary for call dummies on a non-executable stack on
SPARC. */
if (stop_signal == TARGET_SIGNAL_TRAP)
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
ecs->random_signal
= !(bpstat_explains_signal (ecs->event_thread->stop_bpstat)
|| ecs->event_thread->trap_expected
@ -2641,7 +2670,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
{
ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
if (!ecs->random_signal)
stop_signal = TARGET_SIGNAL_TRAP;
ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
}
}
@ -2662,17 +2691,18 @@ process_event_stop_test:
int printed = 0;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n", stop_signal);
fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n",
ecs->event_thread->stop_signal);
stopped_by_random_signal = 1;
if (signal_print[stop_signal])
if (signal_print[ecs->event_thread->stop_signal])
{
printed = 1;
target_terminal_ours_for_output ();
print_stop_reason (SIGNAL_RECEIVED, stop_signal);
print_stop_reason (SIGNAL_RECEIVED, ecs->event_thread->stop_signal);
}
if (signal_stop_state (stop_signal))
if (signal_stop_state (ecs->event_thread->stop_signal))
{
stop_stepping (ecs);
return;
@ -2683,8 +2713,8 @@ process_event_stop_test:
target_terminal_inferior ();
/* Clear the signal if it should not be passed. */
if (signal_program[stop_signal] == 0)
stop_signal = TARGET_SIGNAL_0;
if (signal_program[ecs->event_thread->stop_signal] == 0)
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
if (ecs->event_thread->prev_pc == read_pc ()
&& ecs->event_thread->trap_expected
@ -2712,7 +2742,7 @@ process_event_stop_test:
}
if (ecs->event_thread->step_range_end != 0
&& stop_signal != TARGET_SIGNAL_0
&& ecs->event_thread->stop_signal != TARGET_SIGNAL_0
&& (ecs->event_thread->step_range_start <= stop_pc
&& stop_pc < ecs->event_thread->step_range_end)
&& frame_id_eq (get_frame_id (get_current_frame ()),
@ -3517,12 +3547,14 @@ keep_going (struct execution_control_state *ecs)
/* If we did not do break;, it means we should keep running the
inferior and not return to debugger. */
if (ecs->event_thread->trap_expected && stop_signal != TARGET_SIGNAL_TRAP)
if (ecs->event_thread->trap_expected
&& ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
{
/* We took a signal (which we are supposed to pass through to
the inferior, else we'd not get here) and we haven't yet
gotten our trap. Simply continue. */
resume (currently_stepping (ecs->event_thread), stop_signal);
resume (currently_stepping (ecs->event_thread),
ecs->event_thread->stop_signal);
}
else
{
@ -3577,11 +3609,12 @@ keep_going (struct execution_control_state *ecs)
simulator; the simulator then delivers the hardware
equivalent of a SIGNAL_TRAP to the program being debugged. */
if (stop_signal == TARGET_SIGNAL_TRAP && !signal_program[stop_signal])
stop_signal = TARGET_SIGNAL_0;
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
&& !signal_program[ecs->event_thread->stop_signal])
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
resume (currently_stepping (ecs->event_thread), stop_signal);
resume (currently_stepping (ecs->event_thread),
ecs->event_thread->stop_signal);
}
prepare_to_wait (ecs);
@ -4366,7 +4399,7 @@ save_inferior_status (int restore_stack_info)
struct inferior_status *inf_status = XMALLOC (struct inferior_status);
struct thread_info *tp = inferior_thread ();
inf_status->stop_signal = stop_signal;
inf_status->stop_signal = tp->stop_signal;
inf_status->stop_pc = stop_pc;
inf_status->stop_step = stop_step;
inf_status->stop_stack_dummy = stop_stack_dummy;
@ -4420,7 +4453,7 @@ restore_inferior_status (struct inferior_status *inf_status)
{
struct thread_info *tp = inferior_thread ();
stop_signal = inf_status->stop_signal;
tp->stop_signal = inf_status->stop_signal;
stop_pc = inf_status->stop_pc;
stop_step = inf_status->stop_step;
stop_stack_dummy = inf_status->stop_stack_dummy;