merge from gcc
[deliverable/binutils-gdb.git] / gdb / symfile.c
index f513dfa6f1b52208de59cffe024a63c80d2ef0f1..d0596e661506699e3ba5cdec118eb144d6b17041 100644 (file)
@@ -1,7 +1,7 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
@@ -10,7 +10,7 @@
 
    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,
@@ -19,9 +19,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 "bfdlink.h"
@@ -53,6 +51,8 @@
 #include "exec.h"
 #include "parser-defs.h"
 #include "varobj.h"
+#include "elf-bfd.h"
+#include "solib.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -88,8 +88,6 @@ static int simple_read_overlay_region_table (void);
 static void simple_free_overlay_region_table (void);
 #endif
 
-static void set_initial_language (void);
-
 static void load_command (char *, int);
 
 static void symbol_file_add_main_1 (char *args, int from_tty, int flags);
@@ -537,8 +535,6 @@ place_section (bfd *abfd, asection *sect, void *obj)
 
   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
@@ -637,6 +633,8 @@ default_symfile_offsets (struct objfile *objfile,
                continue;
 
              bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]);
+             exec_set_section_address (bfd_get_filename (abfd), cur_sec->index,
+                                       offsets[cur_sec->index]);
              offsets[cur_sec->index] = 0;
            }
        }
