2010-02-10 Sterling Augustine <sterling@tensilica.com>
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index a8ab1f0faf5511deed07c5e675287bc1d923adb1..f99a4aed9696e3a636587b4e456974bcd259f677 100644 (file)
@@ -2,7 +2,7 @@
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
    1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008, 2009 Free Software Foundation, Inc.
+   2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -20,6 +20,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "arch-utils.h"
 #include <signal.h>
 #include "gdb_string.h"
 #include "symtab.h"
@@ -52,6 +53,9 @@
 #include "cli/cli-decode.h"
 #include "gdbthread.h"
 #include "valprint.h"
+#include "inline-frame.h"
+
+extern void disconnect_or_stop_tracing (int from_tty);
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -122,20 +126,17 @@ void _initialize_infcmd (void);
 #define ERROR_NO_INFERIOR \
    if (!target_has_execution) error (_("The program is not being run."));
 
-/* String containing arguments to give to the program, separated by spaces.
-   Empty string (pointer to '\0') means no args.  */
-
-static char *inferior_args;
-
-/* The inferior arguments as a vector.  If INFERIOR_ARGC is nonzero,
-   then we must compute INFERIOR_ARGS from this (via the target).  */
+/* Scratch area where string containing arguments to give to the program will be
+   stored by 'set args'.  As soon as anything is stored, notice_args_set will
+   move it into per-inferior storage.  Arguments are separated by spaces. Empty
+   string (pointer to '\0') means no args.  */
 
-static int inferior_argc;
-static char **inferior_argv;
+static char *inferior_args_scratch;
 
-/* File name for default use for standard in/out in the inferior.  */
+/* Scratch area where 'set inferior-tty' will store user-provided value.
+   We'll immediate copy it into per-inferior storage.  */
 
-static char *inferior_io_terminal;
+static char *inferior_io_terminal_scratch;
 
 /* Pid of our debugged inferior, or 0 if no inferior now.
    Since various parts of infrun.c test this to see whether there is a program
@@ -162,80 +163,97 @@ int stop_stack_dummy;
 
 int stopped_by_random_signal;
 
-/* Environment to use for running inferior,
-   in format described in environ.h.  */
-
-struct gdb_environ *inferior_environ;
 \f
 /* Accessor routines. */
 
+/* Set the io terminal for the current inferior.  Ownership of
+   TERMINAL_NAME is not transferred.  */
+
 void 
 set_inferior_io_terminal (const char *terminal_name)
 {
-  if (inferior_io_terminal)
-    xfree (inferior_io_terminal);
-
-  if (!terminal_name)
-    inferior_io_terminal = NULL;
-  else
-    inferior_io_terminal = xstrdup (terminal_name);
+  xfree (current_inferior ()->terminal);
+  current_inferior ()->terminal = terminal_name ? xstrdup (terminal_name) : 0;
 }
 
 const char *
 get_inferior_io_terminal (void)
 {
-  return inferior_io_terminal;
+  return current_inferior ()->terminal;
+}
+
+static void
+set_inferior_tty_command (char *args, int from_tty,
+                         struct cmd_list_element *c)
+{
+  /* CLI has assigned the user-provided value to inferior_io_terminal_scratch.
+     Now route it to current inferior.  */
+  set_inferior_io_terminal (inferior_io_terminal_scratch);
+}
+
+static void
+show_inferior_tty_command (struct ui_file *file, int from_tty,
+                          struct cmd_list_element *c, const char *value)
+{
+  /* Note that we ignore the passed-in value in favor of computing it
+     directly.  */
+  fprintf_filtered (gdb_stdout,
+                   _("argument list to give program being debugged when "
+                     "it is started is %s"),
+                   get_inferior_io_terminal ());
 }
 
 char *
 get_inferior_args (void)
 {
-  if (inferior_argc != 0)
+  if (current_inferior ()->argc != 0)
     {
-      char *n, *old;
+      char *n;
 
-      n = construct_inferior_arguments (inferior_argc, inferior_argv);
-      old = set_inferior_args (n);
-      xfree (old);
+      n = construct_inferior_arguments (current_inferior ()->argc,
+                                       current_inferior ()->argv);
+      set_inferior_args (n);
+      xfree (n);
     }
 
-  if (inferior_args == NULL)
-    inferior_args = xstrdup ("");
+  if (current_inferior ()->args == NULL)
+    current_inferior ()->args = xstrdup ("");
 
-  return inferior_args;
+  return current_inferior ()->args;
 }
 
