merge from gcc
[deliverable/binutils-gdb.git] / gdb / elfread.c
index 8a757e4fc678528958f5fca17bcbd86a2ec5f11c..e479a7698a79738adef1b39b0c3d6e6791a11f2d 100644 (file)
@@ -1,27 +1,31 @@
 /* Read ELF (Executable and Linking Format) object files for GDB.
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+   Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+
    Written by Fred Fish at Cygnus Support.
 
-This file is part of GDB.
+   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
-(at your option) any later version.
+   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 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "bfd.h"
 #include "gdb_string.h"
 #include "elf-bfd.h"
+#include "elf/common.h"
+#include "elf/internal.h"
 #include "elf/mips.h"
 #include "symtab.h"
 #include "symfile.h"
@@ -32,59 +36,90 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "complaints.h"
 #include "demangle.h"
 
+extern void _initialize_elfread (void);
+
 /* The struct elfinfo is available only during ELF symbol table and
-   psymtab reading.  It is destroyed at the complation of psymtab-reading.
+   psymtab reading.  It is destroyed at the completion of psymtab-reading.
    It's local to elf_symfile_read.  */
 
-struct elfinfo {
-  file_ptr dboffset;           /* Offset to dwarf debug section */
-  unsigned int dbsize;         /* Size of dwarf debug section */
-  file_ptr lnoffset;           /* Offset to dwarf line number section */
-  unsigned int lnsize;         /* Size of dwarf line number section */
-  asection *stabsect;          /* Section pointer for .stab section */
-  asection *stabindexsect;     /* Section pointer for .stab.index section */
-  asection *mdebugsect;                /* Section pointer for .mdebug section */
-};
-
-/* Various things we might complain about... */
+struct elfinfo
+  {
+    asection *stabsect;                /* Section pointer for .stab section */
+    asection *stabindexsect;   /* Section pointer for .stab.index section */
+    asection *mdebugsect;      /* Section pointer for .mdebug section */
+  };
 
-struct complaint section_info_complaint = 
-  {"elf/stab section information %s without a preceding file symbol", 0, 0};
+static void free_elfinfo (void *);
 
-struct complaint section_info_dup_complaint = 
-  {"duplicated elf/stab section information for %s", 0, 0};
+/* Locate the segments in ABFD.  */
 
-struct complaint stab_info_mismatch_complaint = 
-  {"elf/stab section information missing for %s", 0, 0};
-
-struct complaint stab_info_questionable_complaint = 
-  {"elf/stab section information questionable for %s", 0, 0};
-
-static void
-elf_symfile_init PARAMS ((struct objfile *));
+static struct symfile_segment_data *
+elf_symfile_segments (bfd *abfd)
+{
+  Elf_Internal_Phdr *phdrs, **segments;
+  long phdrs_size;
+  int num_phdrs, num_segments, num_sections, i;
+  asection *sect;
+  struct symfile_segment_data *data;
+
+  phdrs_size = bfd_get_elf_phdr_upper_bound (abfd);
+  if (phdrs_size == -1)
+    return NULL;
+
+  phdrs = alloca (phdrs_size);
+  num_phdrs = bfd_get_elf_phdrs (abfd, phdrs);
+  if (num_phdrs == -1)
+    return NULL;
+
+  num_segments = 0;
+  segments = alloca (sizeof (Elf_Internal_Phdr *) * num_phdrs);
+  for (i = 0; i < num_phdrs; i++)
+    if (phdrs[i].p_type == PT_LOAD)
+      segments[num_segments++] = &phdrs[i];
+
+  if (num_segments == 0)
+    return NULL;
+
+  data = XZALLOC (struct symfile_segment_data);
+  data->num_segments = num_segments;
+  data->segment_bases = XCALLOC (num_segments, CORE_ADDR);
+  data->segment_sizes = XCALLOC (num_segments, CORE_ADDR);
+
+  for (i = 0; i < num_segments; i++)
+    {
+      data->segment_bases[i] = segments[i]->p_vaddr;
+      data->segment_sizes[i] = segments[i]->p_memsz;
+    }
 
-static void
-elf_new_init PARAMS ((struct objfile *));
+  num_sections = bfd_count_sections (abfd);
+  data->segment_info = XCALLOC (num_sections, int);
 
-static void
-elf_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      int j;
+      CORE_ADDR vma;
 
-static void
-elf_symfile_finish PARAMS ((struct objfile *));
+      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+       continue;
 
-static void
-elf_symtab_read PARAMS ((bfd *,  CORE_ADDR, struct objfile *, int));
+      vma = bfd_get_section_vma (abfd, sect);
 
-static void
-free_elfinfo PARAMS ((void *));
+      for (j = 0; j < num_segments; j++)
+       if (segments[j]->p_memsz > 0
+           && vma >= segments[j]->p_vaddr
+           && vma < segments[j]->p_vaddr + segments[j]->p_memsz)
+         {
+           data->segment_info[i] = j + 1;
+           break;
+         }
 
-static struct minimal_symbol *
-record_minimal_symbol_and_info PARAMS ((char *, CORE_ADDR,
-                                       enum minimal_symbol_type, char *,
-                                       struct objfile *));
+      if (bfd_get_section_size (sect) > 0 && j == num_segments)
+       warning (_("Loadable segment \"%s\" outside of ELF segments"),
+                bfd_section_name (abfd, sect));
+    }
 
