aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2010-01-29 15:40:22 +0000
committerDaniel Jacobowitz <drow@false.org>2010-01-29 15:40:22 +0000
commit2b009048566bc0f8eed7ac4c889da40b9470cb0f (patch)
tree10cde133859f076d1f2166e0a17149b1594af436 /gdb
parent97f2ed50d0f6749e17b107b3520001c6288f7837 (diff)
downloadfsf-binutils-gdb-2b009048566bc0f8eed7ac4c889da40b9470cb0f.zip
fsf-binutils-gdb-2b009048566bc0f8eed7ac4c889da40b9470cb0f.tar.gz
fsf-binutils-gdb-2b009048566bc0f8eed7ac4c889da40b9470cb0f.tar.bz2
* 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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/gdbserver/ChangeLog6
-rw-r--r--gdb/gdbserver/linux-low.c21
-rw-r--r--gdb/infrun.c50
4 files changed, 58 insertions, 26 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d7b426d..45d1e61 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index e1ad397..fc6b6e2 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -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.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 8ec73d2..fb4aa5c 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -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
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 06f3ea0..8307986 100644
--- a/gdb/infrun.c
+++ b/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)
{