-char *
+/* Set the arguments for the current inferior.  Ownership of
+   NEWARGS is not transferred.  */
+
+void
 set_inferior_args (char *newargs)
 {
-  char *saved_args = inferior_args;
-
-  inferior_args = newargs;
-  inferior_argc = 0;
-  inferior_argv = 0;
-
-  return saved_args;
+  xfree (current_inferior ()->args);
+  current_inferior ()->args = newargs ? xstrdup (newargs) : NULL;
+  current_inferior ()->argc = 0;
+  current_inferior ()->argv = 0;
 }
 
 void
 set_inferior_args_vector (int argc, char **argv)
 {
-  inferior_argc = argc;
-  inferior_argv = argv;
+  current_inferior ()->argc = argc;
+  current_inferior ()->argv = argv;
 }
 
 /* Notice when `set args' is run.  */
 static void
-notice_args_set (char *args, int from_tty, struct cmd_list_element *c)
+set_args_command (char *args, int from_tty, struct cmd_list_element *c)
 {
-  inferior_argc = 0;
-  inferior_argv = 0;
+  /* CLI has assigned the user-provided value to inferior_args_scratch.
+     Now route it to current inferior.  */
+  set_inferior_args (inferior_args_scratch);
 }
 
 /* Notice when `show args' is run.  */
 static void
-notice_args_read (struct ui_file *file, int from_tty,
-                 struct cmd_list_element *c, const char *value)
+show_args_command (struct ui_file *file, int from_tty,
+                  struct cmd_list_element *c, const char *value)
 {
   /* Note that we ignore the passed-in value in favor of computing it
      directly.  */
@@ -365,15 +383,6 @@ strip_bg_char (char **args)
   return 0;
 }
 
-void
-tty_command (char *file, int from_tty)
-{
-  if (file == 0)
-    error_no_arg (_("terminal name for running target process"));
-
-  set_inferior_io_terminal (file);
-}
-
 /* Common actions to take after creating any sort of inferior, by any
    means (running, attaching, connecting, et cetera).  The target
    should be stopped.  */
@@ -393,22 +402,6 @@ post_create_inferior (struct target_ops *target, int from_tty)
   /* Now that we know the register layout, retrieve current PC.  */
   stop_pc = regcache_read_pc (get_current_regcache ());
 
-  /* 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.  Try to do so first, so
-        that we can add them with the correct value for FROM_TTY.
-        If we made all the inferior hook methods consistent,
-        this call could be removed.  */
-#ifdef SOLIB_ADD
-      SOLIB_ADD (NULL, from_tty, target, auto_solib_add);
-#else
-      solib_add (NULL, from_tty, target, auto_solib_add);
-#endif
-    }
-
   if (exec_bfd)
     {
       /* Create the hooks to handle shared library load and unload
@@ -416,7 +409,25 @@ post_create_inferior (struct target_ops *target, int from_tty)
 #ifdef SOLIB_CREATE_INFERIOR_HOOK
       SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
 #else
-      solib_create_inferior_hook ();
+      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.  */
+
+#ifdef SOLIB_ADD
+      SOLIB_ADD (NULL, 0, target, auto_solib_add);
+#else
+      solib_add (NULL, 0, target, auto_solib_add);
 #endif
     }
 
@@ -530,10 +541,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
 
       /* If there were other args, beside '&', process them. */
       if (args)
-       {
-          char *old_args = set_inferior_args (xstrdup (args));
-          xfree (old_args);
-       }
+       set_inferior_args (args);
     }
 
   if (from_tty)