-static void
-elf_locate_sections PARAMS ((bfd *, asection *, void *));
+  return data;
+}
 
 /* We are called once per section from elf_symfile_read.  We
    need to examine each section we are passed, check to see
@@ -106,147 +141,71 @@ elf_locate_sections PARAMS ((bfd *, asection *, void *));
    -kingdon).  */
 
 static void
-elf_locate_sections (ignore_abfd, sectp, eip)
-     bfd *ignore_abfd;
-     asection *sectp;
-     PTR eip;
+elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip)
 {
-  register struct elfinfo *ei;
+  struct elfinfo *ei;
 
   ei = (struct elfinfo *) eip;
-  if (STREQ (sectp -> name, ".debug"))
-    {
-      ei -> dboffset = sectp -> filepos;
-      ei -> dbsize = bfd_get_section_size_before_reloc (sectp);
-    }
-  else if (STREQ (sectp -> name, ".line"))
-    {
-      ei -> lnoffset = sectp -> filepos;
-      ei -> lnsize = bfd_get_section_size_before_reloc (sectp);
-    }
-  else if (STREQ (sectp -> name, ".stab"))
+  if (strcmp (sectp->name, ".stab") == 0)
     {
-      ei -> stabsect = sectp;
+      ei->stabsect = sectp;
     }
-  else if (STREQ (sectp -> name, ".stab.index"))
+  else if (strcmp (sectp->name, ".stab.index") == 0)
     {
-      ei -> stabindexsect = sectp;
+      ei->stabindexsect = sectp;
     }
-  else if (STREQ (sectp -> name, ".mdebug"))
+  else if (strcmp (sectp->name, ".mdebug") == 0)
     {
-      ei -> mdebugsect = sectp;
+      ei->mdebugsect = sectp;
     }
 }
 
-#if 0  /* Currently unused */
-
-char *
-elf_interpreter (abfd)
-     bfd *abfd;
-{
-  sec_ptr interp_sec;
-  unsigned size;
-  char *interp = NULL;
-
-  interp_sec = bfd_get_section_by_name (abfd, ".interp");
-  if (interp_sec)
-    {
-      size = bfd_section_size (abfd, interp_sec);
-      interp = alloca (size);
-      if (bfd_get_section_contents (abfd, interp_sec, interp, (file_ptr)0,
-                                   size))
-       {
-         interp = savestring (interp, size - 1);
-       }
-      else
-       {
-         interp = NULL;
-       }
-    }
-  return (interp);
-}
-
-#endif
-
 static struct minimal_symbol *
