2011-09-02 Pedro Alves <pedro@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index f499e3e64bf44b5b48275b31f9c6c40fa54ff4f5..3e8bf5d18842464edeb867ca6e3ffdfa531cd3ec 100644 (file)
@@ -421,6 +421,9 @@ post_create_inferior (struct target_ops *target, int from_tty)
 
   if (exec_bfd)
     {
+      const unsigned solib_add_generation
+       = current_program_space->solib_add_generation;
+
       /* Create the hooks to handle shared library load and unload
         events.  */
 #ifdef SOLIB_CREATE_INFERIOR_HOOK
@@ -428,24 +431,29 @@ post_create_inferior (struct target_ops *target, int from_tty)
 #else
       solib_create_inferior_hook (from_tty);
 #endif
-    }
-
-  /* If the solist is global across processes, there's no need to
-     refetch it here.  */
-  if (exec_bfd && !gdbarch_has_global_solist (target_gdbarch))
-    {
-      /* Sometimes the platform-specific hook loads initial shared
-        libraries, and sometimes it doesn't.  If it doesn't FROM_TTY will be
-        incorrectly 0 but such solib targets should be fixed anyway.  If we
-        made all the inferior hook methods consistent, this call could be
-        removed.  Call it only after the solib target has been initialized by
-        solib_create_inferior_hook.  */
 
+      if (current_program_space->solib_add_generation == solib_add_generation)
+       {
+         /* The platform-specific hook should load initial shared libraries,
+            but didn't.  FROM_TTY will be incorrectly 0 but such solib
+            targets should be fixed anyway.  Call it only after the solib
+            target has been initialized by solib_create_inferior_hook.  */
+
+         if (info_verbose)
+           warning (_("platform-specific solib_create_inferior_hook did "
+                      "not load initial shared libraries."));
+
+         /* If the solist is global across processes, there's no need to
+            refetch it here.  */
+         if (!gdbarch_has_global_solist (target_gdbarch))
+           {
 #ifdef SOLIB_ADD
-      SOLIB_ADD (NULL, 0, target, auto_solib_add);
+             SOLIB_ADD (NULL, 0, target, auto_solib_add);
 #else
-      solib_add (NULL, 0, target, auto_solib_add);
+             solib_add (NULL, 0, target, auto_solib_add);
 #endif
+           }
+       }
     }
 
   /* If the user sets watchpoints before execution having started,
@@ -495,6 +503,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
   char *exec_file;
   struct cleanup *old_chain;
   ptid_t ptid;
+  struct ui_out *uiout = current_uiout;
 
   dont_repeat ();
 
@@ -940,7 +949,7 @@ struct step_1_continuation_args
    proceed(), via step_once().  Basically it is like step_once and
    step_1_continuation are co-recursive.  */
 static void
-step_1_continuation (void *args)
+step_1_continuation (void *args, int err)
 {
   struct step_1_continuation_args *a = args;
 
@@ -949,7 +958,8 @@ step_1_continuation (void *args)
       struct thread_info *tp;
 
       tp = inferior_thread ();
-      if (tp->step_multi && tp->control.stop_step)
+      if (!err
+         && tp->step_multi && tp->control.stop_step)
        {
          /* There are more steps to make, and we did stop due to
             ending a stepping range.  Do another step.  */
@@ -960,8 +970,9 @@ step_1_continuation (void *args)
       tp->step_multi = 0;
     }
 
-  /* We either stopped for some reason that is not stepping, or there
-     are no further steps to make.  Cleanup.  */
+  /* We either hit an error, or stopped for some reason that is
+     not stepping, or there are no further steps to make.
+     Cleanup.  */
   if (!a->single_inst || a->skip_subroutines)
     delete_longjmp_breakpoint (a->thread);
 }
@@ -1246,14 +1257,22 @@ signal_command (char *signum_exp, int from_tty)
   proceed ((CORE_ADDR) -1, oursig, 0);
 }
 
+/* Continuation args to be passed to the "until" command
+   continuation.  */
+struct until_next_continuation_args
+{
+  /* The thread that was current when the command was executed.  */
+  int thread;
+};
+
 /* A continuation callback for until_next_command.  */
 
 static void
