* infrun.c (follow_fork): Initialize new step_* locals
[deliverable/binutils-gdb.git] / gdb / exec.c
index e8e5f3be0094fd0b776a1d6b80303eda6f4e3ebf..985fbe57129ef86ea401f7ed32cf88f4390e8c25 100644 (file)
@@ -1,14 +1,14 @@
 /* Work with executable files, for GDB. 
 
-   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
-   Inc.
+   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    GNU General Public License for more details.
 
    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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -32,6 +30,8 @@
 #include "completer.h"
 #include "value.h"
 #include "exec.h"
+#include "observer.h"
+#include "arch-utils.h"
 
 #include <fcntl.h>
 #include "readline/readline.h"
@@ -41,9 +41,6 @@
 
 #include <ctype.h>
 #include "gdb_stat.h"
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
 
 #include "xcoffsolib.h"
 
@@ -61,8 +58,6 @@ static void set_section_command (char *, int);
 
 static void exec_files_info (struct target_ops *);
 
-static int ignore (CORE_ADDR, char *);
-
 static void init_exec_ops (void);
 
 void _initialize_exec (void);
@@ -74,14 +69,23 @@ struct target_ops exec_ops;
 /* The Binary File Descriptor handle for the executable file.  */
 
 bfd *exec_bfd = NULL;
+long exec_bfd_mtime = 0;
 
 /* Whether to open exec and core files read-only or read-write.  */
 
 int write_files = 0;
+static void
+show_write_files (struct ui_file *file, int from_tty,
+                 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Writing into executable and core files is %s.\n"),
+                   value);
+}
+
 
 struct vmap *vmap;
 
-void
+static void
 exec_open (char *args, int from_tty)
 {
   target_preopen (from_tty);
@@ -133,6 +137,7 @@ exec_close (int quitting)
                 name, bfd_errmsg (bfd_get_error ()));
       xfree (name);
       exec_bfd = NULL;
+      exec_bfd_mtime = 0;
     }
 
   if (exec_ops.to_sections)
@@ -153,7 +158,7 @@ exec_file_clear (int from_tty)
     printf_unfiltered (_("No executable file now.\n"));
 }
 
-/*  Process the first arg in ARGS as the new exec file.
+/* Set FILENAME as the new exec file.
 
    This function is intended to be behave essentially the same
    as exec_file_command, except that the latter will detect when
@@ -168,9 +173,7 @@ exec_file_clear (int from_tty)
    given a pid but not a exec pathname, and the attach command could
    figure out the pathname from the pid.  (In this case, we shouldn't
    ask the user whether the current target should be shut down --
-   we're supplying the exec pathname late for good reason.)
-   
-   ARGS is assumed to be the filename. */
+   we're supplying the exec pathname late for good reason.)  */
 
 void
 exec_file_attach (char *filename, int from_tty)
@@ -184,14 +187,17 @@ exec_file_attach (char *filename, int from_tty)
     {
       if (from_tty)
         printf_unfiltered (_("No executable file now.\n"));
+
+      set_gdbarch_from_file (NULL);
     }
   else
     {
+      struct cleanup *cleanups;
       char *scratch_pathname;
       int scratch_chan;
 
       scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
-                  write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, 0,
+                  write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
                            &scratch_pathname);
 #if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
       if (scratch_chan < 0)
@@ -199,24 +205,29 @@ exec_file_attach (char *filename, int from_tty)
          char *exename = alloca (strlen (filename) + 5);
          strcat (strcpy (exename, filename), ".exe");
          scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, exename,
-            write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, 0,
+            write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
             &scratch_pathname);
        }
 #endif
       if (scratch_chan < 0)
        perror_with_name (filename);
-      exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+      exec_bfd = bfd_fopen (scratch_pathname, gnutarget,
+                           write_files ? FOPEN_RUB : FOPEN_RB,
+                           scratch_chan);
 
       if (!exec_bfd)
-       error (_("\"%s\": could not open as an executable file: %s"),
-              scratch_pathname, bfd_errmsg (bfd_get_error ()));
+       {
+         close (scratch_chan);
+         error (_("\"%s\": could not open as an executable file: %s"),
+                scratch_pathname, bfd_errmsg (bfd_get_error ()));
+       }
 
       /* At this point, scratch_pathname and exec_bfd->name both point to the
          same malloc'd string.  However exec_close() will attempt to free it
          via the exec_bfd->name pointer, so we need to make another copy and
          leave exec_bfd as the new owner of the original copy. */
       scratch_pathname = xstrdup (scratch_pathname);