-record_minimal_symbol_and_info (name, address, ms_type, info, objfile)
-     char *name;
-     CORE_ADDR address;
-     enum minimal_symbol_type ms_type;
-     char *info;               /* FIXME, is this really char *? */
-     struct objfile *objfile;
+record_minimal_symbol (char *name, CORE_ADDR address,
+                      enum minimal_symbol_type ms_type,
+                      asection *bfd_section, struct objfile *objfile)
 {
-  int section;
-
-  /* Guess the section from the type.  This is likely to be wrong in
-     some cases.  */
-  switch (ms_type)
-    {
-    case mst_text:
-    case mst_file_text:
-      section = SECT_OFF_TEXT;
-#ifdef SMASH_TEXT_ADDRESS
-      SMASH_TEXT_ADDRESS (address);
-#endif
-      break;
-    case mst_data:
-    case mst_file_data:
-      section = SECT_OFF_DATA;
-      break;
-    case mst_bss:
-    case mst_file_bss:
-      section = SECT_OFF_BSS;
-      break;
-    default:
-      section = -1;
-      break;
-    }
+  if (ms_type == mst_text || ms_type == mst_file_text)
+    address = gdbarch_smash_text_address (current_gdbarch, address);
 
   return prim_record_minimal_symbol_and_info
-    (name, address, ms_type, info, section, objfile);
+    (name, address, ms_type, NULL, bfd_section->index, bfd_section, objfile);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       elf_symtab_read -- read the symbol table of an ELF file
+   elf_symtab_read -- read the symbol table of an ELF file
 
-SYNOPSIS
+   SYNOPSIS
 
-       void elf_symtab_read (bfd *abfd, CORE_ADDR addr,
-                             struct objfile *objfile, int dynamic)
+   void elf_symtab_read (struct objfile *objfile, int dynamic,
+                        long number_of_symbols, asymbol **symbol_table)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given an open bfd, a base address to relocate symbols to, and a
-       flag that specifies whether or not this bfd is for an executable
-       or not (may be shared library for example), add all the global
-       function and data symbols to the minimal symbol table.
+   Given an objfile, a symbol table, and a flag indicating whether the
+   symbol table contains dynamic symbols, add all the global function
+   and data symbols to the minimal symbol table.
 
-       In stabs-in-ELF, as implemented by Sun, there are some local symbols
-       defined in the ELF symbol table, which can be used to locate
-       the beginnings of sections from each ".o" file that was linked to
-       form the executable objfile.  We gather any such info and record it
-       in data structures hung off the objfile's private data.
+   In stabs-in-ELF, as implemented by Sun, there are some local symbols
+   defined in the ELF symbol table, which can be used to locate
+   the beginnings of sections from each ".o" file that was linked to
+   form the executable objfile.  We gather any such info and record it
+   in data structures hung off the objfile's private data.
 
-*/
+ */
 
 static void
-elf_symtab_read (abfd, addr, objfile, dynamic)
-     bfd *abfd;
-     CORE_ADDR addr;
-     struct objfile *objfile;
-     int dynamic;
+elf_symtab_read (struct objfile *objfile, int dynamic,
+                long number_of_symbols, asymbol **symbol_table)
 {
   long storage_needed;
   asymbol *sym;
-  asymbol **symbol_table;
-  long number_of_symbols;
   long i;
-  int index;
-  struct cleanup *back_to;
   CORE_ADDR symaddr;
+  CORE_ADDR offset;
   enum minimal_symbol_type ms_type;
   /* If sectinfo is nonNULL, it contains section info that should end up
      filed in the objfile.  */
@@ -254,271 +213,267 @@ elf_symtab_read (abfd, addr, objfile, dynamic)
   /* If filesym is nonzero, it points to a file symbol, but we haven't
      seen any section info for it yet.  */
   asymbol *filesym = 0;
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
-  /* Name of filesym, as saved on the symbol_obstack.  */
-  char *filesymname = obsavestring ("", 0, &objfile->symbol_obstack);
-#endif
-  struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
-                                objfile->sym_stab_info;
-  unsigned long size;
-  int stripped = (bfd_get_symcount (abfd) == 0);
-  if (dynamic)
-    {
-      storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
+  /* Name of filesym, as saved on the objfile_obstack.  */
+  char *filesymname = obsavestring ("", 0, &objfile->objfile_obstack);
+  struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
+  int stripped = (bfd_get_symcount (objfile->obfd) == 0);
 
-      /* Nothing to be done if there is no dynamic symtab.  */
-      if (storage_needed < 0)
-       return;
-    }
-  else
-    {
-      storage_needed = bfd_get_symtab_upper_bound (abfd);
-      if (storage_needed < 0)
-       error ("Can't read symbols from %s: %s", bfd_get_filename (abfd),
-              bfd_errmsg (bfd_get_error ()));
-    }
-  if (storage_needed > 0)
+  for (i = 0; i < number_of_symbols; i++)
     {
-      symbol_table = (asymbol **) xmalloc (storage_needed);
-      back_to = make_cleanup (free, symbol_table);
-      if (dynamic)
-        number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd,
-                                                            symbol_table);
-      else
-        number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
-      if (number_of_symbols < 0)
-       error ("Can't read symbols from %s: %s", bfd_get_filename (abfd),
-              bfd_errmsg (bfd_get_error ()));
-      for (i = 0; i < number_of_symbols; i++)
+      sym = symbol_table[i];
+      if (sym->name == NULL || *sym->name == '\0')
+       {
+         /* Skip names that don't exist (shouldn't happen), or names
+            that are null strings (may happen). */
+         continue;
+       }
+
+      /* Skip "special" symbols, e.g. ARM mapping symbols.  These are
+        symbols which do not correspond to objects in the symbol table,
+        but have some other target-specific meaning.  */
+      if (bfd_is_target_special_symbol (objfile->obfd, sym))
+       continue;
+
+      offset = ANOFFSET (objfile->section_offsets, sym->section->index);
+      if (dynamic
+         && sym->section == &bfd_und_section
+         && (sym->flags & BSF_FUNCTION))
+       {
+         struct minimal_symbol *msym;
+
+         /* Symbol is a reference to a function defined in
+            a shared library.
+            If its value is non zero then it is usually the address
+            of the corresponding entry in the procedure linkage table,
+            plus the desired section offset.
+            If its value is zero then the dynamic linker has to resolve
+            the symbol. We are unable to find any meaningful address
+            for this symbol in the executable file, so we skip it.  */
+         symaddr = sym->value;
+         if (symaddr == 0)
+           continue;
+         symaddr += offset;
+         msym = record_minimal_symbol
+           ((char *) sym->name, symaddr,
+            mst_solib_trampoline, sym->section, objfile);
+         if (msym != NULL)
+           msym->filename = filesymname;
+         continue;
+       }
+
+      /* If it is a nonstripped executable, do not enter dynamic
+        symbols, as the dynamic symbol table is usually a subset
+        of the main symbol table.  */
+      if (dynamic && !stripped)
+       continue;
+      if (sym->flags & BSF_FILE)
        {
-         sym = symbol_table[i];
-         if (sym -> name == NULL || *sym -> name == '\0')
+         /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
+            Chain any old one onto the objfile; remember new sym.  */
+         if (sectinfo != NULL)
            {
-             /* Skip names that don't exist (shouldn't happen), or names
-                that are null strings (may happen). */
-             continue;
+             sectinfo->next = dbx->stab_section_info;
+             dbx->stab_section_info = sectinfo;
+             sectinfo = NULL;
            }
-
-         if (dynamic
-             && sym -> section == &bfd_und_section
-             && (sym -> flags & BSF_FUNCTION))
+         filesym = sym;
+         filesymname =
+           obsavestring ((char *) filesym->name, strlen (filesym->name),
+                         &objfile->objfile_obstack);
+       }
+      else if (sym->flags & BSF_SECTION_SYM)
+       continue;
+      else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+       {
+         struct minimal_symbol *msym;
+
+         /* Select global/local/weak symbols.  Note that bfd puts abs
+            symbols in their own section, so all symbols we are
+            interested in will have a section. */
+         /* Bfd symbols are section relative. */
+         symaddr = sym->value + sym->section->vma;
+         /* Relocate all non-absolute symbols by the section offset.  */
+         if (sym->section != &bfd_abs_section)
            {
-             struct minimal_symbol *msym;
-
-             /* Symbol is a reference to a function defined in
-                a shared library.
-                If its value is non zero then it is usually the address
-                of the corresponding entry in the procedure linkage table,
-                relative to the base address.
-                If its value is zero then the dynamic linker has to resolve
-                the symbol. We are unable to find any meaningful address
-                for this symbol in the executable file, so we skip it.  */
-             symaddr = sym -> value;
-             if (symaddr == 0)
-               continue;
-             symaddr += addr;
-             msym = record_minimal_symbol_and_info
-               ((char *) sym -> name, symaddr,
-               mst_solib_trampoline, NULL, objfile);
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
-             if (msym != NULL)
-               msym->filename = filesymname;
-#endif
-             continue;
+             symaddr += offset;
            }
-
-         /* If it is a nonstripped executable, do not enter dynamic
-            symbols, as the dynamic symbol table is usually a subset
-            of the main symbol table.  */
-         if (dynamic && !stripped)
-           continue;
-         if (sym -> flags & BSF_FILE)
+         /* For non-absolute symbols, use the type of the section
+            they are relative to, to intuit text/data.  Bfd provides
+            no way of figuring this out for absolute symbols. */
+         if (sym->section == &bfd_abs_section)
            {
-             /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
-                Chain any old one onto the objfile; remember new sym.  */
-             if (sectinfo != NULL)
+             /* This is a hack to get the minimal symbol type
+                right for Irix 5, which has absolute addresses
+                with special section indices for dynamic symbols. */
+             unsigned short shndx =
+               ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;
+
+             switch (shndx)
                {
-                 sectinfo -> next = dbx -> stab_section_info;
-                 dbx -> stab_section_info = sectinfo;
-                 sectinfo = NULL;
+               case SHN_MIPS_TEXT:
+                 ms_type = mst_text;
+                 break;
+               case SHN_MIPS_DATA:
+                 ms_type = mst_data;
+                 break;
+               case SHN_MIPS_ACOMMON:
+                 ms_type = mst_bss;
+                 break;
+               default:
+                 ms_type = mst_abs;
+               }
+
+             /* If it is an Irix dynamic symbol, skip section name
+                symbols, relocate all others by section offset. */
+             if (ms_type != mst_abs)
+               {
+                 if (sym->name[0] == '.')
+                   continue;
+                 symaddr += offset;
                }
-             filesym = sym;
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
-             filesymname =
-               obsavestring ((char *)filesym->name, strlen (filesym->name),
-                             &objfile->symbol_obstack);
-#endif
            }
-         else if (sym -> flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+         else if (sym->section->flags & SEC_CODE)
            {
-             struct minimal_symbol *msym;
-
-             /* Select global/local/weak symbols.  Note that bfd puts abs
-                symbols in their own section, so all symbols we are
-                interested in will have a section. */
-             /* Bfd symbols are section relative. */
-             symaddr = sym -> value + sym -> section -> vma;
-             /* Relocate all non-absolute symbols by base address.  */
-             if (sym -> section != &bfd_abs_section)
+             if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
                {
-                 symaddr += addr;
+                 ms_type = mst_text;
                }
-             /* For non-absolute symbols, use the type of the section
-                they are relative to, to intuit text/data.  Bfd provides
-                no way of figuring this out for absolute symbols. */
-             if (sym -> section == &bfd_abs_section)
+             else if ((sym->name[0] == '.' && sym->name[1] == 'L')
+                      || ((sym->flags & BSF_LOCAL)
+                          && sym->name[0] == '$'
+                          && sym->name[1] == 'L'))
+               /* Looks like a compiler-generated label.  Skip
+                  it.  The assembler should be skipping these (to
+                  keep executables small), but apparently with
+                  gcc on the (deleted) delta m88k SVR4, it loses.
+                  So to have us check too should be harmless (but
+                  I encourage people to fix this in the assembler
+                  instead of adding checks here).  */
+               continue;
+             else
                {
-                 /* This is a hack to get the minimal symbol type
-                    right for Irix 5, which has absolute adresses
-                    with special section indices for dynamic symbols. */
-                 unsigned short shndx =
-                   ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;
-
-                 switch (shndx)
-                   {
-                   case SHN_MIPS_TEXT:
-                     ms_type = mst_text;
-                     break;
-                   case SHN_MIPS_DATA:
-                     ms_type = mst_data;
-                     break;
-                   case SHN_MIPS_ACOMMON:
-                     ms_type = mst_bss;
-                     break;
-                   default:
-                     ms_type = mst_abs;
-                   }
+                 ms_type = mst_file_text;
                }
-             else if (sym -> section -> flags & SEC_CODE)
+           }
+         else if (sym->section->flags & SEC_ALLOC)
+           {
+             if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
                {
-                 if (sym -> flags & BSF_GLOBAL)
+                 if (sym->section->flags & SEC_LOAD)
                    {
-                     ms_type = mst_text;
+                     ms_type = mst_data;
                    }
-                 else if ((sym->name[0] == '.' && sym->name[1] == 'L')
-                          || ((sym -> flags & BSF_LOCAL)
-                              && sym->name[0] == '$'
-                              && sym->name[1] == 'L'))
-                   /* Looks like a compiler-generated label.  Skip it.
-                      The assembler should be skipping these (to keep
-                      executables small), but apparently with gcc on the
-                      delta m88k SVR4, it loses.  So to have us check too
-                      should be harmless (but I encourage people to fix this
-                      in the assembler instead of adding checks here).  */
-                   continue;
                  else
                    {
-                     ms_type = mst_file_text;
+                     ms_type = mst_bss;
                    }
                }
-             else if (sym -> section -> flags & SEC_ALLOC)
+             else if (sym->flags & BSF_LOCAL)
                {
-                 if (sym -> flags & BSF_GLOBAL)
-                   {
-                     if (sym -> section -> flags & SEC_LOAD)
-                       {
-                         ms_type = mst_data;
-                       }
-                     else
-                       {
-                         ms_type = mst_bss;
-                       }
-                   }
-                 else if (sym -> flags & BSF_LOCAL)
+                 /* Named Local variable in a Data section.
+                    Check its name for stabs-in-elf.  */
+                 int special_local_sect;
+                 if (strcmp ("Bbss.bss", sym->name) == 0)
+                   special_local_sect = SECT_OFF_BSS (objfile);
+                 else if (strcmp ("Ddata.data", sym->name) == 0)
+                   special_local_sect = SECT_OFF_DATA (objfile);
+                 else if (strcmp ("Drodata.rodata", sym->name) == 0)
+                   special_local_sect = SECT_OFF_RODATA (objfile);
+                 else
+                   special_local_sect = -1;
+                 if (special_local_sect >= 0)
                    {
-                     /* Named Local variable in a Data section.  Check its
-                        name for stabs-in-elf.  The STREQ macro checks the
-                        first character inline, so we only actually do a
-                        strcmp function call on names that start with 'B'
-                        or 'D' */
-                     index = SECT_OFF_MAX;
-                     if (STREQ ("Bbss.bss", sym -> name))
-                       {
-                         index = SECT_OFF_BSS;
-                       }
-                     else if (STREQ ("Ddata.data", sym -> name))
-                       {
-                         index = SECT_OFF_DATA;
-                       }
-                     else if (STREQ ("Drodata.rodata", sym -> name))
+                     /* Found a special local symbol.  Allocate a
+                        sectinfo, if needed, and fill it in.  */
+                     if (sectinfo == NULL)
                        {
-                         index = SECT_OFF_RODATA;
-                       }
-                     if (index != SECT_OFF_MAX)
-                       {
-                         /* Found a special local symbol.  Allocate a
-                            sectinfo, if needed, and fill it in.  */
-                         if (sectinfo == NULL)
+                         int max_index;
+                         size_t size;
+
+                         max_index 
+                           = max (SECT_OFF_BSS (objfile),
+                                  max (SECT_OFF_DATA (objfile),
+                                       SECT_OFF_RODATA (objfile)));
+
+                         /* max_index is the largest index we'll
+                            use into this array, so we must
+                            allocate max_index+1 elements for it.
+                            However, 'struct stab_section_info'
+                            already includes one element, so we
+                            need to allocate max_index aadditional
+                            elements.  */
+                         size = (sizeof (struct stab_section_info) 
+                                 + (sizeof (CORE_ADDR)
+                                    * max_index));
+                         sectinfo = (struct stab_section_info *)
+                           xmalloc (size);
+                         memset (sectinfo, 0, size);
+                         sectinfo->num_sections = max_index;
+                         if (filesym == NULL)
                            {
-                             sectinfo = (struct stab_section_info *)
-                               xmmalloc (objfile -> md, sizeof (*sectinfo));
-                             memset ((PTR) sectinfo, 0, sizeof (*sectinfo));
-                             if (filesym == NULL)
-                               {
-                                 complain (&section_info_complaint,
-                                           sym -> name);
-                               }
-                             else
-                               {
-                                 sectinfo -> filename =
-                                   (char *) filesym -> name;
-                               }
+                             complaint (&symfile_complaints,
+                                        _("elf/stab section information %s without a preceding file symbol"),
+                                        sym->name);
                            }
-                         if (sectinfo -> sections[index] != 0)
+                         else
                            {
-                             complain (&section_info_dup_complaint,
-                                       sectinfo -> filename);
+                             sectinfo->filename =
+                               (char *) filesym->name;
                            }
-                         /* Bfd symbols are section relative. */
-                         symaddr = sym -> value + sym -> section -> vma;
-                         /* Relocate non-absolute symbols by base address.  */
-                         if (sym -> section != &bfd_abs_section)
-                           {
-                             symaddr += addr;
-                           }
-                         sectinfo -> sections[index] = symaddr;
-                         /* The special local symbols don't go in the
-                            minimal symbol table, so ignore this one. */
-                         continue;
-                       }
-                     /* Not a special stabs-in-elf symbol, do regular
-                        symbol processing. */
-                     if (sym -> section -> flags & SEC_LOAD)
-                       {
-                         ms_type = mst_file_data;
-                       }
-                     else
-                       {
-                         ms_type = mst_file_bss;
                        }
+                     if (sectinfo->sections[special_local_sect] != 0)
+                       complaint (&symfile_complaints,
+                                  _("duplicated elf/stab section information for %s"),
+                                  sectinfo->filename);
+                     /* BFD symbols are section relative.  */
+                     symaddr = sym->value + sym->section->vma;
+                     /* Relocate non-absolute symbols by the
+                        section offset.  */
+                     if (sym->section != &bfd_abs_section)
+                       symaddr += offset;
+                     sectinfo->sections[special_local_sect] = symaddr;
+                     /* The special local symbols don't go in the
+                        minimal symbol table, so ignore this one.  */
+                     continue;
+                   }
+                 /* Not a special stabs-in-elf symbol, do regular
+                    symbol processing.  */
+                 if (sym->section->flags & SEC_LOAD)
+                   {
+                     ms_type = mst_file_data;
                    }
                  else
                    {
-                     ms_type = mst_unknown;
+                     ms_type = mst_file_bss;
                    }
                }
              else
                {
-                 /* FIXME:  Solaris2 shared libraries include lots of
-                    odd "absolute" and "undefined" symbols, that play 
-                    hob with actions like finding what function the PC
-                    is in.  Ignore them if they aren't text, data, or bss.  */
-                 /* ms_type = mst_unknown; */
-                 continue;             /* Skip this symbol. */
+                 ms_type = mst_unknown;
                }
+           }
+         else
+           {
+             /* FIXME:  Solaris2 shared libraries include lots of
+                odd "absolute" and "undefined" symbols, that play 
+                hob with actions like finding what function the PC
+                is in.  Ignore them if they aren't text, data, or bss.  */
+             /* ms_type = mst_unknown; */
+             continue; /* Skip this symbol. */
+           }
+         msym = record_minimal_symbol
+           ((char *) sym->name, symaddr,
+            ms_type, sym->section, objfile);
+         if (msym)
+           {
              /* Pass symbol size field in via BFD.  FIXME!!!  */
-             size = ((elf_symbol_type *) sym) -> internal_elf_sym.st_size;
-             msym = record_minimal_symbol_and_info
-               ((char *) sym -> name, symaddr,
-                ms_type, (PTR) size, objfile);
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
-             if (msym != NULL)
-               msym->filename = filesymname;
-#endif
+             unsigned long size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+             MSYMBOL_SIZE(msym) = size;
            }
+         if (msym != NULL)
+           msym->filename = filesymname;
+         gdbarch_elf_make_msymbol_special (current_gdbarch, sym, msym);
        }
-      do_cleanups (back_to);
     }
 }
 
@@ -544,7 +499,6 @@ elf_symtab_read (abfd, addr, objfile, dynamic)
    We look for sections with specific names, to tell us what debug
    format to look for:  FIXME!!!
 
-   dwarf_build_psymtabs() builds psymtabs for DWARF symbols;
    elfstab_build_psymtabs() handles STABS symbols;
    mdebug_build_psymtabs() handles ECOFF debugging information.
 
@@ -555,106 +509,174 @@ elf_symtab_read (abfd, addr, objfile, dynamic)
    capability even for files compiled without -g.  */
 
 static void
-elf_symfile_read (objfile, section_offsets, mainline)
-     struct objfile *objfile;
-     struct section_offsets *section_offsets;
-     int mainline;
+elf_symfile_read (struct objfile *objfile, int mainline)
 {
   bfd *abfd = objfile->obfd;
   struct elfinfo ei;
   struct cleanup *back_to;
   CORE_ADDR offset;
+  long symcount = 0, dynsymcount = 0, synthcount, storage_needed;
+  asymbol **symbol_table = NULL, **dyn_symbol_table = NULL;
+  asymbol *synthsyms;
 
   init_minimal_symbol_collection ();
-  back_to = make_cleanup (discard_minimal_symbols, 0);
+  back_to = make_cleanup_discard_minimal_symbols ();
 
   memset ((char *) &ei, 0, sizeof (ei));
 
   /* Allocate struct to keep track of the symfile */
-  objfile->sym_stab_info = (PTR)
-    xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
-  memset ((char *) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
-  make_cleanup (free_elfinfo, (PTR) objfile);
+  objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *)
+    xmalloc (sizeof (struct dbx_symfile_info));
+  memset ((char *) objfile->deprecated_sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+  make_cleanup (free_elfinfo, (void *) objfile);
 
   /* Process the normal ELF symbol table first.  This may write some 
-     chain of info into the dbx_symfile_info in objfile->sym_stab_info,
+     chain of info into the dbx_symfile_info in objfile->deprecated_sym_stab_info,
      which can later be used by elfstab_offset_sections.  */
 
-  /* FIXME, should take a section_offsets param, not just an offset.  */
-  offset = ANOFFSET (section_offsets, 0);
-  elf_symtab_read (abfd, offset, objfile, 0);
+  storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
+  if (storage_needed < 0)
+    error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
+          bfd_errmsg (bfd_get_error ()));
+
+  if (storage_needed > 0)
+    {
+      symbol_table = (asymbol **) xmalloc (storage_needed);
+      make_cleanup (xfree, symbol_table);
+      symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
+
+      if (symcount < 0)
+       error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
+              bfd_errmsg (bfd_get_error ()));
+
+      elf_symtab_read (objfile, 0, symcount, symbol_table);
+    }
 
   /* Add the dynamic symbols.  */
 
-  elf_symtab_read (abfd, offset, objfile, 1);
+  storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd);
+
+  if (storage_needed > 0)
+    {
+      dyn_symbol_table = (asymbol **) xmalloc (storage_needed);
+      make_cleanup (xfree, dyn_symbol_table);
+      dynsymcount = bfd_canonicalize_dynamic_symtab (objfile->obfd,
+                                                    dyn_symbol_table);
+
+      if (dynsymcount < 0)
+       error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
+              bfd_errmsg (bfd_get_error ()));
+
+      elf_symtab_read (objfile, 1, dynsymcount, dyn_symbol_table);
+    }
+
+  /* Add synthetic symbols - for instance, names for any PLT entries.  */
+
+  synthcount = bfd_get_synthetic_symtab (abfd, symcount, symbol_table,
+                                        dynsymcount, dyn_symbol_table,
+                                        &synthsyms);
+  if (synthcount > 0)
+    {
+      asymbol **synth_symbol_table;
+      long i;
+
+      make_cleanup (xfree, synthsyms);
+      synth_symbol_table = xmalloc (sizeof (asymbol *) * synthcount);
+      for (i = 0; i < synthcount; i++)
+       synth_symbol_table[i] = synthsyms + i;
+      make_cleanup (xfree, synth_symbol_table);
+      elf_symtab_read (objfile, 0, synthcount, synth_symbol_table);
+    }
+
+  /* Install any minimal symbols that have been collected as the current
+     minimal symbols for this objfile.  The debug readers below this point
+     should not generate new minimal symbols; if they do it's their
+     responsibility to install them.  "mdebug" appears to be the only one
+     which will do this.  */
+
+  install_minimal_symbols (objfile);
+  do_cleanups (back_to);
 
   /* Now process debugging information, which is contained in
-     special ELF sections.  We first have to find them... */
+     special ELF sections. */
 