@@ -553,7 +561,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
   /* We call get_inferior_args() because we might need to compute
      the value now.  */
   target_create_inferior (exec_file, get_inferior_args (),
-                         environ_vector (inferior_environ), from_tty);
+                         environ_vector (current_inferior ()->environment), from_tty);
 
   /* We're starting off a new process.  When we get out of here, in
      non-stop mode, finish the state of all threads of that process,
@@ -588,8 +596,7 @@ run_command (char *args, int from_tty)
 static void
 run_no_args_command (char *args, int from_tty)
 {
-  char *old_args = set_inferior_args (xstrdup (""));
-  xfree (old_args);
+  set_inferior_args ("");
 }
 \f
 
@@ -758,6 +765,17 @@ Can't resume all threads and specify proceed count simultaneously."));
   continue_1 (all_threads);
 }
 \f
+/* Record the starting point of a "step" or "next" command.  */
+
+static void
+set_step_frame (void)
+{
+  struct symtab_and_line sal;
+
+  find_frame_sal (get_current_frame (), &sal);
+  set_step_info (get_current_frame (), sal);
+}
+
 /* Step until outside of current statement.  */
 
 static void
@@ -831,7 +849,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
       if (in_thread_list (inferior_ptid))
        thread = pid_to_thread_id (inferior_ptid);
 
-      set_longjmp_breakpoint ();
+      set_longjmp_breakpoint (thread);
 
       make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
     }
