* write.c (resolve_reloc_expr_symbols): Convert local symbols
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index 5efbf39f965cbee08f5481b59ee97525a3f36838..3e8bf5d18842464edeb867ca6e3ffdfa531cd3ec 100644 (file)
@@ -55,6 +55,8 @@
 #include "valprint.h"
 #include "inline-frame.h"
 #include "tracepoint.h"
+#include "inf-loop.h"
+#include "continuations.h"
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -395,6 +397,8 @@ strip_bg_char (char **args)
 void
 post_create_inferior (struct target_ops *target, int from_tty)
 {
+  volatile struct gdb_exception ex;
+
   /* Be sure we own the terminal in case write operations are performed.  */ 
   target_terminal_ours ();
 
@@ -404,11 +408,22 @@ post_create_inferior (struct target_ops *target, int from_tty)
      don't need to.  */
   target_find_description ();
 
-  /* Now that we know the register layout, retrieve current PC.  */
-  stop_pc = regcache_read_pc (get_current_regcache ());
+  /* Now that we know the register layout, retrieve current PC.  But
+     if the PC is unavailable (e.g., we're opening a core file with
+     missing registers info), ignore it.  */
+  stop_pc = 0;
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      stop_pc = regcache_read_pc (get_current_regcache ());
+    }
+  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+    throw_exception (ex);
 
   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
@@ -416,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,
@@ -483,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 ();
 
@@ -879,23 +900,21 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
     {
       for (; count > 0; count--)
        {
-         struct thread_info *tp;
-
          step_once (skip_subroutines, single_inst, count, thread);
 
-         if (target_has_execution
-             && !ptid_equal (inferior_ptid, null_ptid))
-           tp = inferior_thread ();
+         if (!target_has_execution)
+           break;
          else
-           tp = NULL;
-
-         if (!tp || !tp->control.stop_step || !tp->step_multi)
            {
-             /* If we stopped for some reason that is not stepping
-                there are no further steps to make.  */
-             if (tp)
-               tp->step_multi = 0;
-             break;
+             struct thread_info *tp = inferior_thread ();
+
+             if (!tp->control.stop_step || !tp->step_multi)
+               {
+                 /* If we stopped for some reason that is not stepping
+                    there are no further steps to make.  */
+                 tp->step_multi = 0;
+                 break;
+               }
            }
        }
 
@@ -930,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;
 
@@ -939,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.  */
@@ -950,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);
 }
@@ -986,12 +1007,23 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
          if (!skip_subroutines && !single_inst
              && inline_skipped_frames (inferior_ptid))
            {
+             ptid_t resume_ptid;
+
+             /* Pretend that we've ran.  */
+             resume_ptid = user_visible_resume_ptid (1);
+             set_running (resume_ptid, 1);
+
              step_into_inline_frame (inferior_ptid);
              if (count > 1)
                step_once (skip_subroutines, single_inst, count - 1, thread);
              else
-               /* Pretend that we've stopped.  */
-               normal_stop ();
+               {
+                 /* Pretend that we've stopped.  */
+                 normal_stop ();
+
+                 if (target_can_async_p ())
+                   inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+               }
              return;
            }
 
@@ -1225,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
@@ -1295,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);
@@ -1377,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);
@@ -1384,7 +1430,7 @@ print_return_value (struct type *func_type, struct type *value_type)
   /* FIXME: 2003-09-27: When returning from a nested inferior function
      call, it's possible (with no help from the architecture vector)
      to locate and return/print a "struct return" value.  This is just
-     a more complicated case of what is already being done in in the
+     a more complicated case of what is already being done in the
      inferior function call code.  In fact, when inferior function
      calls are made async, this will likely be made the norm.  */
 
@@ -1437,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))
-    {
-      tp = inferior_thread ();
-      bs = tp->control.stop_bpstat;
-    }
 