-  bfd_map_over_sections (abfd, elf_locate_sections, (PTR) &ei);
-  if (ei.dboffset && ei.lnoffset)
+  /* If we are reinitializing, or if we have never loaded syms yet,
+     set table to empty.  MAINLINE is cleared so that *_read_psymtab
+     functions do not all also re-initialize the psymbol table. */
+  if (mainline)
     {
-      /* DWARF sections */
-      dwarf_build_psymtabs (objfile,
-                           section_offsets, mainline,
-                           ei.dboffset, ei.dbsize,
-                           ei.lnoffset, ei.lnsize);
+      init_psymbol_list (objfile, 0);
+      mainline = 0;
+    }
+
+  /* We first have to find them... */
+  bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei);
+
+  /* ELF debugging information is inserted into the psymtab in the
+     order of least informative first - most informative last.  Since
+     the psymtab table is searched `most recent insertion first' this
+     increases the probability that more detailed debug information
+     for a section is found.
+
+     For instance, an object file might contain both .mdebug (XCOFF)
+     and .debug_info (DWARF2) sections then .mdebug is inserted first
+     (searched last) and DWARF2 is inserted last (searched first).  If
+     we don't do this then the XCOFF info is found first - for code in
+     an included file XCOFF info is useless. */
+
+  if (ei.mdebugsect)
+    {
+      const struct ecoff_debug_swap *swap;
+
+      /* .mdebug section, presumably holding ECOFF debugging
+         information.  */
+      swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+      if (swap)
+       elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect);
     }
   if (ei.stabsect)
     {
       asection *str_sect;
 
       /* Stab sections have an associated string table that looks like
-        a separate section.  */
+         a separate section.  */
       str_sect = bfd_get_section_by_name (abfd, ".stabstr");
 
       /* FIXME should probably warn about a stab section without a stabstr.  */
       if (str_sect)
        elfstab_build_psymtabs (objfile,
-                               section_offsets,
                                mainline,
-                               ei.stabsect->filepos,
-                               bfd_section_size (abfd, ei.stabsect),
+                               ei.stabsect,
                                str_sect->filepos,
                                bfd_section_size (abfd, str_sect));
     }
