gdb
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index 8bcfd63e1ad153d6ce6090bfc861f5665d6755bd..8060af5ed148a88d7eca179627538691f8ee28f8 100644 (file)
@@ -51,6 +51,7 @@
 #include "exceptions.h"
 #include "cli/cli-decode.h"
 #include "gdbthread.h"
+#include "valprint.h"
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -120,8 +121,6 @@ static int strip_bg_char (char **);
 
 void _initialize_infcmd (void);
 
-#define GO_USAGE   "Usage: go <location>\n"
-
 #define ERROR_NO_INFERIOR \
    if (!target_has_execution) error (_("The program is not being run."));
 
@@ -431,8 +430,6 @@ kill_if_already_running (int from_tty)
 Start it from the beginning? "))
        error (_("Program not restarted."));
       target_kill ();
-      no_shared_libraries (NULL, from_tty);
-      init_wait_for_inferior ();
     }
 }
 
@@ -448,6 +445,8 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
   dont_repeat ();
 
   kill_if_already_running (from_tty);
+
+  init_wait_for_inferior ();
   clear_breakpoint_hit_counts ();
 
   /* Clean up any leftovers from other runs.  Some other things from
@@ -572,10 +571,19 @@ start_command (char *args, int from_tty)
 static int
 proceed_thread_callback (struct thread_info *thread, void *arg)
 {
+  /* We go through all threads individually instead of compressing
+     into a single target `resume_all' request, because some threads
+     may be stopped in internal breakpoints/events, or stopped waiting
+     for its turn in the displaced stepping queue (that is, they are
+     running && !executing).  The target side has no idea about why
+     the thread is stopped, so a `resume_all' command would resume too
+     much.  If/when GDB gains a way to tell the target `hold this
+     thread stopped until I say otherwise', then we can optimize
+     this.  */
   if (!is_stopped (thread->ptid))
     return 0;
 
-  context_switch_to (thread->ptid);
+  switch_to_thread (thread->ptid);
   clear_proceed_status ();
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
   return 0;