@@ -926,7 +944,7 @@ step_1_continuation (void *args)
 static void
 step_once (int skip_subroutines, int single_inst, int count, int thread)
 {
-  struct frame_info *frame;
+  struct frame_info *frame = get_current_frame ();
 
   if (count > 0)
     {
@@ -936,23 +954,32 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
         THREAD is set.  */
       struct thread_info *tp = inferior_thread ();
       clear_proceed_status ();
-
-      frame = get_current_frame ();
-      tp->step_frame_id = get_frame_id (frame);
+      set_step_frame ();
 
       if (!single_inst)
        {
          CORE_ADDR pc;
 
+         /* Step at an inlined function behaves like "down".  */
+         if (!skip_subroutines && !single_inst
+             && inline_skipped_frames (inferior_ptid))
+           {
+             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 ();
+             return;
+           }
+
          pc = get_frame_pc (frame);
          find_pc_line_pc_range (pc,
                                 &tp->step_range_start, &tp->step_range_end);
 
          /* If we have no line info, switch to stepi mode.  */
          if (tp->step_range_end == 0 && step_stop_if_no_debug)
-           {
-             tp->step_range_start = tp->step_range_end = 1;
-           }
+           tp->step_range_start = tp->step_range_end = 1;
          else if (tp->step_range_end == 0)
            {
              char *name;
@@ -1008,6 +1035,7 @@ which has no line number information.\n"), name);
 static void
 jump_command (char *arg, int from_tty)
 {
+  struct gdbarch *gdbarch = get_current_arch ();
   CORE_ADDR addr;
   struct symtabs_and_lines sals;
   struct symtab_and_line sal;
@@ -1077,7 +1105,7 @@ jump_command (char *arg, int from_tty)
   if (from_tty)
     {
       printf_filtered (_("Continuing at "));
-      fputs_filtered (paddress (addr), gdb_stdout);
+      fputs_filtered (paddress (gdbarch, addr), gdb_stdout);
       printf_filtered (".\n");
     }
 
@@ -1188,6 +1216,7 @@ until_next_command (int from_tty)
   struct thread_info *tp = inferior_thread ();
 
   clear_proceed_status ();
+  set_step_frame ();
 
   frame = get_current_frame ();
 
@@ -1217,7 +1246,6 @@ until_next_command (int from_tty)
     }
 
   tp->step_over_calls = STEP_OVER_ALL;
-  tp->step_frame_id = get_frame_id (frame);
 
   tp->step_multi = 0;          /* Only one call to proceed */
 
@@ -1440,10 +1468,13 @@ finish_backward (struct symbol *function)
 
   if (sal.pc != pc)
     {
+      struct frame_info *frame = get_selected_frame (NULL);
+      struct gdbarch *gdbarch = get_frame_arch (frame);
+
       /* Set breakpoint and continue.  */
       breakpoint =
-       set_momentary_breakpoint (sal,
-                                 get_frame_id (get_selected_frame (NULL)),
+       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.  */
@@ -1472,6 +1503,7 @@ finish_backward (struct symbol *function)
 static void
 finish_forward (struct symbol *function, struct frame_info *frame)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   struct symtab_and_line sal;
   struct thread_info *tp = inferior_thread ();
   struct breakpoint *breakpoint;
@@ -1481,20 +1513,20 @@ finish_forward (struct symbol *function, struct frame_info *frame)
   sal = find_pc_line (get_frame_pc (frame), 0);
   sal.pc = get_frame_pc (frame);
 
-  breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame),
+  breakpoint = set_momentary_breakpoint (gdbarch, sal,
+                                        get_stack_frame_id (frame),
                                          bp_finish);
 
   old_chain = make_cleanup_delete_breakpoint (breakpoint);
 
   tp->proceed_to_finish = 1;    /* We want stop_registers, please...  */
-  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);
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
 
   discard_cleanups (old_chain);
   if (!target_can_async_p ())
@@ -1544,6 +1576,36 @@ finish_command (char *arg, int from_tty)
 
   clear_proceed_status ();
 
+  /* Finishing from an inline frame is completely different.  We don't
+     try to show the "return value" - no way to locate it.  So we do
+     not need a completion.  */
+  if (get_frame_type (get_selected_frame (_("No selected frame.")))
+      == INLINE_FRAME)
+    {
+      /* Claim we are stepping in the calling frame.  An empty step
+        range means that we will stop once we aren't in a function
+        called by that frame.  We don't use the magic "1" value for
+        step_range_end, because then infrun will think this is nexti,
+        and not step over the rest of this inlined function call.  */
+      struct thread_info *tp = inferior_thread ();
+      struct symtab_and_line empty_sal;
+      init_sal (&empty_sal);
+      set_step_info (frame, empty_sal);
+      tp->step_range_start = tp->step_range_end = get_frame_pc (frame);
+      tp->step_over_calls = STEP_OVER_ALL;
+
+      /* Print info on the selected frame, including level number but not
+        source.  */
+      if (from_tty)
+       {
+         printf_filtered (_("Run till exit from "));
+         print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
+       }
+
+      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+      return;
+    }
+
   /* Find the function we will return from.  */
 
   function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
@@ -1599,7 +1661,8 @@ program_info (char *args, int from_tty)
   stat = bpstat_num (&bs, &num);
 
   target_files_info ();
-  printf_filtered (_("Program stopped at %s.\n"), paddress (stop_pc));
+  printf_filtered (_("Program stopped at %s.\n"),
+                  paddress (target_gdbarch, stop_pc));
   if (tp->stop_step)
     printf_filtered (_("It stopped after being stepped.\n"));
   else if (stat != 0)
@@ -1637,7 +1700,7 @@ environment_info (char *var, int from_tty)
 {
   if (var)
     {
-      char *val = get_in_environ (inferior_environ, var);
+      char *val = get_in_environ (current_inferior ()->environment, var);
       if (val)
        {
          puts_filtered (var);
@@ -1654,7 +1717,7 @@ environment_info (char *var, int from_tty)
     }
   else
     {
-      char **vector = environ_vector (inferior_environ);
+      char **vector = environ_vector (current_inferior ()->environment);
       while (*vector)
        {
          puts_filtered (*vector++);
@@ -1719,10 +1782,10 @@ set_environment_command (char *arg, int from_tty)
       printf_filtered (_("\
 Setting environment variable \"%s\" to null value.\n"),
                       var);
-      set_in_environ (inferior_environ, var, "");
+      set_in_environ (current_inferior ()->environment, var, "");
     }
   else
-    set_in_environ (inferior_environ, var, val);
+    set_in_environ (current_inferior ()->environment, var, val);
   xfree (var);
 }
 
@@ -1735,12 +1798,12 @@ unset_environment_command (char *var, int from_tty)
          Ask for confirmation if reading from the terminal.  */
       if (!from_tty || query (_("Delete all environment variables? ")))
        {
-         free_environ (inferior_environ);
-         inferior_environ = make_environ ();
+         free_environ (current_inferior ()->environment);
+         current_inferior ()->environment = make_environ ();
        }
     }
   else
-    unset_in_environ (inferior_environ, var);
+    unset_in_environ (current_inferior ()->environment, var);
 }
 
 /* Handle the execution path (PATH variable) */
@@ -1751,7 +1814,7 @@ static void
 path_info (char *args, int from_tty)
 {
   puts_filtered ("Executable and object file path: ");
-  puts_filtered (get_in_environ (inferior_environ, path_var_name));
+  puts_filtered (get_in_environ (current_inferior ()->environment, path_var_name));
   puts_filtered ("\n");
 }
 
@@ -1763,13 +1826,13 @@ path_command (char *dirname, int from_tty)
   char *exec_path;
   char *env;
   dont_repeat ();
-  env = get_in_environ (inferior_environ, path_var_name);
+  env = get_in_environ (current_inferior ()->environment, path_var_name);
   /* Can be null if path is not set */
   if (!env)
     env = "";
   exec_path = xstrdup (env);
   mod_path (dirname, &exec_path);
-  set_in_environ (inferior_environ, path_var_name, exec_path);
+  set_in_environ (current_inferior ()->environment, path_var_name, exec_path);
   xfree (exec_path);
   if (from_tty)
     path_info ((char *) NULL, from_tty);
@@ -2447,6 +2510,8 @@ detach_command (char *args, int from_tty)
   if (ptid_equal (inferior_ptid, null_ptid))
     error (_("The program is not being run."));
 
+  disconnect_or_stop_tracing (from_tty);
+
   target_detach (args, from_tty);
 
   /* If the solist is global across inferiors, don't clear it when we
@@ -2582,19 +2647,22 @@ _initialize_infcmd (void)
 
   /* add the filename of the terminal connected to inferior I/O */
   add_setshow_filename_cmd ("inferior-tty", class_run,
-                           &inferior_io_terminal, _("\
+                           &inferior_io_terminal_scratch, _("\
 Set terminal for future runs of program being debugged."), _("\
 Show terminal for future runs of program being debugged."), _("\
-Usage: set inferior-tty /dev/pts/1"), NULL, NULL, &setlist, &showlist);
+Usage: set inferior-tty /dev/pts/1"),
+                           set_inferior_tty_command,
+                           show_inferior_tty_command,
+                           &setlist, &showlist);
   add_com_alias ("tty", "set inferior-tty", class_alias, 0);
 
   add_setshow_optional_filename_cmd ("args", class_run,
-                                    &inferior_args, _("\
+                                    &inferior_args_scratch, _("\
 Set argument list to give program being debugged when it is started."), _("\
 Show argument list to give program being debugged when it is started."), _("\
 Follow this command with any number of args, to be passed to the program."),
-                                    notice_args_set,
-                                    notice_args_read,
+                                    set_args_command,
+                                    show_args_command,
                                     &setlist, &showlist);
 
   c = add_cmd ("environment", no_class, environment_info, _("\
@@ -2639,8 +2707,9 @@ fully linked executable files and separately compiled object files as needed."),
               &showlist);
   set_cmd_completer (c, noop_completer);
 
-  add_com ("kill", class_run, kill_command,
-          _("Kill execution of program being debugged."));
+  add_prefix_cmd ("kill", class_run, kill_command,
+                 _("Kill execution of program being debugged."),
+                 &killlist, "kill ", 0, &cmdlist);
 
   add_com ("attach", class_run, attach_command, _("\
 Attach to a process or file outside of GDB.\n\
@@ -2790,7 +2859,4 @@ Register name as argument means describe only that register."));
 
   add_info ("vector", vector_info,
            _("Print the status of the vector unit\n"));
-
-  inferior_environ = make_environ ();
-  init_environ (inferior_environ);
 }
This page took 0.031819 seconds and 4 git commands to generate.