-  if (ei.mdebugsect)
+  if (dwarf2_has_info (objfile))
     {
-      const struct ecoff_debug_swap *swap;
-
-      /* .mdebug section, presumably holding ECOFF debugging
-        information.  */
-      swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
-      if (swap)
-       elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect,
-                                 section_offsets);
+      /* DWARF 2 sections */
+      dwarf2_build_psymtabs (objfile, mainline);
     }
 
-  /* Install any minimal symbols that have been collected as the current
-     minimal symbols for this objfile. */
-
-  install_minimal_symbols (objfile);
-
-  do_cleanups (back_to);
+  /* FIXME: kettenis/20030504: This still needs to be integrated with
+     dwarf2read.c in a better way.  */
+  dwarf2_build_frame_info (objfile);
 }
 
-/* This cleans up the objfile's sym_stab_info pointer, and the chain of
-   stab_section_info's, that might be dangling from it.  */
+/* This cleans up the objfile's deprecated_sym_stab_info pointer, and
+   the chain of stab_section_info's, that might be dangling from
+   it.  */
 
 static void
-free_elfinfo (objp)
-     PTR objp;
+free_elfinfo (void *objp)
 {
-  struct objfile *objfile = (struct objfile *)objp;
-  struct dbx_symfile_info *dbxinfo = (struct dbx_symfile_info *)
-                                    objfile->sym_stab_info;
+  struct objfile *objfile = (struct objfile *) objp;
+  struct dbx_symfile_info *dbxinfo = objfile->deprecated_sym_stab_info;
   struct stab_section_info *ssi, *nssi;
 
   ssi = dbxinfo->stab_section_info;
   while (ssi)
     {
       nssi = ssi->next;
-      mfree (objfile->md, ssi);
+      xfree (ssi);
       ssi = nssi;
     }
 
@@ -669,8 +691,7 @@ free_elfinfo (objp)
    We reinitialize buildsym, since we may be reading stabs from an ELF file.  */
 
 static void
-elf_new_init (ignore)
-     struct objfile *ignore;
+elf_new_init (struct objfile *ignore)
 {
   stabsread_new_init ();
   buildsym_new_init ();
@@ -682,13 +703,14 @@ elf_new_init (ignore)
    objfile struct from the global list of known objfiles. */
 
 static void
-elf_symfile_finish (objfile)
-     struct objfile *objfile;
+elf_symfile_finish (struct objfile *objfile)
 {
-  if (objfile -> sym_stab_info != NULL)
+  if (objfile->deprecated_sym_stab_info != NULL)
     {
-      mfree (objfile -> md, objfile -> sym_stab_info);
+      xfree (objfile->deprecated_sym_stab_info);
     }
+
+  dwarf2_free_objfile (objfile);
 }
 
 /* ELF specific initialization routine for reading symbols.
@@ -701,8 +723,7 @@ elf_symfile_finish (objfile)
    just a stub. */
 
 static void
-elf_symfile_init (objfile)
-     struct objfile *objfile;
+elf_symfile_init (struct objfile *objfile)
 {
   /* ELF objects may be reordered, so set OBJF_REORDERED.  If we
      find this causes a significant slowdown in gdb then we could
@@ -719,13 +740,10 @@ elf_symfile_init (objfile)
    with wierd names.  Go get 'em when needed.  */
 
 void
-elfstab_offset_sections (objfile, pst)
-     struct objfile *objfile;
-     struct partial_symtab *pst;
+elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst)
 {
   char *filename = pst->filename;
-  struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
-                                objfile->sym_stab_info;
+  struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
   struct stab_section_info *maybe = dbx->stab_section_info;
   struct stab_section_info *questionable = 0;
   int i;
@@ -734,7 +752,7 @@ elfstab_offset_sections (objfile, pst)
   /* The ELF symbol info doesn't include path names, so strip the path
      (if any) from the psymtab filename.  */
   while (0 != (p = strchr (filename, '/')))
-    filename = p+1;
+    filename = p + 1;
 
   /* FIXME:  This linear search could speed up significantly
      if it was chained in the right order to match how we search it,
@@ -742,19 +760,20 @@ elfstab_offset_sections (objfile, pst)
   for (; maybe; maybe = maybe->next)
     {
       if (filename[0] == maybe->filename[0]
-         && STREQ (filename, maybe->filename))
+         && strcmp (filename, maybe->filename) == 0)
        {
          /* We found a match.  But there might be several source files
             (from different directories) with the same name.  */
          if (0 == maybe->found)
            break;
-         questionable = maybe;         /* Might use it later.  */
+         questionable = maybe; /* Might use it later.  */
        }
     }
 
   if (maybe == 0 && questionable != 0)
     {
-      complain (&stab_info_questionable_complaint, filename);
+      complaint (&symfile_complaints,
+                _("elf/stab section information questionable for %s"), filename);
       maybe = questionable;
     }
 
@@ -763,18 +782,17 @@ elfstab_offset_sections (objfile, pst)
       /* Found it!  Allocate a new psymtab struct, and fill it in.  */
       maybe->found++;
       pst->section_offsets = (struct section_offsets *)
-       obstack_alloc (&objfile -> psymbol_obstack,
-                      sizeof (struct section_offsets) +
-              sizeof (pst->section_offsets->offsets) * (SECT_OFF_MAX-1));
-
-      for (i = 0; i < SECT_OFF_MAX; i++)
-       ANOFFSET (pst->section_offsets, i) = maybe->sections[i];
+       obstack_alloc (&objfile->objfile_obstack, 
+                      SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
+      for (i = 0; i < maybe->num_sections; i++)
+       (pst->section_offsets)->offsets[i] = maybe->sections[i];
       return;
     }
 
   /* We were unable to find any offsets for this file.  Complain.  */
-  if (dbx->stab_section_info)          /* If there *is* any info, */
-    complain (&stab_info_mismatch_complaint, filename);
+  if (dbx->stab_section_info)  /* If there *is* any info, */
+    complaint (&symfile_complaints,
+              _("elf/stab section information missing for %s"), filename);
 }
 \f
 /* Register that we are able to handle ELF object file formats.  */