@@ -823,18 +821,13 @@ syms_from_objfile (struct objfile *objfile,
        bfd_map_over_sections (objfile->obfd, find_lowest_section,
                               &lower_sect);
       if (lower_sect == NULL)
-       warning (_("no loadable sections found in added symbol-file %s"),
-                objfile->name);
-      else
-       if ((bfd_get_section_flags (objfile->obfd, lower_sect) & SEC_CODE) == 0)
-         warning (_("Lowest section in %s is %s at %s"),
-                  objfile->name,
-                  bfd_section_name (objfile->obfd, lower_sect),
-                  paddr (bfd_section_vma (objfile->obfd, lower_sect)));
-      if (lower_sect != NULL)
-       lower_offset = bfd_section_vma (objfile->obfd, lower_sect);
+       {
+         warning (_("no loadable sections found in added symbol-file %s"),
+                  objfile->name);
+         lower_offset = 0;
+       }
       else
-       lower_offset = 0;
+       lower_offset = bfd_section_vma (objfile->obfd, lower_sect);
 
       /* Calculate offsets for the loadable sections.
         FIXME! Sections must be in order of increasing loadable section
@@ -1019,7 +1012,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
 {
   struct objfile *objfile;
   struct partial_symtab *psymtab;
-  char *debugfile;
+  char *debugfile = NULL;
   struct section_addr_info *orig_addrs = NULL;
   struct cleanup *my_cleanups;
   const char *name = bfd_get_filename (abfd);
@@ -1083,7 +1076,11 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
        }
     }
 
-  debugfile = find_separate_debug_file (objfile);
+  /* If the file has its own symbol tables it has no separate debug info.
+     `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS.
+     `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'.  */
+  if (objfile->psymtabs == NULL)
+    debugfile = find_separate_debug_file (objfile);
   if (debugfile)
     {
       if (addrs != NULL)
@@ -1216,15 +1213,104 @@ symbol_file_clear (int from_tty)
        storage has just been released, we'd better wipe the solib
        descriptors as well.
      */
-#if defined(SOLIB_RESTART)
-    SOLIB_RESTART ();
-#endif
+    no_shared_libraries (NULL, from_tty);
 
     symfile_objfile = NULL;
     if (from_tty)
       printf_unfiltered (_("No symbol file now.\n"));
 }
 
+struct build_id
+  {
+    size_t size;
+    gdb_byte data[1];
+  };
+
+/* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
+
+static struct build_id *
+build_id_bfd_get (bfd *abfd)
+{
+  struct build_id *retval;
+
+  if (!bfd_check_format (abfd, bfd_object)
+      || bfd_get_flavour (abfd) != bfd_target_elf_flavour
+      || elf_tdata (abfd)->build_id == NULL)
+    return NULL;
+
+  retval = xmalloc (sizeof *retval - 1 + elf_tdata (abfd)->build_id_size);
+  retval->size = elf_tdata (abfd)->build_id_size;
+  memcpy (retval->data, elf_tdata (abfd)->build_id, retval->size);
+
+  return retval;
+}
+
+/* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value.  */
+
+static int
+build_id_verify (const char *filename, struct build_id *check)
+{
+  bfd *abfd;
+  struct build_id *found = NULL;
+  int retval = 0;
+
+  /* We expect to be silent on the non-existing files.  */
+  abfd = bfd_openr (filename, gnutarget);
+  if (abfd == NULL)
+    return 0;
+
+  found = build_id_bfd_get (abfd);
+
+  if (found == NULL)
+    warning (_("File \"%s\" has no build-id, file skipped"), filename);
+  else if (found->size != check->size
+           || memcmp (found->data, check->data, found->size) != 0)
+    warning (_("File \"%s\" has a different build-id, file skipped"), filename);
+  else
+    retval = 1;
+
+  if (!bfd_close (abfd))
+    warning (_("cannot close \"%s\": %s"), filename,
+            bfd_errmsg (bfd_get_error ()));
+  return retval;
+}
+
+static char *
+build_id_to_debug_filename (struct build_id *build_id)
+{
+  char *link, *s, *retval = NULL;
+  gdb_byte *data = build_id->data;
+  size_t size = build_id->size;
+
+  /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
+  link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
+                 + 2 * size + (sizeof ".debug" - 1) + 1);
+  s = link + sprintf (link, "%s/.build-id/", debug_file_directory);
+  if (size > 0)
+    {
+      size--;
+      s += sprintf (s, "%02x", (unsigned) *data++);
+    }
+  if (size > 0)
+    *s++ = '/';
+  while (size-- > 0)
+    s += sprintf (s, "%02x", (unsigned) *data++);
+  strcpy (s, ".debug");
+
+  /* lrealpath() is expensive even for the usually non-existent files.  */
+  if (access (link, F_OK) == 0)
+    retval = lrealpath (link);
+  xfree (link);
+
+  if (retval != NULL && !build_id_verify (retval, build_id))
+    {
+      xfree (retval);
+      retval = NULL;
+    }
+
+  return retval;
+}
+
 static char *
 get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
 {
@@ -1302,6 +1388,25 @@ find_separate_debug_file (struct objfile *objfile)
   bfd_size_type debuglink_size;
   unsigned long crc32;
   int i;
+  struct build_id *build_id;
+
+  build_id = build_id_bfd_get (objfile->obfd);
+  if (build_id != NULL)
+    {
+      char *build_id_name;
+
+      build_id_name = build_id_to_debug_filename (build_id);
+      free (build_id);
+      /* Prevent looping on a stripped .debug file.  */
+      if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0)
+        {
+         warning (_("\"%s\": separate debug info file has no debug info"),
+                  build_id_name);
+         xfree (build_id_name);
+       }
+      else if (build_id_name != NULL)
+        return build_id_name;
+    }
 
   basename = get_debug_link_info (objfile, &crc32);
 
@@ -1463,7 +1568,7 @@ symbol_file_command (char *args, int from_tty)
    stabs we find, but we can't do that until later when we read in
    full symbols.  */
 