-      make_cleanup (xfree, scratch_pathname);
+      cleanups = make_cleanup (xfree, scratch_pathname);
 
       if (!bfd_check_format (exec_bfd, bfd_object))
        {
@@ -253,9 +264,7 @@ exec_file_attach (char *filename, int from_tty)
                 scratch_pathname, bfd_errmsg (bfd_get_error ()));
        }
 
-#ifdef DEPRECATED_HPUX_TEXT_END
-      DEPRECATED_HPUX_TEXT_END (&exec_ops);
-#endif
+      exec_bfd_mtime = bfd_get_mtime (exec_bfd);
 
       validate_files ();
 
@@ -266,8 +275,11 @@ exec_file_attach (char *filename, int from_tty)
       /* Tell display code (if any) about the changed file name.  */
       if (deprecated_exec_file_display_hook)
        (*deprecated_exec_file_display_hook) (filename);
+
+      do_cleanups (cleanups);
     }
   bfd_cache_close_all ();
+  observer_notify_executable_changed ();
 }
 
 /*  Process the first arg in ARGS as the new exec file.
@@ -283,19 +295,21 @@ exec_file_command (char *args, int from_tty)
 {
   char **argv;
   char *filename;
-  
-  target_preopen (from_tty);
+
+  if (from_tty && target_has_execution
+      && !query (_("A program is being debugged already.\n"
+                  "Are you sure you want to change the file? ")))
+    error (_("File not changed."));
 
   if (args)
     {
+      struct cleanup *cleanups;
+
       /* Scan through the args and pick up the first non option arg
          as the filename.  */
 
-      argv = buildargv (args);
-      if (argv == NULL)
-        nomem (0);
-
-      make_cleanup_freeargv (argv);
+      argv = gdb_buildargv (args);
+      cleanups = make_cleanup_freeargv (argv);
 
       for (; (*argv != NULL) && (**argv == '-'); argv++)
         {;
@@ -306,6 +320,8 @@ exec_file_command (char *args, int from_tty)
       filename = tilde_expand (*argv);
       make_cleanup (xfree, filename);
       exec_file_attach (filename, from_tty);
+
+      do_cleanups (cleanups);
     }
   else
     exec_file_attach (NULL, from_tty);
