infrun.c:handle_inferior_event: Don't fall through in TARGET_WAITKIND_LOADED handling.
authorPedro Alves <palves@redhat.com>
Thu, 14 Nov 2013 19:43:25 +0000 (19:43 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 14 Nov 2013 19:43:25 +0000 (19:43 +0000)
Of all the TARGET_WAITKIND_XXXs event kinds other than
TARGET_WAITKIND_STOPPED, TARGET_WAITKIND_LOADED is the only kind that
doesn't end in a return, instead falling through to all the
signal/breakpoint/stepping handling code.  But it only falls through
in the STOP_QUIETLY_NO_SIGSTOP and STOP_QUIETLY_REMOTE cases, which
means the

  /* This is originated from start_remote(), start_inferior() and
     shared libraries hook functions.  */
  if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
    {
      if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
      stop_stepping (ecs);
      return;
    }

bit is eventually reached.  All tests before that is reached will
always fail.  It's simpler to inline the stop_soon checks close to the
TARGET_WAITKIND_LOADED code, which allows removing the fall through.

Tested on x86_64 Fedora 17, but that doesn't exercise this
TARGET_WAITKIND_LOADED.

Also ran gdb.base/solib-disc.exp on Cygwin/gdbserver, which exercises
reconnection while the inferior is stopped at an solib event, but then
again, gdbserver always replies a regular trap on initial connection,
instead of the last event the program had seen:

 Sending packet: $?#3f...Packet received: T0505:4ca72800;04:f8a62800;08:62fcc877;thread:d28;
 Sending packet: $Hc-1#09...Packet received: E01
 Sending packet: $qAttached#8f...Packet received: 0
 Packet qAttached (query-attached) is supported
 infrun: clear_proceed_status_thread (Thread 3368)
 Sending packet: $qOffsets#4b...Packet received:
 infrun: wait_for_inferior ()
 infrun: target_wait (-1, status) =
 infrun:   42000 [Thread 3368],
 infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
 infrun: infwait_normal_state
 infrun: TARGET_WAITKIND_STOPPED
 infrun: stop_pc = 0x77c8fc62
 infrun: quietly stopped
 infrun: stop_stepping

So the only way to exercise this would be to hack gdbserver.  I didn't
go that far though.  I'm reasonably confident this is correct.

gdb/
2013-11-14  Pedro Alves  <palves@redhat.com>

* infrun.c (handle_inferior_event) <TARGET_WAITKIND_LOADED>:
Handle STOP_QUIETLY_NO_SIGSTOP and STOP_QUIETLY_REMOTE here.
Assert we never fall through out of the TARGET_WAITKIND_LOADED
case.

gdb/ChangeLog
gdb/infrun.c

index a9afe0202c3cdf902d4304341423eca7f40fea56..e85ceea767a097202a7f108b687e3aecc7bb4505 100644 (file)
@@ -1,3 +1,10 @@
+2013-11-14  Pedro Alves  <palves@redhat.com>
+
+       * infrun.c (handle_inferior_event) <TARGET_WAITKIND_LOADED>:
+       Handle STOP_QUIETLY_NO_SIGSTOP and STOP_QUIETLY_REMOTE here.
+       Assert we never fall through out of the TARGET_WAITKIND_LOADED
+       case.
+
 2013-11-14  Tom Tromey  <tromey@redhat.com>
 
        * python/py-linetable.c (ltpy_has_line)
index c9e2fe22f48d23b067099246f999013c63d5a58b..ba55686eb6c20d85fc2cb6b95a88bf583fa5275c 100644 (file)
@@ -3319,6 +3319,8 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_LOADED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
+      if (!ptid_equal (ecs->ptid, inferior_ptid))
+       context_switch (ecs->ptid);
       /* Ignore gracefully during startup of the inferior, as it might
          be the shell which has just loaded some objects, otherwise
          add the symbols for the newly loaded objects.  Also ignore at
@@ -3330,8 +3332,6 @@ handle_inferior_event (struct execution_control_state *ecs)
          struct regcache *regcache;
          enum bpstat_signal_value sval;
 
-         if (!ptid_equal (ecs->ptid, inferior_ptid))
-           context_switch (ecs->ptid);
          regcache = get_thread_regcache (ecs->ptid);
 
          handle_solib_event ();
@@ -3370,13 +3370,9 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       /* If we are skipping through a shell, or through shared library
         loading that we aren't interested in, resume the program.  If
-        we're running the program normally, also resume.  But stop if
-        we're attaching or setting up a remote connection.  */
+        we're running the program normally, also resume.  */
       if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
        {
-         if (!ptid_equal (ecs->ptid, inferior_ptid))
-           context_switch (ecs->ptid);
-
          /* Loading of shared libraries might have changed breakpoint
             addresses.  Make sure new breakpoints are inserted.  */
          if (stop_soon == NO_STOP_QUIETLY
@@ -3387,7 +3383,19 @@ handle_inferior_event (struct execution_control_state *ecs)
          return;
        }
 
-      break;
+      /* But stop if we're attaching or setting up a remote
+        connection.  */
+      if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
+         || stop_soon == STOP_QUIETLY_REMOTE)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
+         stop_stepping (ecs);
+         return;
+       }
+
+      internal_error (__FILE__, __LINE__,
+                     _("unhandled stop_soon: %d"), (int) stop_soon);
 
     case TARGET_WAITKIND_SPURIOUS:
       if (debug_infrun)