-static void
+void
 set_initial_language (void)
 {
   struct partial_symtab *pst;
@@ -1947,7 +2052,7 @@ print_transfer_performance (struct ui_file *stream,
                            const struct timeval *start_time,
                            const struct timeval *end_time)
 {
-  unsigned long time_count;
+  ULONGEST time_count;
 
   /* Compute the elapsed time in milliseconds, as a tradeoff between
      accuracy and overflow.  */
@@ -1957,9 +2062,23 @@ print_transfer_performance (struct ui_file *stream,
   ui_out_text (uiout, "Transfer rate: ");
   if (time_count > 0)
     {
-      ui_out_field_fmt (uiout, "transfer-rate", "%lu",
-                       1000 * (data_count * 8) / time_count);
-      ui_out_text (uiout, " bits/sec");
+      unsigned long rate = ((ULONGEST) data_count * 1000) / time_count;
+
+      if (ui_out_is_mi_like_p (uiout))
+       {
+         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate * 8);
+         ui_out_text (uiout, " bits/sec");
+       }
+      else if (rate < 1024)
+       {
+         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate);
+         ui_out_text (uiout, " bytes/sec");
+       }
+      else
+       {
+         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate / 1024);
+         ui_out_text (uiout, " KB/sec");
+       }
     }
   else
     {
@@ -2120,8 +2239,7 @@ add_symbol_file_command (char *args, int from_tty)
          entered on the command line. */
       section_addrs->other[sec_num].name = sec;
       section_addrs->other[sec_num].addr = addr;
-      printf_unfiltered ("\t%s_addr = %s\n",
-                      sec, hex_string ((unsigned long)addr));
+      printf_unfiltered ("\t%s_addr = %s\n", sec, paddress (addr));
       sec_num++;
 
       /* The object's sections are initialized when a
@@ -2213,6 +2331,14 @@ reread_symbols (void)
              /* We need to do this whenever any symbols go away.  */
              make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
 
+             if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd),
+                                             bfd_get_filename (exec_bfd)) == 0)
+               {
+                 /* Reload EXEC_BFD without asking anything.  */
+
+                 exec_file_attach (bfd_get_filename (objfile->obfd), 0);
+               }
+
              /* Clean up any state BFD has sitting around.  We don't need
                 to close the descriptor but BFD lacks a way of closing the
                 BFD without closing the descriptor.  */
@@ -2278,7 +2404,6 @@ reread_symbols (void)
                      sizeof (objfile->msymbol_hash));
              memset (&objfile->msymbol_demangled_hash, 0,
                      sizeof (objfile->msymbol_demangled_hash));
-             objfile->fundamental_types = NULL;
              clear_objfile_data (objfile);
              if (objfile->sf != NULL)
                {
@@ -2349,6 +2474,7 @@ reread_symbols (void)
              objfile->mtime = new_modtime;
              reread_one = 1;
               reread_separate_symbols (objfile);
+             init_entry_point_info (objfile);
            }
        }
     }
@@ -2425,6 +2551,8 @@ reread_separate_symbols (struct objfile *objfile)
       objfile->separate_debug_objfile->separate_debug_objfile_backlink
         = objfile;
     }
+  if (debug_file)
+    xfree (debug_file);
 }
 
 
@@ -2559,6 +2687,7 @@ init_filename_language_table (void)
       add_filename_language (".f", language_fortran);
       add_filename_language (".F", language_fortran);
       add_filename_language (".s", language_asm);
+      add_filename_language (".sx", language_asm);
       add_filename_language (".S", language_asm);
       add_filename_language (".pas", language_pascal);
       add_filename_language (".p", language_pascal);
@@ -2953,38 +3082,33 @@ start_psymtab_common (struct objfile *objfile,
   return (psymtab);
 }
 \f