@@ -335,14 +351,18 @@ static void
 add_to_section_table (bfd *abfd, struct bfd_section *asect,
                      void *table_pp_char)
 {
-  struct section_table **table_pp = (struct section_table **) table_pp_char;
+  struct target_section **table_pp = (struct target_section **) table_pp_char;
   flagword aflag;
 
+  /* Check the section flags, but do not discard zero-length sections, since
+     some symbols may still be attached to this section.  For instance, we
+     encountered on sparc-solaris 2.10 a shared library with an empty .bss
+     section to which a symbol named "_end" was attached.  The address
+     of this symbol still needs to be relocated.  */
   aflag = bfd_get_section_flags (abfd, asect);
   if (!(aflag & SEC_ALLOC))
     return;
-  if (0 == bfd_section_size (abfd, asect))
-    return;
+
   (*table_pp)->bfd = abfd;
   (*table_pp)->the_bfd_section = asect;
   (*table_pp)->addr = bfd_section_vma (abfd, asect);
@@ -354,15 +374,15 @@ add_to_section_table (bfd *abfd, struct bfd_section *asect,
    Returns 0 if OK, 1 on error.  */
 
 int
-build_section_table (struct bfd *some_bfd, struct section_table **start,
-                    struct section_table **end)
+build_section_table (struct bfd *some_bfd, struct target_section **start,
+                    struct target_section **end)
 {
   unsigned count;
 
   count = bfd_count_sections (some_bfd);
   if (*start)
     xfree (* start);
-  *start = (struct section_table *) xmalloc (count * sizeof (**start));
+  *start = (struct target_section *) xmalloc (count * sizeof (**start));
   *end = *start;
   bfd_map_over_sections (some_bfd, add_to_section_table, (char *) end);
   if (*end > *start + count)
@@ -382,14 +402,14 @@ bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
   if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
     return;
 
-  if (DEPRECATED_STREQ (bfd_section_name (abfd, sect), ".text"))
+  if (strcmp (bfd_section_name (abfd, sect), ".text") == 0)
     {
       vp->tstart = bfd_section_vma (abfd, sect);
       vp->tend = vp->tstart + bfd_section_size (abfd, sect);
       vp->tvma = bfd_section_vma (abfd, sect);
       vp->toffs = sect->filepos;
     }
-  else if (DEPRECATED_STREQ (bfd_section_name (abfd, sect), ".data"))
+  else if (strcmp (bfd_section_name (abfd, sect), ".data") == 0)
     {
       vp->dstart = bfd_section_vma (abfd, sect);
       vp->dend = vp->dstart + bfd_section_size (abfd, sect);
@@ -426,10 +446,16 @@ map_vmap (bfd *abfd, bfd *arch)
   return vp;
 }
 \f
-/* Read or write the exec file.
+/* Read or write from BFD executable files.
 
-   Args are address within a BFD file, address within gdb address-space,
-   length, and a flag indicating whether to read or write.
+   MEMADDR is an address within the target address space, MYADDR is an
+   address within GDB address-space where data is written to, LEN is
+   length of buffer, and WRITE indicates whether to read or write.
+   SECTIONS and SECTIONS_END defines a section table holding sections
+   from possibly multiple BFDs.
+
+   If SECTION_NAME is not NULL, only access sections with that same
+   name.
 
    Result is a length:
 
@@ -439,38 +465,28 @@ map_vmap (bfd *abfd, bfd *arch)
    to handle more bytes beyond this length, but no
    promises.
    < 0:  We cannot handle this address, but if somebody
-   else handles (-N) bytes, we can start from there.
-
-   The same routine is used to handle both core and exec files;
-   we just tail-call it with more arguments to select between them.  */
+   else handles (-N) bytes, we can start from there.  */
 
-int
-xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
-            struct mem_attrib *attrib,
-            struct target_ops *target)
+static int
+section_table_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr,
+                          int len, int write,
+                          struct target_section *sections,
+                          struct target_section *sections_end,
+                          const char *section_name)
 {
   int res;
-  struct section_table *p;
+  struct target_section *p;
   CORE_ADDR nextsectaddr, memend;
-  asection *section = NULL;
 
   if (len <= 0)
     internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 
-  if (overlay_debugging)
-    {
-      section = find_pc_overlay (memaddr);
-      if (pc_in_unmapped_range (memaddr, section))
-       memaddr = overlay_mapped_address (memaddr, section);
-    }
-
   memend = memaddr + len;
   nextsectaddr = memend;
 
-  for (p = target->to_sections; p < target->to_sections_end; p++)
+  for (p = sections; p < sections_end; p++)
     {
-      if (overlay_debugging && section && p->the_bfd_section &&
-         strcmp (section->name, p->the_bfd_section->name) != 0)
+      if (section_name && strcmp (section_name, p->the_bfd_section->name) != 0)
        continue;               /* not the section we need */
       if (memaddr >= p->addr)
         {
@@ -516,24 +532,81 @@ xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
   else
     return -(nextsectaddr - memaddr);  /* Next boundary where we can help */
 }
+
+int
+section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
+                                  ULONGEST offset, LONGEST len,
+                                  struct target_section *sections,
+                                  struct target_section *sections_end)
+{
+  if (readbuf != NULL)
+    return section_table_xfer_memory (offset, readbuf, len, 0,
+                                     sections, sections_end, NULL);
+  else
+    return section_table_xfer_memory (offset, (gdb_byte *) writebuf, len, 1,
+                                     sections, sections_end, NULL);
+}
+
+/* Read or write the exec file.
+
+   Args are address within a BFD file, address within gdb address-space,
+   length, and a flag indicating whether to read or write.
+
+   Result is a length:
+
+   0:    We cannot handle this address and length.
+   > 0:  We have handled N bytes starting at this address.
+   (If N == length, we did it all.)  We might be able
+   to handle more bytes beyond this length, but no
+   promises.
+   < 0:  We cannot handle this address, but if somebody
+   else handles (-N) bytes, we can start from there.
+
+   The same routine is used to handle both core and exec files;
+   we just tail-call it with more arguments to select between them.  */
+
+int
+xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
+            struct mem_attrib *attrib, struct target_ops *target)
+{
+  int res;
+  const char *section_name = NULL;
+
+  if (len <= 0)
+    internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+
+  if (overlay_debugging)
+    {
+      struct obj_section *section = find_pc_overlay (memaddr);
+
+      if (section != NULL)
+       {
+         if (pc_in_unmapped_range (memaddr, section))
+           memaddr = overlay_mapped_address (memaddr, section);
+         section_name = section->the_bfd_section->name;
+       }
+    }
+
+  return section_table_xfer_memory (memaddr, myaddr, len, write,
+                                   target->to_sections,
+                                   target->to_sections_end,
+                                   section_name);
+}
 \f
 
 void
 print_section_info (struct target_ops *t, bfd *abfd)
 {
-  struct section_table *p;
-  /* FIXME: 16 is not wide enough when TARGET_ADDR_BIT > 64.  */
-  int wid = TARGET_ADDR_BIT <= 32 ? 8 : 16;
+  struct target_section *p;
+  /* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64.  */
+  int wid = gdbarch_addr_bit (gdbarch_from_bfd (abfd)) <= 32 ? 8 : 16;
 
   printf_filtered ("\t`%s', ", bfd_get_filename (abfd));
   wrap_here ("        ");
   printf_filtered (_("file type %s.\n"), bfd_get_target (abfd));
   if (abfd == exec_bfd)
-    {
-      printf_filtered (_("\tEntry point: "));
-      deprecated_print_address_numeric (bfd_get_start_address (abfd), 1, gdb_stdout);
-      printf_filtered ("\n");
-    }
+    printf_filtered (_("\tEntry point: %s\n"),
+                     paddress (bfd_get_start_address (abfd)));
   for (p = t->to_sections; p < t->to_sections_end; p++)
     {
       printf_filtered ("\t%s", hex_string_custom (p->addr, wid));
@@ -585,46 +658,10 @@ exec_files_info (struct target_ops *t)
     }
 }
 
-/* msnyder 5/21/99:
-   exec_set_section_offsets sets the offsets of all the sections
-   in the exec objfile.  */
-
-void
-exec_set_section_offsets (bfd_signed_vma text_off, bfd_signed_vma data_off,
-                         bfd_signed_vma bss_off)
-{
-  struct section_table *sect;
-
-  for (sect = exec_ops.to_sections;
-       sect < exec_ops.to_sections_end;
-       sect++)
-    {
-      flagword flags;
-
-      flags = bfd_get_section_flags (exec_bfd, sect->the_bfd_section);
-
-      if (flags & SEC_CODE)
-       {
-         sect->addr += text_off;
-         sect->endaddr += text_off;
-       }
-      else if (flags & (SEC_DATA | SEC_LOAD))
-       {
-         sect->addr += data_off;
-         sect->endaddr += data_off;
-       }
-      else if (flags & SEC_ALLOC)
-       {
-         sect->addr += bss_off;
-         sect->endaddr += bss_off;
-       }
-    }
-}
-
 static void
 set_section_command (char *args, int from_tty)
 {
-  struct section_table *p;
+  struct target_section *p;
   char *secname;
   unsigned seclen;
   unsigned long secaddr;
@@ -661,12 +698,31 @@ set_section_command (char *args, int from_tty)
   error (_("Section %s not found"), secprint);
 }
 
+/* If we can find a section in FILENAME with BFD index INDEX, adjust
+   it to ADDRESS.  */
+
+void
+exec_set_section_address (const char *filename, int index, CORE_ADDR address)
+{
+  struct target_section *p;
+
+  for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++)
+    {
+      if (strcmp (filename, p->bfd->filename) == 0
+         && index == p->the_bfd_section->index)
+       {
+         p->endaddr += address - p->addr;
+         p->addr = address;
+       }
+    }
+}
+
 /* If mourn is being called in all the right places, this could be say
    `gdb internal error' (since generic_mourn calls
    breakpoint_init_inferior).  */
 
 static int
-ignore (CORE_ADDR addr, char *contents)
+ignore (struct bp_target_info *bp_tgt)
 {
   return 0;
 }
@@ -746,7 +802,7 @@ file itself are wrong.  Each section must be changed separately.  The\n\
 Set writing into executable and core files."), _("\
 Show writing into executable and core files."), NULL,
                           NULL,
-                          NULL, /* FIXME: i18n: */
+                          show_write_files,
                           &setlist, &showlist);
 
   add_target (&exec_ops);
This page took 0.029788 seconds and 4 git commands to generate.