-until_next_continuation (void *arg)
+until_next_continuation (void *arg, int err)
 {
-  struct thread_info *tp = arg;
+  struct until_next_continuation_args *a = arg;
 
-  delete_longjmp_breakpoint (tp->num);
+  delete_longjmp_breakpoint (a->thread);
 }
 
 /* Proceed until we reach a different source line with pc greater than
@@ -1316,8 +1335,13 @@ until_next_command (int from_tty)
 
   if (target_can_async_p () && is_running (inferior_ptid))
     {
+      struct until_next_continuation_args *cont_args;
+
       discard_cleanups (old_chain);
-      add_continuation (tp, until_next_continuation, tp, NULL);
+      cont_args = XNEW (struct until_next_continuation_args);
+      cont_args->thread = inferior_thread ()->num;
+
+      add_continuation (tp, until_next_continuation, cont_args, xfree);
     }
   else
     do_cleanups (old_chain);
@@ -1398,6 +1422,7 @@ print_return_value (struct type *func_type, struct type *value_type)
   struct cleanup *old_chain;
   struct ui_stream *stb;
   struct value *value;
+  struct ui_out *uiout = current_uiout;
 
   CHECK_TYPEDEF (value_type);
   gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID);
@@ -1458,62 +1483,69 @@ print_return_value (struct type *func_type, struct type *value_type)
    impossible to do all the stuff as part of the finish_command
    function itself.  The only chance we have to complete this command
    is in fetch_inferior_event, which is called by the event loop as
-   soon as it detects that the target has stopped.  This function is
-   called via the cmd_continuation pointer.  */
+   soon as it detects that the target has stopped.  */
 
 struct finish_command_continuation_args
 {
+  /* The thread that as current when the command was executed.  */
+  int thread;
   struct breakpoint *breakpoint;
   struct symbol *function;
 };
 
 static void
-finish_command_continuation (void *arg)
+finish_command_continuation (void *arg, int err)
 {
   struct finish_command_continuation_args *a = arg;
-  struct thread_info *tp = NULL;
-  bpstat bs = NULL;
 
-  if (!ptid_equal (inferior_ptid, null_ptid)
-      && target_has_execution
-      && is_stopped (inferior_ptid))
+  if (!err)
     {
-      tp = inferior_thread ();
-      bs = tp->control.stop_bpstat;
-    }
-
-  if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL
-      && a->function != NULL)
-    {
-      struct type *value_type;
+      struct thread_info *tp = NULL;
+      bpstat bs = NULL;
 
-      value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function));
-      if (!value_type)
-       internal_error (__FILE__, __LINE__,
-                       _("finish_command: function has no target type"));
+      if (!ptid_equal (inferior_ptid, null_ptid)
+         && target_has_execution
+         && is_stopped (inferior_ptid))
+       {
+         tp = inferior_thread ();
+         bs = tp->control.stop_bpstat;
+       }
 
-      if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
+      if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL
+         && a->function != NULL)
        {
-         volatile struct gdb_exception ex;
+         struct type *value_type;
+
+         value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function));
+         if (!value_type)
+           internal_error (__FILE__, __LINE__,
+                           _("finish_command: function has no target type"));
 
-         TRY_CATCH (ex, RETURN_MASK_ALL)
+         if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
            {
-             /* print_return_value can throw an exception in some
-                circumstances.  We need to catch this so that we still
-                delete the breakpoint.  */
-             print_return_value (SYMBOL_TYPE (a->function), value_type);
+             volatile struct gdb_exception ex;
+
+             TRY_CATCH (ex, RETURN_MASK_ALL)
+               {
+                 /* print_return_value can throw an exception in some
+                    circumstances.  We need to catch this so that we still
+                    delete the breakpoint.  */
+                 print_return_value (SYMBOL_TYPE (a->function), value_type);
+               }
+             if (ex.reason < 0)
+               exception_print (gdb_stdout, ex);
            }
-         if (ex.reason < 0)
-           exception_print (gdb_stdout, ex);
        }
+
+      /* We suppress normal call of normal_stop observer and do it
+        here so that the *stopped notification includes the return
+        value.  */
+      if (bs != NULL && tp->control.proceed_to_finish)
+       observer_notify_normal_stop (bs, 1 /* print frame */);
     }
 
-  /* We suppress normal call of normal_stop observer and do it here so
-     that the *stopped notification includes the return value.  */
-  if (bs != NULL && tp->control.proceed_to_finish)
-    observer_notify_normal_stop (bs, 1 /* print frame */);
   delete_breakpoint (a->breakpoint);
-  delete_longjmp_breakpoint (inferior_thread ()->num);
+  delete_longjmp_breakpoint (a->thread);
 }
 
 static void
@@ -1604,6 +1636,7 @@ finish_forward (struct symbol *function, struct frame_info *frame)
   tp->control.proceed_to_finish = 1;
   cargs = xmalloc (sizeof (*cargs));
 
+  cargs->thread = thread;
   cargs->breakpoint = breakpoint;
   cargs->function = function;
   add_continuation (tp, finish_command_continuation, cargs,
@@ -1612,7 +1645,7 @@ finish_forward (struct symbol *function, struct frame_info *frame)
 
   discard_cleanups (old_chain);
   if (!target_can_async_p ())
-    do_all_continuations ();
+    do_all_continuations (0);
 }
 
 /* "finish": Set a temporary breakpoint at the place the selected
@@ -2405,10 +2438,13 @@ struct attach_command_continuation_args
 };
 
 static void
-attach_command_continuation (void *args)
+attach_command_continuation (void *args, int err)
 {
   struct attach_command_continuation_args *a = args;
 
+  if (err)
+    return;
+
   attach_command_post_wait (a->args, a->from_tty, a->async_exec);
 }
 
This page took 0.027027 seconds and 4 git commands to generate.