* infrun.c (follow_fork): Initialize new step_* locals
[deliverable/binutils-gdb.git] / gdb / exec.c
index 7bd2ccd5734083e3db919de8e92f2411a7063687..985fbe57129ef86ea401f7ed32cf88f4390e8c25 100644 (file)
@@ -1,14 +1,14 @@
 /* Work with executable files, for GDB. 
 
-   Copyright (C) 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., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -33,6 +31,7 @@
 #include "value.h"
 #include "exec.h"
 #include "observer.h"
+#include "arch-utils.h"
 
 #include <fcntl.h>
 #include "readline/readline.h"
@@ -70,6 +69,7 @@ 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.  */
 
@@ -85,7 +85,7 @@ show_write_files (struct ui_file *file, int from_tty,
 
 struct vmap *vmap;
 
-void
+static void
 exec_open (char *args, int from_tty)
 {
   target_preopen (from_tty);
@@ -137,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)
@@ -157,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
@@ -172,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)
@@ -188,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)
@@ -203,7 +205,7 @@ 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
@@ -214,15 +216,18 @@ exec_file_attach (char *filename, int from_tty)
                            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))
        {
@@ -259,6 +264,8 @@ exec_file_attach (char *filename, int from_tty)
                 scratch_pathname, bfd_errmsg (bfd_get_error ()));
        }
 
+      exec_bfd_mtime = bfd_get_mtime (exec_bfd);
+
       validate_files ();
 
       set_gdbarch_from_file (exec_bfd);
@@ -268,9 +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 (NULL);
+  observer_notify_executable_changed ();
 }
 
 /*  Process the first arg in ARGS as the new exec file.
@@ -286,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++)
         {;
@@ -309,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);
@@ -338,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);
@@ -357,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)
@@ -429,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:
 
@@ -442,37 +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.
+   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)
+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)
         {
@@ -518,24 +532,81 @@ xfer_memory (CORE_ADDR memaddr, gdb_byte *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));
@@ -587,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;
@@ -663,23 +698,21 @@ 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, and the
-   user has not assigned an address to it yet (via "set section"), adjust it
-   to ADDRESS.  */
+/* 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 section_table *p;
+  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->addr == 0)
+         && index == p->the_bfd_section->index)
        {
+         p->endaddr += address - p->addr;
          p->addr = address;
-         p->endaddr += address;
        }
     }
 }
This page took 0.029686 seconds and 4 git commands to generate.