*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / infcmd.c
index 807db8054cde9fe9e25c7b322927714a0b14f88b..59602e04655cf3640296df3225227eaf55d3b66f 100644 (file)
@@ -1,7 +1,7 @@
 /* Memory-access and commands for "inferior" process, for GDB.
 
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -18,8 +18,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include <signal.h>
 #include "regcache.h"
 #include "reggroups.h"
 #include "block.h"
+#include "solib.h"
 #include <ctype.h>
 #include "gdb_assert.h"
+#include "observer.h"
+#include "target-descriptions.h"
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -135,7 +138,7 @@ static char **inferior_argv;
 
 /* File name for default use for standard in/out in the inferior.  */
 
-char *inferior_io_terminal;
+static char *inferior_io_terminal;
 
 /* 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
@@ -198,10 +201,28 @@ int step_multi;
 /* Environment to use for running inferior,
    in format described in environ.h.  */
 
-struct environ *inferior_environ;
+struct gdb_environ *inferior_environ;
 \f
 /* Accessor routines. */
 
+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 = savestring (terminal_name, strlen (terminal_name));
+}
+
+const char *
+get_inferior_io_terminal (void)
+{
+  return inferior_io_terminal;
+}
+
 char *
 get_inferior_args (void)
 {
@@ -250,8 +271,10 @@ notice_args_set (char *args, int from_tty, struct cmd_list_element *c)
 
 /* Notice when `show args' is run.  */
 static void
-notice_args_read (char *args, int from_tty, struct cmd_list_element *c)
+notice_args_read (struct ui_file *file, int from_tty,
+                 struct cmd_list_element *c, const char *value)
 {
+  deprecated_show_value_hack (file, from_tty, c, value);
   /* Might compute the value.  */
   get_inferior_args ();
 }
@@ -373,7 +396,50 @@ tty_command (char *file, int from_tty)
   if (file == 0)
     error_no_arg (_("terminal name for running target process"));
 
-  inferior_io_terminal = savestring (file, strlen (file));
+  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.  */
+
+void
+post_create_inferior (struct target_ops *target, int from_tty)
+{
+  /* Be sure we own the terminal in case write operations are performed.  */ 
+  target_terminal_ours ();
+
+  /* If the target hasn't taken care of this already, do it now.
+     Targets which need to access registers during to_open,
+     to_create_inferior, or to_attach should do it earlier; but many
+     don't need to.  */
+  target_find_description ();
+
+  if (exec_bfd)
+    {
+      /* 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.  */
+#ifdef SOLIB_ADD
+      SOLIB_ADD (NULL, from_tty, target, auto_solib_add);
+#else
+      solib_add (NULL, from_tty, target, auto_solib_add);
+#endif
+
+      /* Create the hooks to handle shared library load and unload
+        events.  */
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+      SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
+#else
+      solib_create_inferior_hook ();
+#endif
+
+      /* Enable any breakpoints which were disabled when the
+        underlying shared library was deleted.  */
+      re_enable_breakpoints_in_shlibs ();
+    }
+
+  observer_notify_inferior_created (target, from_tty);
 }
 
 /* Kill the inferior if already running.  This function is designed
@@ -398,8 +464,12 @@ Start it from the beginning? "))
     }
 }
 
+/* Implement the "run" command. If TBREAK_AT_MAIN is set, then insert
+   a temporary breakpoint at the begining of the main program before
+   running the program.  */
+
 static void
-run_command (char *args, int from_tty)
+run_command_1 (char *args, int from_tty, int tbreak_at_main)
 {
   char *exec_file;
 
@@ -408,6 +478,10 @@ run_command (char *args, int from_tty)
   kill_if_already_running (from_tty);
   clear_breakpoint_hit_counts ();
 
+  /* Clean up any leftovers from other runs.  Some other things from
+     this function should probably be moved into target_pre_inferior.  */
+  target_pre_inferior (from_tty);
+
   /* Purge old solib objfiles. */
   objfile_purge_solibs ();
 
@@ -423,6 +497,10 @@ run_command (char *args, int from_tty)
   reopen_exec_file ();
   reread_symbols ();
 
+  /* Insert the temporary breakpoint if a location was specified.  */
+  if (tbreak_at_main)
+    tbreak_command (main_name (), 0);
+
   exec_file = (char *) get_exec_file (0);
 
   /* We keep symbols from add-symbol-file, on the grounds that the
@@ -481,9 +559,20 @@ run_command (char *args, int from_tty)
      the value now.  */
   target_create_inferior (exec_file, get_inferior_args (),
                          environ_vector (inferior_environ), from_tty);
+
+  post_create_inferior (&current_target, from_tty);
+
+  /* Start the target running.  */
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
 }
 
 
+static void
+run_command (char *args, int from_tty)
+{
+  run_command_1 (args, from_tty, 0);
+}
+
 static void
 run_no_args_command (char *args, int from_tty)
 {
@@ -504,15 +593,8 @@ start_command (char *args, int from_tty)
   if (!have_minimal_symbols ())
     error (_("No symbol table loaded.  Use the \"file\" command."));
 
-  /* If the inferior is already running, we want to ask the user if we
-     should restart it or not before we insert the temporary breakpoint.
-     This makes sure that this command doesn't have any side effect if
-     the user changes its mind.  */
-  kill_if_already_running (from_tty);
-
-  /* Insert the temporary breakpoint, and run...  */
-  tbreak_command (main_name (), 0);
-  run_command (args, from_tty);
+  /* Run the program until reaching the main procedure...  */
+  run_command_1 (args, from_tty, 1);
 } 
 
 void
@@ -543,23 +625,27 @@ continue_command (char *proc_count_exp, int from_tty)
   if (proc_count_exp != NULL)
     {
       bpstat bs = stop_bpstat;
-      int num = bpstat_num (&bs);
-      if (num == 0 && from_tty)
+      int num, stat;
+      int stopped = 0;
+
+      while ((stat = bpstat_num (&bs, &num)) != 0)
+       if (stat > 0)
+         {
+           set_ignore_count (num,
+                             parse_and_eval_long (proc_count_exp) - 1,
+                             from_tty);
+           /* set_ignore_count prints a message ending with a period.
+              So print two spaces before "Continuing.".  */
+           if (from_tty)
+             printf_filtered ("  ");
+           stopped = 1;
+         }
+
+      if (!stopped && from_tty)
        {
          printf_filtered
            ("Not stopped at any breakpoint; argument ignored.\n");
        }
-      while (num != 0)
-       {
-         set_ignore_count (num,
-                           parse_and_eval_long (proc_count_exp) - 1,
-                           from_tty);
-         /* set_ignore_count prints a message ending with a period.
-            So print two spaces before "Continuing.".  */
-         if (from_tty)
-           printf_filtered ("  ");
-         num = bpstat_num (&bs);
-       }
     }
 
   if (from_tty)
@@ -1083,6 +1169,7 @@ print_return_value (int struct_return, struct type *value_type)
   struct ui_stream *stb;
   struct value *value;
 
+  CHECK_TYPEDEF (value_type);
   gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID);
 
   /* FIXME: 2003-09-27: When returning from a nested inferior function
@@ -1096,8 +1183,8 @@ print_return_value (int struct_return, struct type *value_type)
     {
     case RETURN_VALUE_REGISTER_CONVENTION:
     case RETURN_VALUE_ABI_RETURNS_ADDRESS:
+    case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
       value = allocate_value (value_type);
-      CHECK_TYPEDEF (value_type);
       gdbarch_return_value (current_gdbarch, value_type, stop_registers,
                            value_contents_raw (value), NULL);
       break;
@@ -1215,10 +1302,8 @@ finish_command (char *arg, int from_tty)
     error (_("The \"finish\" command does not take any arguments."));
   if (!target_has_execution)
     error (_("The program is not running."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
 
-  frame = get_prev_frame (deprecated_selected_frame);
+  frame = get_prev_frame (get_selected_frame (_("No selected frame.")));
   if (frame == 0)
     error (_("\"finish\" not meaningful in the outermost frame."));
 
@@ -1236,7 +1321,7 @@ finish_command (char *arg, int from_tty)
 
   /* Find the function we will return from.  */
 