@@ -1055,7 +1063,7 @@ static void
 go_command (char *line_no, int from_tty)
 {
   if (line_no == (char *) NULL || !*line_no)
-    printf_filtered (GO_USAGE);
+    printf_filtered (_("Usage: go <location>\n"));
   else
     {
       tbreak_command (line_no, from_tty);
@@ -1284,6 +1292,8 @@ print_return_value (struct type *func_type, struct type *value_type)
 
   if (value)
     {
+      struct value_print_options opts;
+
       /* Print it.  */
       stb = ui_out_stream_new (uiout);
       old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -1291,7 +1301,8 @@ print_return_value (struct type *func_type, struct type *value_type)
       ui_out_field_fmt (uiout, "gdb-result-var", "$%d",
                        record_latest_value (value));
       ui_out_text (uiout, " = ");
-      value_print (value, stb->stream, 0, Val_no_prettyprint);
+      get_raw_print_options (&opts);
+      value_print (value, stb->stream, &opts);
       ui_out_field_stream (uiout, "return-value", stb);
       ui_out_text (uiout, "\n");
       do_cleanups (old_chain);
@@ -1366,19 +1377,109 @@ finish_command_continuation_free_arg (void *arg)
   xfree (arg);
 }
 
+/* finish_backward -- helper function for finish_command.  */
+
+static void
+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 func_addr;
+  int back_up;
+
+  if (find_pc_partial_function (get_frame_pc (get_current_frame ()),
+                               NULL, &func_addr, NULL) == 0)
+    internal_error (__FILE__, __LINE__,
+                   _("Finish: couldn't find function."));
+
+  sal = find_pc_line (func_addr, 0);
+
+  /* We don't need a return value.  */
+  tp->proceed_to_finish = 0;
+  /* 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
+     no good to do so.
+
+     Note that this can only happen at frame #0, since there's
+     no way that a function up the stack can have a return address
+     that's equal to its entry point.  */
+
+  if (sal.pc != read_pc ())
+    {
+      /* Set breakpoint and continue.  */
+      breakpoint =
+       set_momentary_breakpoint (sal,
+                                 get_frame_id (get_selected_frame (NULL)),
+                                 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->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.  */
+      tp->step_range_start = tp->step_range_end = 1;
+      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+    }
+  return;
+}
+
+/* finish_forward -- helper function for finish_command.  */
+
+static void
+finish_forward (struct symbol *function, struct frame_info *frame)
+{
+  struct symtab_and_line sal;
+  struct thread_info *tp = inferior_thread ();
+  struct breakpoint *breakpoint;
+  struct cleanup *old_chain;
+  struct finish_command_continuation_args *cargs;
+
+  sal = find_pc_line (get_frame_pc (frame), 0);
+  sal.pc = get_frame_pc (frame);
+
+  breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame),
+                                         bp_finish);
+
+  old_chain = make_cleanup_delete_breakpoint (breakpoint);
+
+  tp->proceed_to_finish = 1;    /* We want stop_registers, please...  */
+  make_cleanup_restore_integer (&suppress_stop_observer);
+  suppress_stop_observer = 1;
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+
+  cargs = xmalloc (sizeof (*cargs));
+
+  cargs->breakpoint = breakpoint;
+  cargs->function = function;
+  add_continuation (tp, finish_command_continuation, cargs,
+                    finish_command_continuation_free_arg);
+
+  discard_cleanups (old_chain);
+  if (!target_can_async_p ())
+    do_all_continuations ();
+}
+
 /* "finish": Set a temporary breakpoint at the place the selected
    frame will return to, then continue.  */
 
 static void
 finish_command (char *arg, int from_tty)
 {
-  struct symtab_and_line sal;
   struct frame_info *frame;
   struct symbol *function;
-  struct breakpoint *breakpoint;
-  struct cleanup *old_chain;
-  struct finish_command_continuation_args *cargs;
-  struct thread_info *tp;
 
   int async_exec = 0;
 
@@ -1391,6 +1492,10 @@ 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 ())
@@ -1408,17 +1513,8 @@ finish_command (char *arg, int from_tty)
   if (frame == 0)
     error (_("\"finish\" not meaningful in the outermost frame."));
 
-  tp = inferior_thread ();
-
   clear_proceed_status ();
 
-  sal = find_pc_line (get_frame_pc (frame), 0);
-  sal.pc = get_frame_pc (frame);
-
-  breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish);
-
-  old_chain = make_cleanup_delete_breakpoint (breakpoint);
-
   /* Find the function we will return from.  */
 
   function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
@@ -1427,25 +1523,18 @@ finish_command (char *arg, int from_tty)
      source.  */
   if (from_tty)
     {
-      printf_filtered (_("Run till exit from "));
+      if (execution_direction == EXEC_REVERSE)
+       printf_filtered (_("Run back to call of "));
+      else
+       printf_filtered (_("Run till exit from "));
+
       print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
     }
 
-  tp->proceed_to_finish = 1;   /* We want stop_registers, please...  */
-  make_cleanup_restore_integer (&suppress_stop_observer);
-  suppress_stop_observer = 1;
-  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
-
-  cargs = xmalloc (sizeof (*cargs));
-
-  cargs->breakpoint = breakpoint;
-  cargs->function = function;
-  add_continuation (tp, finish_command_continuation, cargs,
-                   finish_command_continuation_free_arg);
-
-  discard_cleanups (old_chain);
-  if (!target_can_async_p ())
-    do_all_continuations ();
+  if (execution_direction == EXEC_REVERSE)
+    finish_backward (function);
+  else
+    finish_forward (function, frame);
 }
 \f
 
@@ -1727,9 +1816,12 @@ default_print_registers_info (struct gdbarch *gdbarch,
          || TYPE_CODE (register_type (gdbarch, i)) == TYPE_CODE_DECFLOAT)
        {
          int j;
+         struct value_print_options opts;
 
+         get_user_print_options (&opts);
+         opts.deref_ref = 1;
          val_print (register_type (gdbarch, i), buffer, 0, 0,
-                    file, 0, 1, 0, Val_pretty_default, current_language);
+                    file, 0, &opts, current_language);
 
          fprintf_filtered (file, "\t(raw 0x");
          for (j = 0; j < register_size (gdbarch, i); j++)