@@ -782,17 +800,19 @@ elfstab_offset_sections (objfile, pst)
 static struct sym_fns elf_sym_fns =
 {
   bfd_target_elf_flavour,
-  elf_new_init,                /* sym_new_init: init anything gbl to entire symtab */
-  elf_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
-  elf_symfile_read,    /* sym_read: read a symbol file into symtab */
-  elf_symfile_finish,  /* sym_finish: finished with file, cleanup */
-  default_symfile_offsets,
-                       /* sym_offsets:  Translate ext. to int. relocation */
-  NULL                 /* next: pointer to next struct sym_fns */
+  elf_new_init,                        /* sym_new_init: init anything gbl to entire symtab */
+  elf_symfile_init,            /* sym_init: read initial info, setup for sym_read() */
+  elf_symfile_read,            /* sym_read: read a symbol file into symtab */
+  elf_symfile_finish,          /* sym_finish: finished with file, cleanup */
+  default_symfile_offsets,     /* sym_offsets:  Translate ext. to int. relocation */
+  elf_symfile_segments,                /* sym_segments: Get segment information from
+                                  a file.  */
+  NULL,                         /* sym_read_linetable */
+  NULL                         /* next: pointer to next struct sym_fns */
 };
 
 void
-_initialize_elfread ()
+_initialize_elfread (void)
 {
   add_symtab_fns (&elf_sym_fns);
 }
This page took 0.041604 seconds and 4 git commands to generate.