* symfile.c (add_symbol_file_command): Abort if the user forgot
[deliverable/binutils-gdb.git] / gdb / symfile.c
index 6bf94138d5370d5eb8251cf8980559cffc82c290..e63ee53053129f76b9afe79b0abd4d1cd274dc9c 100644 (file)
@@ -1,7 +1,8 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
 
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
@@ -19,8 +20,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 "bfdlink.h"
@@ -48,6 +49,8 @@
 #include "readline/readline.h"
 #include "gdb_assert.h"
 #include "block.h"
+#include "observer.h"
+#include "exec.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -55,6 +58,7 @@
 #include "gdb_stat.h"
 #include <ctype.h>
 #include <time.h>
+#include <sys/time.h>
 
 #ifndef O_BINARY
 #define O_BINARY 0
@@ -455,6 +459,84 @@ init_objfile_sect_indices (struct objfile *objfile)
     }
 }
 
+/* The arguments to place_section.  */
+
+struct place_section_arg
+{
+  struct section_offsets *offsets;
+  CORE_ADDR lowest;
+};
+
+/* Find a unique offset to use for loadable section SECT if
+   the user did not provide an offset.  */
+
+void
+place_section (bfd *abfd, asection *sect, void *obj)
+{
+  struct place_section_arg *arg = obj;
+  CORE_ADDR *offsets = arg->offsets->offsets, start_addr;
+  int done;
+
+  /* We are only interested in loadable sections.  */
+  if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+    return;
+
+  /* If the user specified an offset, honor it.  */
+  if (offsets[sect->index] != 0)
+    return;
+
+  /* Otherwise, let's try to find a place for the section.  */
+  do {
+    asection *cur_sec;
+    ULONGEST align = 1 << bfd_get_section_alignment (abfd, sect);
+
+    start_addr = (arg->lowest + align - 1) & -align;
+    done = 1;
+
+    for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next)
+      {
+       int indx = cur_sec->index;
+       CORE_ADDR cur_offset;
+
+       /* We don't need to compare against ourself.  */
+       if (cur_sec == sect)
+         continue;
+
+       /* We can only conflict with loadable sections.  */
+       if ((bfd_get_section_flags (abfd, cur_sec) & SEC_LOAD) == 0)
+         continue;
+
+       /* We do not expect this to happen; just ignore sections in a
+          relocatable file with an assigned VMA.  */
+       if (bfd_section_vma (abfd, cur_sec) != 0)
+         continue;
+
+       /* If the section offset is 0, either the section has not been placed
+          yet, or it was the lowest section placed (in which case LOWEST
+          will be past its end).  */
+       if (offsets[indx] == 0)
+         continue;
+
+       /* If this section would overlap us, then we must move up.  */
+       if (start_addr + bfd_get_section_size (sect) > offsets[indx]
+           && start_addr < offsets[indx] + bfd_get_section_size (cur_sec))
+         {
+           start_addr = offsets[indx] + bfd_get_section_size (cur_sec);
+           start_addr = (start_addr + align - 1) & -align;
+           done = 0;
+           continue;
+         }
+
+       /* Otherwise, we appear to be OK.  So far.  */
+      }
+    }
+  while (!done);
+
+  offsets[sect->index] = start_addr;
+  arg->lowest = start_addr + bfd_get_section_size (sect);
+
+  exec_set_section_address (bfd_get_filename (abfd), sect->index, start_addr);
+}
 
 /* Parse the user's idea of an offset for dynamic linking, into our idea
    of how to represent it for fast symbol reading.  This is the default
@@ -491,6 +573,19 @@ default_symfile_offsets (struct objfile *objfile,
       (objfile->section_offsets)->offsets[osp->sectindex] = osp->addr;
     }
 
+  /* For relocatable files, all loadable sections will start at zero.
+     The zero is meaningless, so try to pick arbitrary addresses such
+     that no loadable sections overlap.  This algorithm is quadratic,
+     but the number of sections in a single object file is generally
+     small.  */
+  if ((bfd_get_file_flags (objfile->obfd) & (EXEC_P | DYNAMIC)) == 0)
+    {
+      struct place_section_arg arg;
+      arg.offsets = objfile->section_offsets;
+      arg.lowest = 0;
+      bfd_map_over_sections (objfile->obfd, place_section, &arg);
+    }
+
   /* Remember the bfd indexes for the .text, .data, .bss and
      .rodata sections. */
   init_objfile_sect_indices (objfile);