@@ -1745,16 +1837,23 @@ default_print_registers_info (struct gdbarch *gdbarch,
        }
       else
        {
+         struct value_print_options opts;
+
          /* Print the register in hex.  */
+         get_formatted_print_options (&opts, 'x');
+         opts.deref_ref = 1;
          val_print (register_type (gdbarch, i), buffer, 0, 0,
-                    file, 'x', 1, 0, Val_pretty_default, current_language);
+                    file, 0, &opts,
+                    current_language);
           /* If not a vector register, print it also according to its
              natural format.  */
          if (TYPE_VECTOR (register_type (gdbarch, i)) == 0)
            {
+             get_user_print_options (&opts);
+             opts.deref_ref = 1;
              fprintf_filtered (file, "\t");
              val_print (register_type (gdbarch, i), buffer, 0, 0,
-                        file, 0, 1, 0, Val_pretty_default, current_language);
+                        file, 0, &opts, current_language);
            }
        }
 
@@ -1820,12 +1919,14 @@ registers_info (char *addr_exp, int fpregs)
            if (regnum >= gdbarch_num_regs (gdbarch)
                          + gdbarch_num_pseudo_regs (gdbarch))
              {
+               struct value_print_options opts;
                struct value *val = value_of_user_reg (regnum, frame);
 
                printf_filtered ("%s: ", start);
+               get_formatted_print_options (&opts, 'x');
                print_scalar_formatted (value_contents (val),
                                        check_typedef (value_type (val)),
-                                       'x', 0, gdb_stdout);
+                                       &opts, 0, gdb_stdout);
                printf_filtered ("\n");
              }
            else
@@ -1935,6 +2036,48 @@ vector_info (char *args, int from_tty)
 }
 \f
 
+/* Used in `attach&' command.  ARG is a point to an integer
+   representing a process id.  Proceed threads of this process iff
+   they stopped due to debugger request, and when they did, they
+   reported a clean stop (TARGET_SIGNAL_0).  Do not proceed threads
+   that have been explicitly been told to stop.  */
+
+static int
+proceed_after_attach_callback (struct thread_info *thread,
+                              void *arg)
+{
+  int pid = * (int *) arg;
+
+  if (ptid_get_pid (thread->ptid) == pid
+      && !is_exited (thread->ptid)
+      && !is_executing (thread->ptid)
+      && !thread->stop_requested
+      && thread->stop_signal == TARGET_SIGNAL_0)
+    {
+      switch_to_thread (thread->ptid);
+      clear_proceed_status ();
+      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+    }
+
+  return 0;
+}
+
+static void
+proceed_after_attach (int pid)
+{
+  /* Don't error out if the current thread is running, because
+     there may be other stopped threads.  */
+  struct cleanup *old_chain;
+
+  /* Backup current thread and selected frame.  */
+  old_chain = make_cleanup_restore_current_thread ();
+
+  iterate_over_threads (proceed_after_attach_callback, &pid);
+
+  /* Restore selected ptid.  */
+  do_cleanups (old_chain);
+}
+
 /*
  * TODO:
  * Should save/restore the tty state since it might be that the
@@ -1956,8 +2099,10 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
 {
   char *exec_file;
   char *full_exec_path = NULL;
+  struct inferior *inferior;
 
-  stop_soon = NO_STOP_QUIETLY;
+  inferior = current_inferior ();
+  inferior->stop_soon = NO_STOP_QUIETLY;
 
   /* If no exec file is yet known, try to determine it from the
      process itself.  */
@@ -1997,11 +2142,44 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
   target_terminal_inferior ();
 
   if (async_exec)