-/* Add a symbol with a long value to a psymtab.
-   Since one arg is a struct, we pass in a ptr and deref it (sigh).
-   Return the partial symbol that has been added.  */
-
-/* NOTE: carlton/2003-09-11: The reason why we return the partial
-   symbol is so that callers can get access to the symbol's demangled
-   name, which they don't have any cheap way to determine otherwise.
-   (Currenly, dwarf2read.c is the only file who uses that information,
-   though it's possible that other readers might in the future.)
-   Elena wasn't thrilled about that, and I don't blame her, but we
-   couldn't come up with a better way to get that information.  If
-   it's needed in other situations, we could consider breaking up
-   SYMBOL_SET_NAMES to provide access to the demangled name lookup
-   cache.  */
-
-const struct partial_symbol *
-add_psymbol_to_list (char *name, int namelength, domain_enum domain,
-                    enum address_class class,
-                    struct psymbol_allocation_list *list, long val,    /* Value as a long */
-                    CORE_ADDR coreaddr,        /* Value as a CORE_ADDR */
-                    enum language language, struct objfile *objfile)
+/* Helper function, initialises partial symbol structure and stashes 
+   it into objfile's bcache.  Note that our caching mechanism will
+   use all fields of struct partial_symbol to determine hash value of the
+   structure.  In other words, having two symbols with the same name but
+   different domain (or address) is possible and correct.  */
+
+static struct partial_symbol *
+add_psymbol_to_bcache (char *name, int namelength, domain_enum domain,
+                      enum address_class class,
+                      long val,        /* Value as a long */
+                      CORE_ADDR coreaddr,      /* Value as a CORE_ADDR */
+                      enum language language, struct objfile *objfile,
+                      int *added)
 {
-  struct partial_symbol *psym;
-  char *buf = alloca (namelength + 1);
+  char *buf = name;  
   /* psymbol is static so that there will be no uninitialized gaps in the
      structure which might contain random data, causing cache misses in
      bcache. */
   static struct partial_symbol psymbol;
-
-  /* Create local copy of the partial symbol */
-  memcpy (buf, name, namelength);
-  buf[namelength] = '\0';
+  
+  if (name[namelength] != '\0')
+    {
+      buf = alloca (namelength + 1);
+      /* Create local copy of the partial symbol */
+      memcpy (buf, name, namelength);
+      buf[namelength] = '\0';
+    }
   /* val and coreaddr are mutually exclusive, one of them *will* be zero */
   if (val != 0)
     {
@@ -3002,17 +3126,62 @@ add_psymbol_to_list (char *name, int namelength, domain_enum domain,
   SYMBOL_SET_NAMES (&psymbol, buf, namelength, objfile);
 
   /* Stash the partial symbol away in the cache */
-  psym = deprecated_bcache (&psymbol, sizeof (struct partial_symbol),
-                           objfile->psymbol_cache);
+  return deprecated_bcache_added (&psymbol, sizeof (struct partial_symbol),
+                                 objfile->psymbol_cache, added);
+}
 
-  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+/* Helper function, adds partial symbol to the given partial symbol
+   list.  */
+
+static void
+append_psymbol_to_list (struct psymbol_allocation_list *list,
+                       struct partial_symbol *psym,
+                       struct objfile *objfile)
+{
   if (list->next >= list->list + list->size)
-    {
-      extend_psymbol_list (list, objfile);
-    }
+    extend_psymbol_list (list, objfile);
   *list->next++ = psym;
   OBJSTAT (objfile, n_psyms++);
+}
+
+/* Add a symbol with a long value to a psymtab.
+   Since one arg is a struct, we pass in a ptr and deref it (sigh).
+   Return the partial symbol that has been added.  */
+
+/* NOTE: carlton/2003-09-11: The reason why we return the partial
+   symbol is so that callers can get access to the symbol's demangled
+   name, which they don't have any cheap way to determine otherwise.
+   (Currenly, dwarf2read.c is the only file who uses that information,
+   though it's possible that other readers might in the future.)
+   Elena wasn't thrilled about that, and I don't blame her, but we
+   couldn't come up with a better way to get that information.  If
+   it's needed in other situations, we could consider breaking up
+   SYMBOL_SET_NAMES to provide access to the demangled name lookup
+   cache.  */
+
+const struct partial_symbol *
+add_psymbol_to_list (char *name, int namelength, domain_enum domain,
+                    enum address_class class,
+                    struct psymbol_allocation_list *list, 
+                    long val,  /* Value as a long */
+                    CORE_ADDR coreaddr,        /* Value as a CORE_ADDR */
+                    enum language language, struct objfile *objfile)
+{
+  struct partial_symbol *psym;
+
+  int added;
+
+  /* Stash the partial symbol away in the cache */
+  psym = add_psymbol_to_bcache (name, namelength, domain, class,
+                               val, coreaddr, language, objfile, &added);
 
+  /* Do not duplicate global partial symbols.  */
+  if (list == &objfile->global_psymbols
+      && !added)
+    return psym;
+
+  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+  append_psymbol_to_list (list, psym, objfile);
   return psym;
 }
 
@@ -3388,13 +3557,13 @@ list_overlays_command (char *args, int from_tty)
        name = bfd_section_name (objfile->obfd, osect->the_bfd_section);
 
        printf_filtered ("Section %s, loaded at ", name);
-       deprecated_print_address_numeric (lma, 1, gdb_stdout);
+       fputs_filtered (paddress (lma), gdb_stdout);
        puts_filtered (" - ");
-       deprecated_print_address_numeric (lma + size, 1, gdb_stdout);
+       fputs_filtered (paddress (lma + size), gdb_stdout);
        printf_filtered (", mapped at ");
-       deprecated_print_address_numeric (vma, 1, gdb_stdout);
+       fputs_filtered (paddress (vma), gdb_stdout);
        puts_filtered (" - ");
-       deprecated_print_address_numeric (vma + size, 1, gdb_stdout);
+       fputs_filtered (paddress (vma + size), gdb_stdout);
        puts_filtered ("\n");
 
        nmapped++;
@@ -3858,6 +4027,21 @@ free_symfile_segment_data (struct symfile_segment_data *data)
   xfree (data);
 }
 
+
+/* Given:
+   - DATA, containing segment addresses from the object file ABFD, and
+     the mapping from ABFD's sections onto the segments that own them,
+     and
+   - SEGMENT_BASES[0 .. NUM_SEGMENT_BASES - 1], holding the actual
+     segment addresses reported by the target,
+   store the appropriate offsets for each section in OFFSETS.
+
+   If there are fewer entries in SEGMENT_BASES than there are segments
+   in DATA, then apply SEGMENT_BASES' last entry to all the segments.
+
+   If there are more entries, then ignore the extra.  The target may
+   not be able to distinguish between an empty data segment and a
+   missing data segment; a missing text segment is less plausible.  */
 int
 symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
                                 struct section_offsets *offsets,
@@ -3867,33 +4051,33 @@ symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
   int i;
   asection *sect;
 
+  /* It doesn't make sense to call this function unless you have some
+     segment base addresses.  */
+  gdb_assert (segment_bases > 0);
+
   /* If we do not have segment mappings for the object file, we
      can not relocate it by segments.  */
   gdb_assert (data != NULL);
   gdb_assert (data->num_segments > 0);
 
-  /* If more offsets are provided than we have segments, make sure the
-     excess offsets are all the same as the last segment's offset.
-     This allows "Text=X;Data=X" for files which have only a single
-     segment.  */
-  if (num_segment_bases > data->num_segments)
-    for (i = data->num_segments; i < num_segment_bases; i++)
-      if (segment_bases[i] != segment_bases[data->num_segments - 1])
-       return 0;
-
   for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
     {
-      CORE_ADDR vma;
       int which = data->segment_info[i];
 
+      gdb_assert (0 <= which && which <= data->num_segments);
+
+      /* Don't bother computing offsets for sections that aren't
+         loaded as part of any segment.  */
+      if (! which)
+        continue;
+
+      /* Use the last SEGMENT_BASES entry as the address of any extra
+         segments mentioned in DATA->segment_info.  */
       if (which > num_segment_bases)
-       offsets->offsets[i] = segment_bases[num_segment_bases - 1];
-      else if (which > 0)
-       offsets->offsets[i] = segment_bases[which - 1];
-      else
-       continue;
+        which = num_segment_bases;
 
-      offsets->offsets[i] -= data->segment_bases[which - 1];
+      offsets->offsets[i] = (segment_bases[which - 1]
+                             - data->segment_bases[which - 1]);
     }
 
   return 1;
This page took 0.029903 seconds and 4 git commands to generate.