@@ -991,8 +1086,10 @@ symbol_file_clear (int from_tty)
 {
   if ((have_full_symbols () || have_partial_symbols ())
       && from_tty
-      && !query ("Discard symbol table from `%s'? ",
-                symfile_objfile->name))
+      && (symfile_objfile
+         ? !query (_("Discard symbol table from `%s'? "),
+                   symfile_objfile->name)
+         : !query (_("Discard symbol table? "))))
     error (_("Not confirmed."));
     free_all_objfiles ();
 
@@ -1045,7 +1142,7 @@ separate_debug_file_exists (const char *name, unsigned long crc)
 {
   unsigned long file_crc = 0;
   int fd;
-  char buffer[8*1024];
+  gdb_byte buffer[8*1024];
   int count;
 
   fd = open (name, O_RDONLY | O_BINARY);
@@ -1157,26 +1254,21 @@ find_separate_debug_file (struct objfile *objfile)
 
 /* This is the symbol-file command.  Read the file, analyze its
    symbols, and add a struct symtab to a symtab list.  The syntax of
-   the command is rather bizarre--(1) buildargv implements various
-   quoting conventions which are undocumented and have little or
-   nothing in common with the way things are quoted (or not quoted)
-   elsewhere in GDB, (2) options are used, which are not generally
-   used in GDB (perhaps "set mapped on", "set readnow on" would be
-   better), (3) the order of options matters, which is contrary to GNU
+   the command is rather bizarre:
+
+   1. The function buildargv implements various quoting conventions
+   which are undocumented and have little or nothing in common with
+   the way things are quoted (or not quoted) elsewhere in GDB.
+
+   2. Options are used, which are not generally used in GDB (perhaps
+   "set mapped on", "set readnow on" would be better)
+
+   3. The order of options matters, which is contrary to GNU
    conventions (because it is confusing and inconvenient).  */
-/* Note: ezannoni 2000-04-17. This function used to have support for
-   rombug (see remote-os9k.c). It consisted of a call to target_link()
-   (target.c) to get the address of the text segment from the target,
-   and pass that to symbol_file_add(). This is no longer supported. */
 
 void
 symbol_file_command (char *args, int from_tty)
 {
-  char **argv;
-  char *name = NULL;
-  struct cleanup *cleanups;
-  int flags = OBJF_USERLOADED;
-
   dont_repeat ();
 
   if (args == NULL)
@@ -1185,10 +1277,14 @@ symbol_file_command (char *args, int from_tty)
     }
   else
     {
-      if ((argv = buildargv (args)) == NULL)
-       {
-         nomem (0);
-       }
+      char **argv = buildargv (args);
+      int flags = OBJF_USERLOADED;
+      struct cleanup *cleanups;
+      char *name = NULL;
+
+      if (argv == NULL)
+       nomem (0);
+
       cleanups = make_cleanup_freeargv (argv);
       while (*argv != NULL)
        {
@@ -1198,30 +1294,30 @@ symbol_file_command (char *args, int from_tty)
            error (_("unknown option `%s'"), *argv);
          else
            {
+             symbol_file_add_main_1 (*argv, from_tty, flags);
              name = *argv;
-
-             symbol_file_add_main_1 (name, from_tty, flags);
            }
+
          argv++;
        }
 
       if (name == NULL)
-       {
-         error (_("no symbol file name was specified"));
-       }
+       error (_("no symbol file name was specified"));
+
       do_cleanups (cleanups);
     }
 }
 
 /* Set the initial language.
 
-   A better solution would be to record the language in the psymtab when reading
-   partial symbols, and then use it (if known) to set the language.  This would
-   be a win for formats that encode the language in an easily discoverable place,
-   such as DWARF.  For stabs, we can jump through hoops looking for specially
-   named symbols or try to intuit the language from the specific type of stabs
-   we find, but we can't do that until later when we read in full symbols.
-   FIXME.  */
+   FIXME: A better solution would be to record the language in the
+   psymtab when reading partial symbols, and then use it (if known) to
+   set the language.  This would be a win for formats that encode the
+   language in an easily discoverable place, such as DWARF.  For
+   stabs, we can jump through hoops looking for specially named
+   symbols or try to intuit the language from the specific type of
+   stabs we find, but we can't do that until later when we read in
+   full symbols.  */
 
 static void
 set_initial_language (void)
