* infrun.c (prepare_to_proceed): Handle other signals which might
authorDaniel Jacobowitz <drow@false.org>
Fri, 29 Jan 2010 15:40:22 +0000 (15:40 +0000)
committerDaniel Jacobowitz <drow@false.org>
Fri, 29 Jan 2010 15:40:22 +0000 (15:40 +0000)
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.

gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c
gdb/infrun.c

index d7b426d7f57931462d063ab99fa2cfa3e079b780..45d1e61974083f3ac3c166324c60f6a141455dad 100644 (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.
index e1ad397d5b797b660f1cb804d0e31d65c52eb76e..fc6b6e222eb67d3526246da241cd97ab496ca0b4 100644 (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.
index 8ec73d2045fe0b8e255578cc7239e9392ebd6ea9..fb4aa5c2494ebfc8e32962dbc1e14a85052de8c6 100644 (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
index 06f3ea09dd3f0ad18a5363b48480c1f24837d7f5..8307986900b4d33b55263b062cf92d0c9b9e4cb0 100644 (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)
     {