* infrun.c (prepare_to_proceed): Handle other signals which might

match a breakpoint.
	(handle_inferior_event): Move the check for unusual breakpoint
	signals earlier.

	gdbserver/
	* linux-low.c (get_stop_pc): Check for SIGTRAP.
	(linux_wait_for_event_1): Handle SIGILL and SIGSEGV as possible
	breakpoints.
This commit is contained in:
Daniel Jacobowitz 2010-01-29 15:40:22 +00:00
parent 97f2ed50d0
commit 2b00904856
4 changed files with 58 additions and 26 deletions

View file

@ -1,3 +1,10 @@
2010-01-29 Daniel Jacobowitz <dan@codesourcery.com>
* infrun.c (prepare_to_proceed): Handle other signals which might
match a breakpoint.
(handle_inferior_event): Move the check for unusual breakpoint
signals earlier.
2010-01-29 Paul Hilfinger <hilfinger@adacore.com>
amd64 - function returning record with field straddling 2 registers.

View file

@ -1,3 +1,9 @@
2010-01-29 Daniel Jacobowitz <dan@codesourcery.com>
* linux-low.c (get_stop_pc): Check for SIGTRAP.
(linux_wait_for_event_1): Handle SIGILL and SIGSEGV as possible
breakpoints.
2010-01-21 Pedro Alves <pedro@codesourcery.com>
* linux-ppc-low.c (ppc_arch_setup): Adjust to regcache changes.

View file

@ -455,7 +455,8 @@ get_stop_pc (void)
struct regcache *regcache = get_thread_regcache (current_inferior, 1);
CORE_ADDR stop_pc = (*the_low_target.get_pc) (regcache);
if (! get_thread_lwp (current_inferior)->stepping)
if (! get_thread_lwp (current_inferior)->stepping
&& WSTOPSIG (get_thread_lwp (current_inferior)->last_status) == SIGTRAP)
stop_pc -= the_low_target.decr_pc_after_break;
if (debug_threads)
@ -1244,18 +1245,28 @@ linux_wait_for_event_1 (ptid_t ptid, int *wstat, int options)
continue;
}
/* If this event was not handled above, and is not a SIGTRAP, report
it. */
if (!WIFSTOPPED (*wstat) || WSTOPSIG (*wstat) != SIGTRAP)
/* If this event was not handled above, and is not a SIGTRAP,
report it. SIGILL and SIGSEGV are also treated as traps in case
a breakpoint is inserted at the current PC. */
if (!WIFSTOPPED (*wstat)
|| (WSTOPSIG (*wstat) != SIGTRAP && WSTOPSIG (*wstat) != SIGILL
&& WSTOPSIG (*wstat) != SIGSEGV))
return lwpid_of (event_child);
/* If this target does not support breakpoints, we simply report the
SIGTRAP; it's of no concern to us. */
signal; it's of no concern to us. */
if (the_low_target.get_pc == NULL)
return lwpid_of (event_child);
stop_pc = get_stop_pc ();
/* Only handle SIGILL or SIGSEGV if we've hit a recognized
breakpoint. */
if (WSTOPSIG (*wstat) != SIGTRAP
&& (event_child->stepping
|| ! (*the_low_target.breakpoint_at) (stop_pc)))
return lwpid_of (event_child);
/* bp_reinsert will only be set if we were single-stepping.
Notice that we will resume the process after hitting
a gdbserver breakpoint; single-stepping to/over one

View file

@ -1640,7 +1640,10 @@ prepare_to_proceed (int step)
/* Make sure we were stopped at a breakpoint. */
if (wait_status.kind != TARGET_WAITKIND_STOPPED
|| wait_status.value.sig != TARGET_SIGNAL_TRAP)
|| (wait_status.value.sig != TARGET_SIGNAL_TRAP
&& wait_status.value.sig != TARGET_SIGNAL_ILL
&& wait_status.value.sig != TARGET_SIGNAL_SEGV
&& wait_status.value.sig != TARGET_SIGNAL_EMT))
{
return 0;
}
@ -2661,6 +2664,7 @@ handle_inferior_event (struct execution_control_state *ecs)
{
struct frame_info *frame;
struct gdbarch *gdbarch;
struct regcache *regcache;
int sw_single_step_trap_p = 0;
int stopped_by_watchpoint;
int stepped_after_stopped_by_watchpoint = 0;
@ -2721,6 +2725,30 @@ handle_inferior_event (struct execution_control_state *ecs)
breakpoint_retire_moribund ();
/* First, distinguish signals caused by the debugger from signals
that have to do with the program's own actions. Note that
breakpoint insns may cause SIGTRAP or SIGILL or SIGEMT, depending
on the operating system version. Here we detect when a SIGILL or
SIGEMT is really a breakpoint and change it to SIGTRAP. We do
something similar for SIGSEGV, since a SIGSEGV will be generated
when we're trying to execute a breakpoint instruction on a
non-executable stack. This happens for call dummy breakpoints
for architectures like SPARC that place call dummies on the
stack. */
regcache = get_thread_regcache (ecs->ptid);
if (ecs->ws.kind == TARGET_WAITKIND_STOPPED
&& (ecs->ws.value.sig == TARGET_SIGNAL_ILL
|| ecs->ws.value.sig == TARGET_SIGNAL_SEGV
|| ecs->ws.value.sig == TARGET_SIGNAL_EMT)
&& breakpoint_inserted_here_p (get_regcache_aspace (regcache),
regcache_read_pc (regcache)))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: Treating signal as SIGTRAP\n");
ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
}
/* Mark the non-executing threads accordingly. In all-stop, all
threads of all processes are stopped when we get any event
reported. In non-stop mode, only the event thread stops. If
@ -3500,27 +3528,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
3) set ecs->random_signal to 1, and the decision between 1 and 2
will be made according to the signal handling tables. */
/* First, distinguish signals caused by the debugger from signals
that have to do with the program's own actions. Note that
breakpoint insns may cause SIGTRAP or SIGILL or SIGEMT, depending
on the operating system version. Here we detect when a SIGILL or
SIGEMT is really a breakpoint and change it to SIGTRAP. We do
something similar for SIGSEGV, since a SIGSEGV will be generated
when we're trying to execute a breakpoint instruction on a
non-executable stack. This happens for call dummy breakpoints
for architectures like SPARC that place call dummies on the
stack.
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 (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
|| (! ecs->event_thread->trap_expected
&& breakpoint_inserted_here_p (get_regcache_aspace (get_current_regcache ()),
stop_pc)
&& (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)
{