@@ -1233,23 +1329,23 @@ set_initial_language (void)
   if (pst != NULL)
     {
       if (pst->filename != NULL)
-       {
-         lang = deduce_language_from_filename (pst->filename);
-       }
+       lang = deduce_language_from_filename (pst->filename);
+
       if (lang == language_unknown)
        {
          /* Make C the default language */
          lang = language_c;
        }
+
       set_language (lang);
-      expected_language = current_language;    /* Don't warn the user */
+      expected_language = current_language; /* Don't warn the user.  */
     }
 }
 
-/* Open file specified by NAME and hand it off to BFD for preliminary
-   analysis.  Result is a newly initialized bfd *, which includes a newly
-   malloc'd` copy of NAME (tilde-expanded and made absolute).
-   In case of trouble, error() is called.  */
+/* Open the file specified by NAME and hand it off to BFD for
+   preliminary analysis.  Return a newly initialized bfd *, which
+   includes a newly malloc'd` copy of NAME (tilde-expanded and made
+   absolute).  In case of trouble, error() is called.  */
 
 bfd *
 symfile_bfd_open (char *name)
@@ -1258,13 +1354,11 @@ symfile_bfd_open (char *name)
   int desc;
   char *absolute_name;
 
-
-
-  name = tilde_expand (name);  /* Returns 1st new malloc'd copy */
+  name = tilde_expand (name);  /* Returns 1st new malloc'd copy.  */
 
   /* Look down path for it, allocate 2nd new malloc'd copy.  */
-  desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, name, O_RDONLY | O_BINARY,
-               0, &absolute_name);
+  desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, name,
+               O_RDONLY | O_BINARY, 0, &absolute_name);
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
   if (desc < 0)
     {
@@ -1279,11 +1373,13 @@ symfile_bfd_open (char *name)
       make_cleanup (xfree, name);
       perror_with_name (name);
     }
-  xfree (name);                        /* Free 1st new malloc'd copy */
-  name = absolute_name;                /* Keep 2nd malloc'd copy in bfd */
-  /* It'll be freed in free_objfile(). */
 
-  sym_bfd = bfd_fdopenr (name, gnutarget, desc);
+  /* Free 1st new malloc'd copy, but keep the 2nd malloc'd copy in
+     bfd.  It'll be freed in free_objfile(). */
+  xfree (name);
+  name = absolute_name;
+
+  sym_bfd = bfd_fopen (name, gnutarget, FOPEN_RB, desc);
   if (!sym_bfd)
     {
       close (desc);
@@ -1295,33 +1391,36 @@ symfile_bfd_open (char *name)
 
   if (!bfd_check_format (sym_bfd, bfd_object))
     {
-      /* FIXME: should be checking for errors from bfd_close (for one thing,
-         on error it does not free all the storage associated with the
-         bfd).  */
-      bfd_close (sym_bfd);     /* This also closes desc */
+      /* FIXME: should be checking for errors from bfd_close (for one
+         thing, on error it does not free all the storage associated
+         with the bfd).  */
+      bfd_close (sym_bfd);     /* This also closes desc */
       make_cleanup (xfree, name);
       error (_("\"%s\": can't read symbols: %s."), name,
             bfd_errmsg (bfd_get_error ()));
     }
-  return (sym_bfd);
+
+  return sym_bfd;
 }
 
-/* Return the section index for the given section name. Return -1 if
-   the section was not found. */
+/* Return the section index for SECTION_NAME on OBJFILE.  Return -1 if
+   the section was not found.  */
+
 int
 get_section_index (struct objfile *objfile, char *section_name)
 {
   asection *sect = bfd_get_section_by_name (objfile->obfd, section_name);
+
   if (sect)
     return sect->index;
   else
     return -1;
 }
 
-/* Link a new symtab_fns into the global symtab_fns list.  Called on gdb
-   startup by the _initialize routine in each object file format reader,
-   to register information about each format the the reader is prepared
-   to handle. */
+/* Link SF into the global symtab_fns list.  Called on startup by the
+   _initialize routine in each object file format reader, to register
+   information about each format the the reader is prepared to
+   handle. */
 
 void
 add_symtab_fns (struct sym_fns *sf)