-  if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL
-      && a->function != NULL)
+  if (!err)
     {
-      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;
 
-         TRY_CATCH (ex, RETURN_MASK_ALL)
+         value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function));
+         if (!value_type)
+           internal_error (__FILE__, __LINE__,
+                           _("finish_command: function has no target type"));
+
+         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
@@ -1508,11 +1561,8 @@ finish_backward (struct symbol *function)
 {
   struct symtab_and_line sal;
   struct thread_info *tp = inferior_thread ();
-  struct breakpoint *breakpoint;
-  struct cleanup *old_chain;
   CORE_ADDR pc;
   CORE_ADDR func_addr;
-  int back_up;
 
   pc = get_frame_pc (get_current_frame ());
 
@@ -1522,8 +1572,7 @@ finish_backward (struct symbol *function)
 
   sal = find_pc_line (func_addr, 0);
 
-  /* We don't need a return value.  */
-  tp->control.proceed_to_finish = 0;
+  tp->control.proceed_to_finish = 1;
   /* Special case: if we're sitting at the function entry point,
      then all we need to do is take a reverse singlestep.  We
      don't need to set a breakpoint, and indeed it would do us
@@ -1537,33 +1586,25 @@ finish_backward (struct symbol *function)
     {
       struct frame_info *frame = get_selected_frame (NULL);
       struct gdbarch *gdbarch = get_frame_arch (frame);
+      struct symtab_and_line sr_sal;
+
+      /* Set a step-resume at the function's entry point.  Once that's
+        hit, we'll do one more step backwards.  */
+      init_sal (&sr_sal);
+      sr_sal.pc = sal.pc;
+      sr_sal.pspace = get_frame_program_space (frame);
+      insert_step_resume_breakpoint_at_sal (gdbarch,
+                                           sr_sal, null_frame_id);
 
-      /* Set breakpoint and continue.  */
-      breakpoint =
-       set_momentary_breakpoint (gdbarch, sal,
-                                 get_stack_frame_id (frame),
-                                 bp_breakpoint);
-      /* Tell the breakpoint to keep quiet.  We won't be done
-         until we've done another reverse single-step.  */
-      make_breakpoint_silent (breakpoint);
-      old_chain = make_cleanup_delete_breakpoint (breakpoint);
       proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
-      /* We will be stopped when proceed returns.  */
-      back_up = (bpstat_find_breakpoint (tp->control.stop_bpstat, breakpoint)
-                != NULL);
-      do_cleanups (old_chain);
     }
   else
-    back_up = 1;
-  if (back_up)
     {
-      /* If in fact we hit the step-resume breakpoint (and not
-        some other breakpoint), then we're almost there --
-        we just need to back up by one more single-step.  */
+      /* We're almost there -- we just need to back up by one more
+        single-step.  */
       tp->control.step_range_start = tp->control.step_range_end = 1;
       proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
     }
-  return;
 }
 
 /* finish_forward -- helper function for finish_command.  */
@@ -1595,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,
@@ -1603,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
@@ -1631,10 +1673,6 @@ finish_command (char *arg, int from_tty)
   if (async_exec && !target_can_async_p ())
     error (_("Asynchronous execution not supported on this target."));
 
-  /* Don't try to async in reverse.  */
-  if (async_exec && execution_direction == EXEC_REVERSE)
-    error (_("Asynchronous 'finish' not supported in reverse."));
-
   /* If we are not asked to run in the bg, then prepare to run in the
      foreground, synchronously.  */
   if (!async_exec && target_can_async_p ())
@@ -2400,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);
 }
 
@@ -2516,7 +2557,7 @@ attach_command (char *args, int from_tty)
          return;
        }
 
-      wait_for_inferior (0);
+      wait_for_inferior ();
     }
 
   attach_command_post_wait (args, from_tty, async_exec);
@@ -2580,7 +2621,7 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
          return;
        }
       else
-       wait_for_inferior (0);
+       wait_for_inferior ();
     }
 
   async_exec = leave_running;
@@ -2907,7 +2948,7 @@ This command is a combination of tbreak and jump."));
   if (xdb_commands)
     add_com_alias ("g", "go", class_run, 1);
 
-  c = add_com ("continue", class_run, continue_command, _("\
+  add_com ("continue", class_run, continue_command, _("\
 Continue program being debugged, after signal or breakpoint.\n\
 If proceeding from breakpoint, a number N may be used as an argument,\n\
 which means to set the ignore count of that breakpoint to N - 1 (so that\n\
@@ -2941,8 +2982,8 @@ You may specify arguments to give to your program, just as with the\n\
 \"run\" command."));
   set_cmd_completer (c, filename_completer);
 
-  c = add_com ("interrupt", class_run, interrupt_target_command,
-              _("Interrupt the execution of the debugged program.\n\
+  add_com ("interrupt", class_run, interrupt_target_command,
+          _("Interrupt the execution of the debugged program.\n\
 If non-stop mode is enabled, interrupt only the current thread,\n\
 otherwise all the threads in the program are stopped.  To \n\
 interrupt all running threads in non-stop mode, use the -a option."));
This page took 0.0343 seconds and 4 git commands to generate.