-    proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+    {
+      /* The user requested an `attach&', so be sure to leave threads
+        that didn't get a signal running.  */
+
+      /* Immediatelly resume all suspended threads of this inferior,
+        and this inferior only.  This should have no effect on
+        already running threads.  If a thread has been stopped with a
+        signal, leave it be.  */
+      if (non_stop)
+       proceed_after_attach (inferior->pid);
+      else
+       {
+         if (inferior_thread ()->stop_signal == TARGET_SIGNAL_0)
+           {
+             clear_proceed_status ();
+             proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+           }
+       }
+    }
   else
     {
+      /* The user requested a plain `attach', so be sure to leave
+        the inferior stopped.  */
+
       if (target_can_async_p ())
        async_enable_stdin ();
+
+      /* At least the current thread is already stopped.  */
+
+      /* In all-stop, by definition, all threads have to be already
+        stopped at this point.  In non-stop, however, although the
+        selected thread is stopped, others may still be executing.
+        Be sure to explicitly stop all threads of the process.  This
+        should have no effect on already stopped threads.  */
+      if (non_stop)
+       target_stop (pid_to_ptid (inferior->pid));
+
+      /* Tell the user/frontend where we're stopped.  */
       normal_stop ();
       if (deprecated_attach_hook)
        deprecated_attach_hook ();
@@ -2039,7 +2217,10 @@ attach_command (char *args, int from_tty)
 
   dont_repeat ();              /* Not for the faint of heart */
 
-  if (target_has_execution)
+  if (target_supports_multi_process ())
+    /* Don't complain if we can be attached to multiple processes.  */
+    ;
+  else if (target_has_execution)
     {
       if (query ("A program is being debugged already.  Kill it? "))
        target_kill ();
@@ -2083,16 +2264,33 @@ attach_command (char *args, int from_tty)
   init_wait_for_inferior ();
   clear_proceed_status ();
 
+  if (non_stop)
+    {
+      /* If we find that the current thread isn't stopped, explicitly
+        do so now, because we're going to install breakpoints and
+        poke at memory.  */
+
+      if (async_exec)
+       /* The user requested an `attach&'; stop just one thread.  */
+       target_stop (inferior_ptid);
+      else
+       /* The user requested an `attach', so stop all threads of this
+          inferior.  */
+       target_stop (pid_to_ptid (ptid_get_pid (inferior_ptid)));
+    }
+
   /* Some system don't generate traps when attaching to inferior.
      E.g. Mach 3 or GNU hurd.  */
   if (!target_attach_no_wait)
     {
+      struct inferior *inferior = current_inferior ();
+
       /* Careful here. See comments in inferior.h.  Basically some
         OSes don't ignore SIGSTOPs on continue requests anymore.  We
         need a way for handle_inferior_event to reset the stop_signal
         variable after an attach, and this is what
         STOP_QUIETLY_NO_SIGSTOP is for.  */
-      stop_soon = STOP_QUIETLY_NO_SIGSTOP;
+      inferior->stop_soon = STOP_QUIETLY_NO_SIGSTOP;
 
       if (target_can_async_p ())
        {
@@ -2132,7 +2330,12 @@ detach_command (char *args, int from_tty)
   dont_repeat ();              /* Not for the faint of heart.  */
   target_detach (args, from_tty);
   no_shared_libraries (NULL, from_tty);
-  init_thread_list ();
+
+  /* If the current target interface claims there's still execution,
+     then don't mess with threads of other processes.  */
+  if (!target_has_execution)
+    init_thread_list ();
+
   if (deprecated_detach_hook)
     deprecated_detach_hook ();
 }
@@ -2165,6 +2368,15 @@ interrupt_target_1 (int all_threads)
   else
     ptid = inferior_ptid;
   target_stop (ptid);
+
+  /* Tag the thread as having been explicitly requested to stop, so
+     other parts of gdb know not to resume this thread automatically,
+     if it was stopped due to an internal event.  Limit this to
+     non-stop mode, as when debugging a multi-threaded application in
+     all-stop mode, we will only get one stop event --- it's undefined
+     which thread will report the event.  */
+  if (non_stop)
+    set_stop_requested (ptid, 1);
 }
 
 /* Stop the execution of the target while running in async mode, in
This page took 0.031291 seconds and 4 git commands to generate.