@@ -1330,11 +1429,10 @@ add_symtab_fns (struct sym_fns *sf)
   symtab_fns = sf;
 }
 
-
-/* Initialize to read symbols from the symbol file sym_bfd.  It either
-   returns or calls error().  The result is an initialized struct sym_fns
-   in the objfile structure, that contains cached information about the
-   symbol file.  */
+/* Initialize OBJFILE to read symbols from its associated BFD.  It
+   either returns or calls error().  The result is an initialized
+   struct sym_fns in the objfile structure, that contains cached
+   information about the symbol file.  */
 
 static void
 find_sym_fns (struct objfile *objfile)
@@ -1346,7 +1444,7 @@ find_sym_fns (struct objfile *objfile)
   if (our_flavour == bfd_target_srec_flavour
       || our_flavour == bfd_target_ihex_flavour
       || our_flavour == bfd_target_tekhex_flavour)
-    return;    /* No symbols. */
+    return;    /* No symbols.  */
 
   for (sf = symtab_fns; sf != NULL; sf = sf->next)
     {
@@ -1356,10 +1454,12 @@ find_sym_fns (struct objfile *objfile)
          return;
        }
     }
+
   error (_("I'm sorry, Dave, I can't do that.  Symbol format `%s' unknown."),
         bfd_get_target (objfile->obfd));
 }
 \f
+
 /* This function runs the load command of our current target.  */
 
 static void
@@ -1424,7 +1524,7 @@ load_section_callback (bfd *abfd, asection *asec, void *data)
       bfd_size_type size = bfd_get_section_size (asec);
       if (size > 0)
        {
-         char *buffer;
+         gdb_byte *buffer;
          struct cleanup *old_chain;
          CORE_ADDR lma = bfd_section_lma (abfd, asec) + args->load_offset;
          bfd_size_type block_size;
@@ -1469,7 +1569,7 @@ load_section_callback (bfd *abfd, asection *asec, void *data)
                     method to the target vector and then use
                     that.  remote.c could implement that method
                     using the ``qCRC'' packet.  */
-                 char *check = xmalloc (len);
+                 gdb_byte *check = xmalloc (len);
                  struct cleanup *verify_cleanups =
                    make_cleanup (xfree, check);
 
@@ -1511,7 +1611,7 @@ generic_load (char *args, int from_tty)
 {
   asection *s;
   bfd *loadfile_bfd;
-  time_t start_time, end_time; /* Start and end times of download */
+  struct timeval start_time, end_time;
   char *filename;
   struct cleanup *old_cleanups;
   char *offptr;
@@ -1563,11 +1663,11 @@ generic_load (char *args, int from_tty)
   bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
                         (void *) &cbdata.total_size);
 
-  start_time = time (NULL);
+  gettimeofday (&start_time, NULL);
 
   bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
 
-  end_time = time (NULL);
+  gettimeofday (&end_time, NULL);
 
   entry = bfd_get_start_address (loadfile_bfd);
   ui_out_text (uiout, "Start address ");
@@ -1586,7 +1686,7 @@ generic_load (char *args, int from_tty)
      others don't (or didn't - perhaps they have all been deleted).  */
 
   print_transfer_performance (gdb_stdout, cbdata.data_count,
-                             cbdata.write_count, end_time - start_time);
+                             cbdata.write_count, &start_time, &end_time);
 
   do_cleanups (old_cleanups);
 }
@@ -1601,21 +1701,35 @@ void
 report_transfer_performance (unsigned long data_count, time_t start_time,
                             time_t end_time)
 {
-  print_transfer_performance (gdb_stdout, data_count,
-                             end_time - start_time, 0);
+  struct timeval start, end;
+
+  start.tv_sec = start_time;
+  start.tv_usec = 0;
+  end.tv_sec = end_time;
+  end.tv_usec = 0;
+
+  print_transfer_performance (gdb_stdout, data_count, 0, &start, &end);
 }
 
 void
 print_transfer_performance (struct ui_file *stream,
                            unsigned long data_count,
                            unsigned long write_count,
-                           unsigned long time_count)
+                           const struct timeval *start_time,
+                           const struct timeval *end_time)
 {
+  unsigned long time_count;
+
+  /* Compute the elapsed time in milliseconds, as a tradeoff between
+     accuracy and overflow.  */
+  time_count = (end_time->tv_sec - start_time->tv_sec) * 1000;
+  time_count += (end_time->tv_usec - start_time->tv_usec) / 1000;
+
   ui_out_text (uiout, "Transfer rate: ");
   if (time_count > 0)
     {
       ui_out_field_fmt (uiout, "transfer-rate", "%lu",
-                       (data_count * 8) / time_count);
+                       1000 * (data_count * 8) / time_count);
       ui_out_text (uiout, " bits/sec");
     }
   else
