* 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:
parent
97f2ed50d0
commit
2b00904856
4 changed files with 58 additions and 26 deletions
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
50
gdb/infrun.c
50
gdb/infrun.c
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue