]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/elfread.c
* coffread.c (coff_sym_fns): Add default_symfile_segments.
[thirdparty/binutils-gdb.git] / gdb / elfread.c
index afb043de1f1f81ff3680dc4949d9352c89510a58..7b84ede6c7165f329f12667307e587b4c3a2f8e1 100644 (file)
@@ -1,5 +1,8 @@
 /* Read ELF (Executable and Linking Format) object files for GDB.
-   Copyright 1991, 92, 93, 94, 95, 96, 1998 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.
 
    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 "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"
@@ -33,7 +38,7 @@
 #include "complaints.h"
 #include "demangle.h"
 
-extern void _initialize_elfread PARAMS ((void));
+extern void _initialize_elfread (void);
 
 /* The struct elfinfo is available only during ELF symbol table and
    psymtab reading.  It is destroyed at the completion of psymtab-reading.
@@ -41,55 +46,82 @@ extern void _initialize_elfread PARAMS ((void));
 
 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 complaint section_info_complaint =
-{"elf/stab section information %s without a preceding file symbol", 0, 0};
-
-struct complaint section_info_dup_complaint =
-{"duplicated elf/stab section information for %s", 0, 0};
-
-struct complaint stab_info_mismatch_complaint =
-{"elf/stab section information missing for %s", 0, 0};
+static void free_elfinfo (void *);
 
-struct complaint stab_info_questionable_complaint =
-{"elf/stab section information questionable for %s", 0, 0};
+/* Locate the segments in ABFD.  */
 
-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 *, 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 ((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 *,
-                                         asection * bfd_section,
-                                         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
@@ -111,106 +143,35 @@ 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;
     }
-  else if (STREQ (sectp->name, ".stab.index"))
+  else if (strcmp (sectp->name, ".stab.index") == 0)
     {
       ei->stabindexsect = sectp;
     }
-  else if (STREQ (sectp->name, ".mdebug"))
+  else if (strcmp (sectp->name, ".mdebug") == 0)
     {
       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, bfd_section,
-                               objfile)
-     char *name;
-     CORE_ADDR address;
-     enum minimal_symbol_type ms_type;
-     char *info;               /* FIXME, is this really char *? */
-     asection *bfd_section;
-     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, bfd_section, objfile);
+    (name, address, ms_type, NULL, bfd_section->index, bfd_section, objfile);
 }
 
 /*
@@ -221,13 +182,14 @@ record_minimal_symbol_and_info (name, address, ms_type, info, bfd_section,
 
    SYNOPSIS
 
-   void elf_symtab_read (struct objfile *objfile, int dynamic)
+   void elf_symtab_read (struct objfile *objfile, int dynamic,
+                        long number_of_symbols, asymbol **symbol_table)
 
    DESCRIPTION
 
-   Given an objfile and a flag that specifies whether or not the objfile
-   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
@@ -238,17 +200,12 @@ record_minimal_symbol_and_info (name, address, ms_type, info, bfd_section,
  */
 
 static void
-elf_symtab_read (objfile, dynamic)
-     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;
@@ -259,294 +216,274 @@ elf_symtab_read (objfile, dynamic)
      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);
+  /* Name of filesym, as saved on the objfile_obstack.  */
+  char *filesymname = obsavestring ("", 0, &objfile->objfile_obstack);
 #endif
-  struct dbx_symfile_info *dbx = objfile->sym_stab_info;
-  unsigned long size;
+  struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
   int stripped = (bfd_get_symcount (objfile->obfd) == 0);
 
-  if (dynamic)
+  for (i = 0; i < number_of_symbols; i++)
     {
-      storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd);
+      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;
+       }
 
-      /* Nothing to be done if there is no dynamic symtab.  */
-      if (storage_needed < 0)
-       return;
-    }
-  else
-    {
-      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);
-      back_to = make_cleanup (free, symbol_table);
-      if (dynamic)
-       number_of_symbols = bfd_canonicalize_dynamic_symtab (objfile->obfd,
-                                                            symbol_table);
-      else
-       number_of_symbols = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
-      if (number_of_symbols < 0)
-       error ("Can't read symbols from %s: %s", bfd_get_filename (objfile->obfd),
-              bfd_errmsg (bfd_get_error ()));
-      /* FIXME: Should use section specific offset, not SECT_OFF_TEXT. */
-      offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT);
-      for (i = 0; i < number_of_symbols; i++)
+      /* 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))
        {
-         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;
-           }
+         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);
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+         if (msym != NULL)
+           msym->filename = filesymname;
+#endif
+         continue;
+       }
 
-         if (dynamic
-             && sym->section == &bfd_und_section
-             && (sym->flags & BSF_FUNCTION))
+      /* 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)
+       {
+         /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
+            Chain any old one onto the objfile; remember new sym.  */
+         if (sectinfo != NULL)
            {
-             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_and_info
-               ((char *) sym->name, symaddr,
-                mst_solib_trampoline, NULL, sym->section, objfile);
+             sectinfo->next = dbx->stab_section_info;
+             dbx->stab_section_info = sectinfo;
+             sectinfo = NULL;
+           }
+         filesym = sym;
 #ifdef SOFUN_ADDRESS_MAYBE_MISSING