@@ -1762,6 +1876,13 @@ add_symbol_file_command (char *args, int from_tty)
       argcnt++;
     }
 
+  /* This command takes at least two arguments.  The first one is a
+     filename, and the second is the address where this file has been
+     loaded.  Abort now if this address hasn't been provided by the
+     user.  */
+  if (section_index < 1)
+    error (_("The address where %s has been loaded is missing"), filename);
+
   /* Print the prompt for the query below. And save the arguments into
      a sect_addr_info structure to be passed around to other
      functions.  We have to split this up into separate print
@@ -1899,6 +2020,10 @@ reread_symbols (void)
              memcpy (offsets, objfile->section_offsets,
                      SIZEOF_N_SECTION_OFFSETS (num_offsets));
 
+             /* Remove any references to this objfile in the global
+                value lists.  */
+             preserve_values (objfile);
+
              /* Nuke all the state that we will re-read.  Much of the following
                 code which sets things to NULL really is necessary to tell
                 other parts of GDB that there is nothing currently there.  */
@@ -2013,7 +2138,13 @@ reread_symbols (void)
     }
 
   if (reread_one)
-    clear_symtab_users ();
+    {
+      clear_symtab_users ();
+      /* At least one objfile has changed, so we can consider that
+         the executable we're debugging has changed too.  */
+      observer_notify_executable_changed (NULL);
+    }
+      
 }
 
 
@@ -2360,12 +2491,14 @@ clear_symtab_users (void)
 {
   /* Someday, we should do better than this, by only blowing away
      the things that really need to be blown.  */
-  clear_value_history ();
+
+  /* Clear the "current" symtab first, because it is no longer valid.
+     breakpoint_re_set may try to access the current symtab.  */
+  clear_current_source_symtab_and_line ();
+
   clear_displays ();
-  clear_internalvars ();
   breakpoint_re_set ();
   set_default_breakpoint (0, 0, 0, 0);
-  clear_current_source_symtab_and_line ();
   clear_pc_function_cache ();
   if (deprecated_target_new_objfile_hook)
     deprecated_target_new_objfile_hook (NULL);
@@ -3352,7 +3485,7 @@ static void
 read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, int len)
 {
   /* FIXME (alloca): Not safe if array is very large. */
-  char *buf = alloca (len * TARGET_LONG_BYTES);
+  gdb_byte *buf = alloca (len * TARGET_LONG_BYTES);
   int i;
 
   read_memory (memaddr, buf, len * TARGET_LONG_BYTES);
@@ -3392,7 +3525,7 @@ simple_read_overlay_table (void)
     = (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table));
   cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym);
   read_target_long_array (cache_ovly_table_base,
-                          (int *) cache_ovly_table,
+                          (unsigned int *) cache_ovly_table,
                           cache_novlys * 4);
 
   return 1;                    /* SUCCESS */
@@ -3420,7 +3553,7 @@ simple_read_overlay_region_table (void)
        {
          cache_ovly_region_table_base = SYMBOL_VALUE_ADDRESS (msym);
          read_target_long_array (cache_ovly_region_table_base,
-                                 (int *) cache_ovly_region_table,
+                                 (unsigned int *) cache_ovly_region_table,
                                  cache_novly_regions * 3);
        }
       else
@@ -3454,7 +3587,7 @@ simple_overlay_update_1 (struct obj_section *osect)
        /* && cache_ovly_table[i][SIZE] == size */ )
       {
        read_target_long_array (cache_ovly_table_base + i * TARGET_LONG_BYTES,
-                               (int *) cache_ovly_table[i], 4);
+                               (unsigned int *) cache_ovly_table[i], 4);
        if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
            && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
            /* && cache_ovly_table[i][SIZE] == size */ )
This page took 0.034973 seconds and 4 git commands to generate.