-  function = find_pc_function (get_frame_pc (deprecated_selected_frame));
+  function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
 
   /* Print info on the selected frame, including level number but not
      source.  */
@@ -1308,7 +1393,8 @@ static void
 program_info (char *args, int from_tty)
 {
   bpstat bs = stop_bpstat;
-  int num = bpstat_num (&bs);
+  int num;
+  int stat = bpstat_num (&bs, &num);
 
   if (!target_has_execution)
     {
@@ -1321,20 +1407,20 @@ program_info (char *args, int from_tty)
                   hex_string ((unsigned long) stop_pc));
   if (stop_step)
     printf_filtered (_("It stopped after being stepped.\n"));
-  else if (num != 0)
+  else if (stat != 0)
     {
       /* There may be several breakpoints in the same place, so this
          isn't as strange as it seems.  */
-      while (num != 0)
+      while (stat != 0)
        {
-         if (num < 0)
+         if (stat < 0)
            {
              printf_filtered (_("\
 It stopped at a breakpoint that has since been deleted.\n"));
            }
          else
            printf_filtered (_("It stopped at breakpoint %d.\n"), num);
-         num = bpstat_num (&bs);
+         stat = bpstat_num (&bs, &num);
        }
     }
   else if (stop_signal != TARGET_SIGNAL_0)
@@ -1513,8 +1599,9 @@ default_print_registers_info (struct gdbarch *gdbarch,
                              int regnum, int print_all)
 {
   int i;
-  const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
-  char buffer[MAX_REGISTER_SIZE];
+  const int numregs = gdbarch_num_regs (current_gdbarch)
+                     + gdbarch_num_pseudo_regs (current_gdbarch);
+  gdb_byte buffer[MAX_REGISTER_SIZE];
 
   for (i = 0; i < numregs; i++)
     {
@@ -1541,11 +1628,13 @@ default_print_registers_info (struct gdbarch *gdbarch,
 
       /* If the register name is empty, it is undefined for this
          processor, so don't display anything.  */
-      if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+      if (gdbarch_register_name (current_gdbarch, i) == NULL
+         || *(gdbarch_register_name (current_gdbarch, i)) == '\0')
        continue;
 
-      fputs_filtered (REGISTER_NAME (i), file);
-      print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), file);
+      fputs_filtered (gdbarch_register_name (current_gdbarch, i), file);
+      print_spaces_filtered (15 - strlen (gdbarch_register_name
+                                         (current_gdbarch, i)), file);
 
       /* Get the data in raw format.  */
       if (! frame_register_read (frame, i, buffer))
@@ -1567,7 +1656,7 @@ default_print_registers_info (struct gdbarch *gdbarch,
          for (j = 0; j < register_size (current_gdbarch, i); j++)
            {
              int idx;
-             if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+             if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
                idx = j;
              else
                idx = register_size (current_gdbarch, i) - 1 - j;
@@ -1597,18 +1686,18 @@ default_print_registers_info (struct gdbarch *gdbarch,
 void
 registers_info (char *addr_exp, int fpregs)
 {
+  struct frame_info *frame;
   int regnum, numregs;
   char *end;
 
   if (!target_has_registers)
     error (_("The program has no registers now."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
+  frame = get_selected_frame (NULL);
 
   if (!addr_exp)
     {
       gdbarch_print_registers_info (current_gdbarch, gdb_stdout,
-                                   deprecated_selected_frame, -1, fpregs);
+                                   frame, -1, fpregs);
       return;
     }
 
@@ -1641,12 +1730,12 @@ registers_info (char *addr_exp, int fpregs)
 
       /* A register name?  */
       {
-       int regnum = frame_map_name_to_regnum (deprecated_selected_frame,
+       int regnum = frame_map_name_to_regnum (frame,
                                               start, end - start);
        if (regnum >= 0)
          {
            gdbarch_print_registers_info (current_gdbarch, gdb_stdout,
-                                         deprecated_selected_frame, regnum, fpregs);
+                                         frame, regnum, fpregs);
            continue;
          }
       }
@@ -1657,10 +1746,11 @@ registers_info (char *addr_exp, int fpregs)
        int regnum = strtol (start, &endptr, 0);
        if (endptr == end
            && regnum >= 0
-           && regnum < NUM_REGS + NUM_PSEUDO_REGS)
+           && regnum < gdbarch_num_regs (current_gdbarch)
+                       + gdbarch_num_pseudo_regs (current_gdbarch))
          {
            gdbarch_print_registers_info (current_gdbarch, gdb_stdout,
-                                         deprecated_selected_frame, regnum, fpregs);
+                                         frame, regnum, fpregs);
            continue;
          }
       }
@@ -1681,12 +1771,15 @@ registers_info (char *addr_exp, int fpregs)
        if (group != NULL)
          {
            int regnum;
-           for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
+           for (regnum = 0;
+                regnum < gdbarch_num_regs (current_gdbarch)
+                         + gdbarch_num_pseudo_regs (current_gdbarch);
+                regnum++)
              {
                if (gdbarch_register_reggroup_p (current_gdbarch, regnum,
                                                 group))
                  gdbarch_print_registers_info (current_gdbarch,
-                                               gdb_stdout, deprecated_selected_frame,
+                                               gdb_stdout, frame,
                                                regnum, fpregs);
              }
            continue;
@@ -1714,11 +1807,6 @@ static void
 print_vector_info (struct gdbarch *gdbarch, struct ui_file *file,
                   struct frame_info *frame, const char *args)
 {
-  if (!target_has_registers)
-    error (_("The program has no registers now."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
-
   if (gdbarch_print_vector_info_p (gdbarch))
     gdbarch_print_vector_info (gdbarch, file, frame, args);
   else
@@ -1726,7 +1814,10 @@ print_vector_info (struct gdbarch *gdbarch, struct ui_file *file,
       int regnum;
       int printed_something = 0;
 
-      for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
+      for (regnum = 0;
+          regnum < gdbarch_num_regs (current_gdbarch)
+                   + gdbarch_num_pseudo_regs (current_gdbarch);
+          regnum++)
        {
          if (gdbarch_register_reggroup_p (gdbarch, regnum, vector_reggroup))
            {
@@ -1742,7 +1833,11 @@ print_vector_info (struct gdbarch *gdbarch, struct ui_file *file,
 static void
 vector_info (char *args, int from_tty)
 {
-  print_vector_info (current_gdbarch, gdb_stdout, deprecated_selected_frame, args);
+  if (!target_has_registers)
+    error (_("The program has no registers now."));
+
+  print_vector_info (current_gdbarch, gdb_stdout,
+                    get_selected_frame (NULL), args);
 }
 \f
 
@@ -1778,10 +1873,14 @@ attach_command (char *args, int from_tty)
        error (_("Not killed."));
     }
 
+  /* Clean up any leftovers from other runs.  Some other things from
+     this function should probably be moved into target_pre_inferior.  */
+  target_pre_inferior (from_tty);
+
   /* Clear out solib state. Otherwise the solib state of the previous
      inferior might have survived and is entirely wrong for the new
-     target.  This has been observed on Linux using glibc 2.3. How to
-     reproduce:
+     target.  This has been observed on GNU/Linux using glibc 2.3. How
+     to reproduce:
 
      bash$ ./foo&
      [1] 4711
@@ -1796,6 +1895,8 @@ attach_command (char *args, int from_tty)
   */
 #ifdef CLEAR_SOLIB
       CLEAR_SOLIB ();
+#else
+      clear_solib ();
 #endif
 
   target_attach (args, from_tty);
@@ -1852,16 +1953,12 @@ attach_command (char *args, int from_tty)
       reread_symbols ();
     }
 
-#ifdef SOLIB_ADD
-  /* Add shared library symbols from the newly attached process, if any.  */
-  SOLIB_ADD ((char *) 0, from_tty, &current_target, auto_solib_add);
-  re_enable_breakpoints_in_shlibs ();
-#endif
-
   /* Take any necessary post-attaching actions for this platform.
    */
   target_post_attach (PIDGET (inferior_ptid));
 
+  post_create_inferior (&current_target, from_tty);
+
   /* Install inferior's terminal modes.  */
   target_terminal_inferior ();
 
@@ -1930,11 +2027,6 @@ static void
 print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
                  struct frame_info *frame, const char *args)
 {
-  if (!target_has_registers)
-    error (_("The program has no registers now."));
-  if (deprecated_selected_frame == NULL)
-    error (_("No selected frame."));
-
   if (gdbarch_print_float_info_p (gdbarch))
     gdbarch_print_float_info (gdbarch, file, frame, args);
   else
@@ -1942,7 +2034,10 @@ print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
       int regnum;
       int printed_something = 0;
 
-      for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
+      for (regnum = 0;
+          regnum < gdbarch_num_regs (current_gdbarch)
+                   + gdbarch_num_pseudo_regs (current_gdbarch);
+          regnum++)
        {
          if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
            {
@@ -1959,8 +2054,11 @@ No floating-point info available for this processor.\n");
 static void
 float_info (char *args, int from_tty)
 {
+  if (!target_has_registers)
+    error (_("The program has no registers now."));
+
   print_float_info (current_gdbarch, gdb_stdout, 
-                   deprecated_selected_frame, args);
+                   get_selected_frame (NULL), args);
 }
 \f
 static void
@@ -1974,21 +2072,24 @@ unset_command (char *args, int from_tty)
 void
 _initialize_infcmd (void)
 {
-  struct cmd_list_element *c;
-
-  c = add_com ("tty", class_run, tty_command,
-              _("Set terminal for future runs of program being debugged."));
-  set_cmd_completer (c, filename_completer);
-
-  c = add_set_cmd ("args", class_run, var_string_noescape,
-                  (char *) &inferior_args,
-                  "Set argument list to give program being debugged when it is started.\n\
-Follow this command with any number of args, to be passed to the program.",
-                  &setlist);
-  set_cmd_completer (c, filename_completer);
-  set_cmd_sfunc (c, notice_args_set);
-  c = deprecated_add_show_from_set (c, &showlist);
-  set_cmd_sfunc (c, notice_args_read);
+  struct cmd_list_element *c = NULL;
+
+  /* add the filename of the terminal connected to inferior I/O */
+  add_setshow_filename_cmd ("inferior-tty", class_run,
+                           &inferior_io_terminal, _("\
+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);
+  add_com_alias ("tty", "set inferior-tty", class_alias, 0);
+
+  add_setshow_optional_filename_cmd ("args", class_run,
+                                    &inferior_args, _("\
+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,
+                                    &setlist, &showlist);
 
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
@@ -2045,10 +2146,11 @@ directory, or (if not found there) using the source file search path\n\
 (see the \"directory\" command).  You can also use the \"file\" command\n\
 to specify the program, and to load its symbol table."));
 
-  add_com ("detach", class_run, detach_command, _("\
+  add_prefix_cmd ("detach", class_run, detach_command, _("\
 Detach a process or file previously attached.\n\
 If a process, it is no longer traced, and it continues its execution.  If\n\
-you were debugging a file, the file is closed and gdb no longer accesses it."));
+you were debugging a file, the file is closed and gdb no longer accesses it."),
+                 &detachlist, "detach ", 0, &cmdlist);
 
   add_com ("disconnect", class_run, disconnect_command, _("\
 Disconnect from a target.\n\
This page took 0.030762 seconds and 4 git commands to generate.