-             if (msym != NULL)
-               msym->filename = filesymname;
+         filesymname =
+           obsavestring ((char *) filesym->name, strlen (filesym->name),
+                         &objfile->objfile_obstack);
 #endif
-             continue;
+       }
+      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)
+           {
+             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 the section offset.  */
-             if (sym->section != &bfd_abs_section)
+             if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
                {
-                 symaddr += offset;
+                 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;
-                   }
-
-                 /* 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;
-                   }
+                 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;
-                   }
-                 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;
-#ifdef HARRIS_TARGET
-                 else if (sym->name[0] == '.' && sym->name[1] == '.')
-                   {
-                     /* Looks like a Harris compiler generated label for the
-                        purpose of marking instructions that are relevant to
-                        DWARF dies.  The assembler can't get rid of these 
-                        because they are relocatable addresses that the
-                        linker needs to resolve. */
-                     continue;
+                     ms_type = mst_data;
                    }
-#endif
                  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))
+                     /* Found a special local symbol.  Allocate a
+                        sectinfo, if needed, and fill it in.  */
+                     if (sectinfo == NULL)
                        {
-                         index = SECT_OFF_BSS;
-                       }
-                     else if (STREQ ("Ddata.data", sym->name))
-                       {
-                         index = SECT_OFF_DATA;
-                       }
-                     else if (STREQ ("Drodata.rodata", sym->name))
-                       {
-                         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)
-                           {
-                             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;
-                               }
-                           }
-                         if (sectinfo->sections[index] != 0)
+                         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)
                            {
-                             complain (&section_info_dup_complaint,
-                                       sectinfo->filename);
+                             complaint (&symfile_complaints,
+                                        _("elf/stab section information %s without a preceding file symbol"),
+                                        sym->name);
                            }
-                         /* 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)
+                         else
                            {
-                             symaddr += offset;
+                             sectinfo->filename =
+                               (char *) filesym->name;
                            }
-                         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, sym->section, objfile);
+             unsigned long size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+             MSYMBOL_SIZE(msym) = size;
+           }
 #ifdef SOFUN_ADDRESS_MAYBE_MISSING
-             if (msym != NULL)
-               msym->filename = filesymname;
-#endif
-#ifdef ELF_MAKE_MSYMBOL_SPECIAL
-             ELF_MAKE_MSYMBOL_SPECIAL (sym, msym);
+         if (msym != NULL)
+           msym->filename = filesymname;
 #endif
-           }
+         gdbarch_elf_make_msymbol_special (current_gdbarch, sym, msym);
        }
-      do_cleanups (back_to);
     }
 }
 
@@ -572,7 +509,6 @@ elf_symtab_read (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.
 
@@ -583,35 +519,93 @@ elf_symtab_read (objfile, dynamic)
    capability even for files compiled without -g.  */
 
 static void
-elf_symfile_read (objfile, mainline)
-     struct objfile *objfile;
-     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 ((make_cleanup_func) 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 = (struct dbx_symfile_info *)
-    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.  */
 
-  elf_symtab_read (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 (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. */
@@ -626,7 +620,7 @@ elf_symfile_read (objfile, mainline)
     }
 
   /* We first have to find them... */
-  bfd_map_over_sections (abfd, elf_locate_sections, (PTR) & ei);
+  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
@@ -662,49 +656,37 @@ elf_symfile_read (objfile, mainline)
       if (str_sect)
        elfstab_build_psymtabs (objfile,
                                mainline,
-                               ei.stabsect->filepos,
-                               bfd_section_size (abfd, ei.stabsect),
+                               ei.stabsect,
                                str_sect->filepos,
                                bfd_section_size (abfd, str_sect));
     }
-  if (dwarf2_has_info (abfd))
+  if (dwarf2_has_info (objfile))
     {
       /* DWARF 2 sections */
       dwarf2_build_psymtabs (objfile, mainline);
     }
-  else if (ei.dboffset && ei.lnoffset)
-    {
-      /* DWARF sections */
-      dwarf_build_psymtabs (objfile,
-                           mainline,
-                           ei.dboffset, ei.dbsize,
-                           ei.lnoffset, ei.lnsize);
-    }
 
-  /* 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 = objfile->sym_stab_info;
+  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;
     }
 
@@ -719,8 +701,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 ();
@@ -732,12 +713,11 @@ 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);
     }
 }
 
@@ -751,8 +731,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
@@ -769,12 +748,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 = 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;
@@ -791,7 +768,7 @@ 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.  */
@@ -803,7 +780,8 @@ elfstab_offset_sections (objfile, pst)
 
   if (maybe == 0 && questionable != 0)
     {
-      complain (&stab_info_questionable_complaint, filename);
+      complaint (&symfile_complaints,
+                _("elf/stab section information questionable for %s"), filename);
       maybe = questionable;
     }
 
@@ -812,15 +790,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_SECTION_OFFSETS);
-      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);
+    complaint (&symfile_complaints,
+              _("elf/stab section information missing for %s"), filename);
 }
 \f
 /* Register that we are able to handle ELF object file formats.  */
@@ -833,11 +813,13 @@ static struct sym_fns elf_sym_fns =
   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                         /* next: pointer to next struct sym_fns */
 };
 
 void
-_initialize_elfread ()
+_initialize_elfread (void)
 {
   add_symtab_fns (&elf_sym_fns);
 }