]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/dbxread.c
sim: bfin: initial bf60x support
[thirdparty/binutils-gdb.git] / gdb / dbxread.c
index e79d2a858af60a5bdda386864e16e28f69ecc8e2..ebfd48e29cd91ad889a96fda4f138cca11b110da 100644 (file)
@@ -1,5 +1,5 @@
 /* Read dbx symbol tables and convert to internal format, for GDB.
-   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+   Copyright (C) 1986-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    for real.  dbx_psymtab_to_symtab() is the function that does this */
 
 #include "defs.h"
-#if defined(__CYGNUSCLIB__)
-#include <sys/types.h>
-#include <fcntl.h>
-#endif
 
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
 #include <sys/stat.h>
 #include "symtab.h"
 #include "breakpoint.h"
 #include "target.h"
-#include "gdbcore.h"           /* for bfd stuff */
-#include "libaout.h"           /* FIXME Secret internal BFD stuff for a.out */
+#include "gdbcore.h"
+#include "libaout.h"
 #include "filenames.h"
 #include "objfiles.h"
-#include "buildsym.h"
+#include "buildsym-legacy.h"
 #include "stabsread.h"
 #include "gdb-stabs.h"
 #include "demangle.h"
 #include "complaints.h"
 #include "cp-abi.h"
 #include "cp-support.h"
-#include "psympriv.h"
+#include "c-lang.h"
+#include "psymtab.h"
 #include "block.h"
 #include "aout/aout64.h"
-#include "aout/stab_gnu.h"     /* We always use GNU stabs, not
-                                  native, now.  */
+#include "aout/stab_gnu.h"
 \f
 
 /* Key for dbx-associated data.  */
 
-const struct objfile_data *dbx_objfile_data_key;
+const registry<objfile>::key<dbx_symfile_info> dbx_objfile_data_key;
 
 /* We put a pointer to this structure in the read_symtab_private field
    of the psymtab.  */
@@ -160,7 +156,7 @@ static unsigned char processing_acc_compilation;
    need to make guesses based on the symbols (which *are* relocated to
    reflect the address it will be loaded at).  */
 
-static CORE_ADDR lowest_text_address;
+static unrelocated_addr lowest_text_address;
 
 /* Non-zero if there is any line number info in the objfile.  Prevents
    dbx_end_psymtab from discarding an otherwise empty psymtab.  */
@@ -207,10 +203,10 @@ find_text_range (bfd * sym_bfd, struct objfile *objfile)
   CORE_ADDR end = 0;
 
   for (sec = sym_bfd->sections; sec; sec = sec->next)
-    if (bfd_get_section_flags (sym_bfd, sec) & SEC_CODE)
+    if (bfd_section_flags (sec) & SEC_CODE)
       {
-       CORE_ADDR sec_start = bfd_section_vma (sym_bfd, sec);
-       CORE_ADDR sec_end = sec_start + bfd_section_size (sym_bfd, sec);
+       CORE_ADDR sec_start = bfd_section_vma (sec);
+       CORE_ADDR sec_end = sec_start + bfd_section_size (sec);
 
        if (found_any)
          {
@@ -245,7 +241,7 @@ find_text_range (bfd * sym_bfd, struct objfile *objfile)
 struct header_file_location
 {
   header_file_location (const char *name_, int instance_,
-                       struct partial_symtab *pst_)
+                       legacy_psymtab *pst_)
     : name (name_),
       instance (instance_),
       pst (pst_)
@@ -254,7 +250,7 @@ struct header_file_location
 
   const char *name;            /* Name of header file */
   int instance;                        /* See above */
-  struct partial_symtab *pst;  /* Partial symtab that has the
+  legacy_psymtab *pst; /* Partial symtab that has the
                                   BINCL/EINCL defs for this file.  */
 };
 
@@ -263,16 +259,17 @@ static std::vector<struct header_file_location> *bincl_list;
 
 /* Local function prototypes.  */
 
-static void read_ofile_symtab (struct objfile *, struct partial_symtab *);
+static void read_ofile_symtab (struct objfile *, legacy_psymtab *);
 
-static void dbx_read_symtab (struct partial_symtab *self,
+static void dbx_read_symtab (legacy_psymtab *self,
                             struct objfile *objfile);
 
-static void dbx_psymtab_to_symtab_1 (struct objfile *, struct partial_symtab *);
+static void dbx_expand_psymtab (legacy_psymtab *, struct objfile *);
 
-static void read_dbx_symtab (minimal_symbol_reader &, struct objfile *);
+static void read_dbx_symtab (minimal_symbol_reader &, psymtab_storage *,
+                            struct objfile *);
 
-static struct partial_symtab *find_corresponding_bincl_psymtab (const char *,
+static legacy_psymtab *find_corresponding_bincl_psymtab (const char *,
                                                                int);
 
 static const char *dbx_next_symbol_text (struct objfile *);
@@ -288,7 +285,7 @@ static void dbx_symfile_read (struct objfile *, symfile_add_flags);
 static void dbx_symfile_finish (struct objfile *);
 
 static void record_minimal_symbol (minimal_symbol_reader &,
-                                  const char *, CORE_ADDR, int,
+                                  const char *, unrelocated_addr, int,
                                   struct objfile *);
 
 static void add_new_header_file (const char *, int);
@@ -297,10 +294,8 @@ static void add_old_header_file (const char *, int);
 
 static void add_this_object_header_file (int);
 
-static struct partial_symtab *start_psymtab (struct objfile *, const char *,
-                                            CORE_ADDR, int,
-                                            std::vector<partial_symbol *> &,
-                                            std::vector<partial_symbol *> &);
+static legacy_psymtab *start_psymtab (psymtab_storage *, struct objfile *,
+                                     const char *, unrelocated_addr, int);
 
 /* Free up old header file tables.  */
 
@@ -432,7 +427,7 @@ explicit_lookup_type (int real_filenum, int index)
 \f
 static void
 record_minimal_symbol (minimal_symbol_reader &reader,
-                      const char *name, CORE_ADDR address, int type,
+                      const char *name, unrelocated_addr address, int type,
                       struct objfile *objfile)
 {
   enum minimal_symbol_type ms_type;
@@ -463,8 +458,8 @@ record_minimal_symbol (minimal_symbol_reader &reader,
       break;
     case N_SETV:
       /* I don't think this type actually exists; since a N_SETV is the result
-         of going over many .o files, it doesn't make sense to have one
-         file local.  */
+        of going over many .o files, it doesn't make sense to have one
+        file local.  */
       ms_type = mst_file_data;
       section = SECT_OFF_DATA (objfile);
       break;
@@ -480,17 +475,18 @@ record_minimal_symbol (minimal_symbol_reader &reader,
       ms_type = mst_file_data;
 
       /* Check for __DYNAMIC, which is used by Sun shared libraries. 
-         Record it as global even if it's local, not global, so
-         lookup_minimal_symbol can find it.  We don't check symbol_leading_char
-         because for SunOS4 it always is '_'.  */
-      if (name[8] == 'C' && strcmp ("__DYNAMIC", name) == 0)
+        Record it as global even if it's local, not global, so
+        lookup_minimal_symbol can find it.  We don't check symbol_leading_char
+        because for SunOS4 it always is '_'.  */
+      if (strcmp ("__DYNAMIC", name) == 0)
        ms_type = mst_data;
 
       /* Same with virtual function tables, both global and static.  */
       {
        const char *tempstring = name;
 
-       if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
+       if (*tempstring != '\0'
+           && *tempstring == bfd_get_symbol_leading_char (objfile->obfd.get ()))
          ++tempstring;
        if (is_vtable_name (tempstring))
          ms_type = mst_data;
@@ -525,7 +521,7 @@ dbx_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
   bfd *sym_bfd;
   int val;
 
-  sym_bfd = objfile->obfd;
+  sym_bfd = objfile->obfd.get ();
 
   /* .o and .nlm files are relocatables with text, data and bss segs based at
      0.  This flag disables special (Solaris stabs-in-elf only) fixups for
@@ -537,11 +533,6 @@ dbx_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
   if (val < 0)
     perror_with_name (objfile_name (objfile));
 
-  /* Size the symbol table.  */
-  if (objfile->global_psymbols.capacity () == 0
-      && objfile->static_psymbols.capacity () == 0)
-    init_psymbol_list (objfile, DBX_SYMCOUNT (objfile));
-
   symbol_size = DBX_SYMBOL_SIZE (objfile);
   symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
 
@@ -551,7 +542,10 @@ dbx_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 
   /* Read stabs data from executable file and define symbols.  */
 
-  read_dbx_symtab (reader, objfile);
+  psymbol_functions *psf = new psymbol_functions ();
+  psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
+  objfile->qf.emplace_front (psf);
+  read_dbx_symtab (reader, partial_symtabs, objfile);
 
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
@@ -567,7 +561,6 @@ static void
 dbx_new_init (struct objfile *ignore)
 {
   stabsread_new_init ();
-  buildsym_init ();
   init_header_files ();
 }
 
@@ -591,15 +584,13 @@ static void
 dbx_symfile_init (struct objfile *objfile)
 {
   int val;
-  bfd *sym_bfd = objfile->obfd;
-  char *name = bfd_get_filename (sym_bfd);
+  bfd *sym_bfd = objfile->obfd.get ();
+  const char *name = bfd_get_filename (sym_bfd);
   asection *text_sect;
   unsigned char size_temp[DBX_STRINGTAB_SIZE_SIZE];
-  struct dbx_symfile_info *dbx;
 
   /* Allocate struct to keep track of the symfile.  */
-  dbx = XCNEW (struct dbx_symfile_info);
-  set_objfile_data (objfile, dbx_objfile_data_key, dbx);
+  dbx_objfile_data_key.emplace (objfile);
 
   DBX_TEXT_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
   DBX_DATA_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".data");
@@ -614,8 +605,8 @@ dbx_symfile_init (struct objfile *objfile)
   text_sect = bfd_get_section_by_name (sym_bfd, ".text");
   if (!text_sect)
     error (_("Can't find .text section in symbol file"));
-  DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
-  DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+  DBX_TEXT_ADDR (objfile) = bfd_section_vma (text_sect);
+  DBX_TEXT_SIZE (objfile) = bfd_section_size (text_sect);
 
   DBX_SYMBOL_SIZE (objfile) = obj_symbol_entry_size (sym_bfd);
   DBX_SYMCOUNT (objfile) = bfd_get_symcount (sym_bfd);
@@ -637,8 +628,8 @@ dbx_symfile_init (struct objfile *objfile)
   if (STRING_TABLE_OFFSET == 0)
     {
       /* It appears that with the existing bfd code, STRING_TABLE_OFFSET
-         will never be zero, even when there is no string table.  This
-         would appear to be a bug in bfd.  */
+        will never be zero, even when there is no string table.  This
+        would appear to be a bug in bfd.  */
       DBX_STRINGTAB_SIZE (objfile) = 0;
       DBX_STRINGTAB (objfile) = NULL;
     }
@@ -649,7 +640,7 @@ dbx_symfile_init (struct objfile *objfile)
        perror_with_name (name);
 
       memset (size_temp, 0, sizeof (size_temp));
-      val = bfd_bread (size_temp, sizeof (size_temp), sym_bfd);
+      val = bfd_read (size_temp, sizeof (size_temp), sym_bfd);
       if (val < 0)
        {
          perror_with_name (name);
@@ -688,9 +679,9 @@ dbx_symfile_init (struct objfile *objfile)
          val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET);
          if (val < 0)
            perror_with_name (name);
-         val = bfd_bread (DBX_STRINGTAB (objfile),
-                          DBX_STRINGTAB_SIZE (objfile),
-                          sym_bfd);
+         val = bfd_read (DBX_STRINGTAB (objfile),
+                         DBX_STRINGTAB_SIZE (objfile),
+                         sym_bfd);
          if (val != DBX_STRINGTAB_SIZE (objfile))
            perror_with_name (name);
        }
@@ -708,15 +699,12 @@ dbx_symfile_finish (struct objfile *objfile)
   free_header_files ();
 }
 
-static void
-dbx_free_symfile_info (struct objfile *objfile, void *arg)
+dbx_symfile_info::~dbx_symfile_info ()
 {
-  struct dbx_symfile_info *dbx = (struct dbx_symfile_info *) arg;
-
-  if (dbx->header_files != NULL)
+  if (header_files != NULL)
     {
-      int i = dbx->n_header_files;
-      struct header_file *hfiles = dbx->header_files;
+      int i = n_header_files;
+      struct header_file *hfiles = header_files;
 
       while (--i >= 0)
        {
@@ -725,8 +713,6 @@ dbx_free_symfile_info (struct objfile *objfile, void *arg)
        }
       xfree (hfiles);
     }
-
-  xfree (dbx);
 }
 
 \f
@@ -752,7 +738,8 @@ static char *stringtab_global;
 /* These variables are used to control fill_symbuf when the stabs
    symbols are not contiguous (as may be the case when a COFF file is
    linked using --split-by-reloc).  */
-static struct stab_section_list *symbuf_sections;
+static const std::vector<asection *> *symbuf_sections;
+static size_t sect_idx;
 static unsigned int symbuf_left;
 static unsigned int symbuf_read;
 
@@ -776,31 +763,31 @@ fill_symbuf (bfd *sym_bfd)
     {
       nbytes = sizeof (symbuf);
       if (nbytes > symbuf_left)
-        nbytes = symbuf_left;
+       nbytes = symbuf_left;
       memcpy (symbuf, stabs_data + symbuf_read, nbytes);
     }
   else if (symbuf_sections == NULL)
     {
       count = sizeof (symbuf);
-      nbytes = bfd_bread (symbuf, count, sym_bfd);
+      nbytes = bfd_read (symbuf, count, sym_bfd);
     }
   else
     {
       if (symbuf_left <= 0)
        {
-         file_ptr filepos = symbuf_sections->section->filepos;
+         file_ptr filepos = (*symbuf_sections)[sect_idx]->filepos;
 
          if (bfd_seek (sym_bfd, filepos, SEEK_SET) != 0)
            perror_with_name (bfd_get_filename (sym_bfd));
-         symbuf_left = bfd_section_size (sym_bfd, symbuf_sections->section);
+         symbuf_left = bfd_section_size ((*symbuf_sections)[sect_idx]);
          symbol_table_offset = filepos - symbuf_read;
-         symbuf_sections = symbuf_sections->next;
+         ++sect_idx;
        }
 
       count = symbuf_left;
       if (count > sizeof (symbuf))
        count = sizeof (symbuf);
-      nbytes = bfd_bread (symbuf, count, sym_bfd);
+      nbytes = bfd_read (symbuf, count, sym_bfd);
     }
 
   if (nbytes < 0)
@@ -822,7 +809,8 @@ stabs_seek (int sym_offset)
       symbuf_left -= sym_offset;
     }
   else
-    bfd_seek (symfile_bfd, sym_offset, SEEK_CUR);
+    if (bfd_seek (symfile_bfd, sym_offset, SEEK_CUR) != 0)
+      perror_with_name (bfd_get_filename (symfile_bfd));
 }
 
 #define INTERNALIZE_SYMBOL(intern, extern, abfd)                       \
@@ -868,7 +856,7 @@ dbx_next_symbol_text (struct objfile *objfile)
    bincl in the list.  Return the partial symtab associated
    with that header_file_location.  */
 
-static struct partial_symtab *
+static legacy_psymtab *
 find_corresponding_bincl_psymtab (const char *name, int instance)
 {
   for (const header_file_location &bincl : *bincl_list)
@@ -877,7 +865,7 @@ find_corresponding_bincl_psymtab (const char *name, int instance)
       return bincl.pst;
 
   repeated_header_complaint (name, symnum);
-  return (struct partial_symtab *) 0;
+  return (legacy_psymtab *) 0;
 }
 
 /* Set namestring based on nlist.  If the string table index is invalid, 
@@ -903,9 +891,9 @@ set_namestring (struct objfile *objfile, const struct internal_nlist *nlist)
   return namestring;
 }
 
-static CORE_ADDR
-find_stab_function_addr (const char *namestring, const char *filename,
-                        struct objfile *objfile)
+static struct bound_minimal_symbol
+find_stab_function (const char *namestring, const char *filename,
+                   struct objfile *objfile)
 {
   struct bound_minimal_symbol msym;
   int n;
@@ -924,8 +912,8 @@ find_stab_function_addr (const char *namestring, const char *filename,
   if (msym.minsym == NULL)
     {
       /* Sun Fortran appends an underscore to the minimal symbol name,
-         try again with an appended underscore if the minimal symbol
-         was not found.  */
+        try again with an appended underscore if the minimal symbol
+        was not found.  */
       p[n] = '_';
       p[n + 1] = 0;
       msym = lookup_minimal_symbol (p, filename, objfile);
@@ -945,7 +933,7 @@ find_stab_function_addr (const char *namestring, const char *filename,
       msym = lookup_minimal_symbol (p, NULL, objfile);
     }
 
-  return msym.minsym == NULL ? 0 : BMSYMBOL_VALUE_ADDRESS (msym);
+  return msym;
 }
 
 static void
@@ -960,9 +948,11 @@ function_outside_compilation_unit_complaint (const char *arg1)
    debugging information is available.  */
 
 static void
-read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
+read_dbx_symtab (minimal_symbol_reader &reader,
+                psymtab_storage *partial_symtabs,
+                struct objfile *objfile)
 {
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct external_nlist *bufp = 0;     /* =0 avoids gcc -Wall glitch.  */
   struct internal_nlist nlist;
   CORE_ADDR text_addr;
@@ -979,7 +969,7 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
   int data_sect_index;
 
   /* Current partial symtab.  */
-  struct partial_symtab *pst;
+  legacy_psymtab *pst;
 
   /* List of current psymtab's include files.  */
   const char **psymtab_include_list;
@@ -987,7 +977,7 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
   int includes_used;
 
   /* Index within current psymtab dependency list.  */
-  struct partial_symtab **dependency_list;
+  legacy_psymtab **dependency_list;
   int dependencies_used, dependencies_allocated;
 
   text_addr = DBX_TEXT_ADDR (objfile);
@@ -1000,7 +990,7 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
 
   stringtab_global = DBX_STRINGTAB (objfile);
 
-  pst = (struct partial_symtab *) 0;
+  pst = (legacy_psymtab *) 0;
 
   includes_allocated = 30;
   includes_used = 0;
@@ -1010,8 +1000,8 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
   dependencies_allocated = 30;
   dependencies_used = 0;
   dependency_list =
-    (struct partial_symtab **) alloca (dependencies_allocated *
-                                      sizeof (struct partial_symtab *));
+    (legacy_psymtab **) alloca (dependencies_allocated *
+                               sizeof (legacy_psymtab *));
 
   /* Init bincl list */
   std::vector<struct header_file_location> bincl_storage;
@@ -1020,10 +1010,10 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
 
   set_last_source_file (NULL);
 
-  lowest_text_address = (CORE_ADDR) -1;
+  lowest_text_address = (unrelocated_addr) -1;
 
-  symfile_bfd = objfile->obfd; /* For next_text_symbol.  */
-  abfd = objfile->obfd;
+  symfile_bfd = objfile->obfd.get ();  /* For next_text_symbol.  */
+  abfd = objfile->obfd.get ();
   symbuf_end = symbuf_idx = 0;
   next_symbol_text_func = dbx_next_symbol_text;
   textlow_not_set = 1;
@@ -1057,9 +1047,7 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
 
   /* If data_sect_index is still -1, that's okay.  It's perfectly fine
      for the file to have no .data, no .bss, and no .text at all, if
-     it also has no global or static variables.  If it does, we will
-     get an internal error from an ANOFFSET macro below when we try to
-     use data_sect_index.  */
+     it also has no global or static variables.  */
 
   for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
     {
@@ -1082,15 +1070,15 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
       OBJSTAT (objfile, n_stabs++);
 
       /* Ok.  There is a lot of code duplicated in the rest of this
-         switch statement (for efficiency reasons).  Since I don't
-         like duplicating code, I will do my penance here, and
-         describe the code which is duplicated:
+        switch statement (for efficiency reasons).  Since I don't
+        like duplicating code, I will do my penance here, and
+        describe the code which is duplicated:
 
-         *) The assignment to namestring.
-         *) The call to strchr.
-         *) The addition of a partial symbol the two partial
-         symbol lists.  This last is a large section of code, so
-         I've imbedded it in the following macro.  */
+        *) The assignment to namestring.
+        *) The call to strchr.
+        *) The addition of a partial symbol the two partial
+        symbol lists.  This last is a large section of code, so
+        I've embedded it in the following macro.  */
 
       switch (nlist.n_type)
        {
@@ -1116,7 +1104,8 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
          record_it:
          namestring = set_namestring (objfile, &nlist);
 
-         record_minimal_symbol (reader, namestring, nlist.n_value,
+         record_minimal_symbol (reader, namestring,
+                                unrelocated_addr (nlist.n_value),
                                 nlist.n_type, objfile);        /* Always */
          continue;
 
@@ -1138,21 +1127,21 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
              || (namestring[(nsl = strlen (namestring)) - 1] == 'o'
                  && namestring[nsl - 2] == '.'))
            {
-             nlist.n_value += ANOFFSET (objfile->section_offsets,
-                                        SECT_OFF_TEXT (objfile));
+             unrelocated_addr unrel_val = unrelocated_addr (nlist.n_value);
 
              if (past_first_source_file && pst
                  /* The gould NP1 uses low values for .o and -l symbols
                     which are not the address.  */
-                 && nlist.n_value >= pst->textlow)
+                 && unrel_val >= pst->unrelocated_text_low ())
                {
-                 dbx_end_psymtab (objfile, pst, psymtab_include_list,
+                 dbx_end_psymtab (objfile, partial_symtabs,
+                                  pst, psymtab_include_list,
                                   includes_used, symnum * symbol_size,
-                                  nlist.n_value > pst->texthigh
-                                  ? nlist.n_value : pst->texthigh,
+                                  unrel_val > pst->unrelocated_text_high ()
+                                  ? unrel_val : pst->unrelocated_text_high (),
                                   dependency_list, dependencies_used,
                                   textlow_not_set);
-                 pst = (struct partial_symtab *) 0;
+                 pst = (legacy_psymtab *) 0;
                  includes_used = 0;
                  dependencies_used = 0;
                  has_line_numbers = 0;
@@ -1236,8 +1225,7 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
            static const char *dirname_nso;
            int prev_textlow_not_set;
 
-           valu = nlist.n_value + ANOFFSET (objfile->section_offsets,
-                                            SECT_OFF_TEXT (objfile));
+           valu = nlist.n_value;
 
            prev_textlow_not_set = textlow_not_set;
 
@@ -1262,13 +1250,16 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
 
                if (pst)
                  {
-                   dbx_end_psymtab (objfile, pst, psymtab_include_list,
+                   unrelocated_addr unrel_value = unrelocated_addr (valu);
+                   dbx_end_psymtab (objfile, partial_symtabs,
+                                    pst, psymtab_include_list,
                                     includes_used, symnum * symbol_size,
-                                    valu > pst->texthigh
-                                    ? valu : pst->texthigh,
+                                    unrel_value > pst->unrelocated_text_high ()
+                                    ? unrel_value
+                                    : pst->unrelocated_text_high (),
                                     dependency_list, dependencies_used,
                                     prev_textlow_not_set);
-                   pst = (struct partial_symtab *) 0;
+                   pst = (legacy_psymtab *) 0;
                    includes_used = 0;
                    dependencies_used = 0;
                    has_line_numbers = 0;
@@ -1295,8 +1286,8 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
              {
                /* Save the directory name SOs locally, then save it into
                   the psymtab when it's created below.  */
-               dirname_nso = namestring;
-               continue;               
+               dirname_nso = namestring;
+               continue;               
              }
 
            /* Some other compilers (C++ ones in particular) emit useless
@@ -1305,11 +1296,10 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
 
            if (!pst)
              {
-               pst = start_psymtab (objfile,
-                                    namestring, valu,
-                                    first_so_symnum * symbol_size,
-                                    objfile->global_psymbols,
-                                    objfile->static_psymbols);
+               pst = start_psymtab (partial_symtabs, objfile,
+                                    namestring,
+                                    unrelocated_addr (valu),
+                                    first_so_symnum * symbol_size);
                pst->dirname = dirname_nso;
                dirname_nso = NULL;
              }
@@ -1433,14 +1423,15 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
          /* See if this is an end of function stab.  */
          if (pst && nlist.n_type == N_FUN && *namestring == '\000')
            {
-             CORE_ADDR valu;
+             unrelocated_addr valu;
 
              /* It's value is the size (in bytes) of the function for
                 function relative stabs, or the address of the function's
                 end for old style stabs.  */
-             valu = nlist.n_value + last_function_start;
-             if (pst->texthigh == 0 || valu > pst->texthigh)
-               pst->texthigh = valu;
+             valu = unrelocated_addr (nlist.n_value + last_function_start);
+             if (pst->unrelocated_text_high () == unrelocated_addr (0)
+                 || valu > pst->unrelocated_text_high ())
+               pst->set_text_high (valu);
              break;
            }
 
@@ -1448,26 +1439,38 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
          if (!p)
            continue;           /* Not a debugging symbol.   */
 
-         sym_len = 0;
+         sym_len = 0;
          sym_name = NULL;      /* pacify "gcc -Werror" */
-         if (psymtab_language == language_cplus)
-           {
+         if (psymtab_language == language_cplus)
+           {
+             std::string name (namestring, p - namestring);
+             gdb::unique_xmalloc_ptr<char> new_name
+               = cp_canonicalize_string (name.c_str ());
+             if (new_name != nullptr)
+               {
+                 sym_len = strlen (new_name.get ());
+                 sym_name = obstack_strdup (&objfile->objfile_obstack,
+                                            new_name.get ());
+               }
+           }
+         else if (psymtab_language == language_c)
+           {
              std::string name (namestring, p - namestring);
-             std::string new_name = cp_canonicalize_string (name.c_str ());
-             if (!new_name.empty ())
+             gdb::unique_xmalloc_ptr<char> new_name
+               = c_canonicalize_name (name.c_str ());
+             if (new_name != nullptr)
                {
-                 sym_len = new_name.length ();
-                 sym_name = (char *) obstack_copy0 (&objfile->objfile_obstack,
-                                                    new_name.c_str (),
-                                                    sym_len);
+                 sym_len = strlen (new_name.get ());
+                 sym_name = obstack_strdup (&objfile->objfile_obstack,
+                                            new_name.get ());
                }
            }
 
-         if (sym_len == 0)
-           {
-             sym_name = namestring;
-             sym_len = p - namestring;
-           }
+         if (sym_len == 0)
+           {
+             sym_name = namestring;
+             sym_len = p - namestring;
+           }
 
          /* Main processing section for debugging symbols which
             the initial read through the symbol tables needs to worry
@@ -1479,27 +1482,35 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
          switch (p[1])
            {
            case 'S':
-             nlist.n_value += ANOFFSET (objfile->section_offsets,
-                                        data_sect_index);
-
-             if (gdbarch_static_transform_name_p (gdbarch))
-               gdbarch_static_transform_name (gdbarch, namestring);
-
-             add_psymbol_to_list (sym_name, sym_len, 1,
-                                  VAR_DOMAIN, LOC_STATIC,
-                                  &objfile->static_psymbols,
-                                  nlist.n_value, psymtab_language, objfile);
+             if (pst != nullptr)
+               pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+                                 VAR_DOMAIN, LOC_STATIC,
+                                 data_sect_index,
+                                 psymbol_placement::STATIC,
+                                 unrelocated_addr (nlist.n_value),
+                                 psymtab_language,
+                                 partial_symtabs, objfile);
+             else
+               complaint (_("static `%*s' appears to be defined "
+                            "outside of all compilation units"),
+                          sym_len, sym_name);
              continue;
 
            case 'G':
-             nlist.n_value += ANOFFSET (objfile->section_offsets,
-                                        data_sect_index);
              /* The addresses in these entries are reported to be
                 wrong.  See the code that reads 'G's for symtabs.  */
-             add_psymbol_to_list (sym_name, sym_len, 1,
-                                  VAR_DOMAIN, LOC_STATIC,
-                                  &objfile->global_psymbols,
-                                  nlist.n_value, psymtab_language, objfile);
+             if (pst != nullptr)
+               pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+                                 VAR_DOMAIN, LOC_STATIC,
+                                 data_sect_index,
+                                 psymbol_placement::GLOBAL,
+                                 unrelocated_addr (nlist.n_value),
+                                 psymtab_language,
+                                 partial_symtabs, objfile);
+             else
+               complaint (_("global `%*s' appears to be defined "
+                            "outside of all compilation units"),
+                          sym_len, sym_name);
              continue;
 
            case 'T':
@@ -1513,17 +1524,32 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
                  || (p == namestring + 1
                      && namestring[0] != ' '))
                {
-                 add_psymbol_to_list (sym_name, sym_len, 1,
-                                      STRUCT_DOMAIN, LOC_TYPEDEF,
-                                      &objfile->static_psymbols,
-                                      0, psymtab_language, objfile);
+                 if (pst != nullptr)
+                   pst->add_psymbol (std::string_view (sym_name, sym_len),
+                                     true, STRUCT_DOMAIN, LOC_TYPEDEF, -1,
+                                     psymbol_placement::STATIC,
+                                     unrelocated_addr (0),
+                                     psymtab_language,
+                                     partial_symtabs, objfile);
+                 else
+                   complaint (_("enum, struct, or union `%*s' appears "
+                                "to be defined outside of all "
+                                "compilation units"),
+                              sym_len, sym_name);
                  if (p[2] == 't')
                    {
                      /* Also a typedef with the same name.  */
-                     add_psymbol_to_list (sym_name, sym_len, 1,
-                                          VAR_DOMAIN, LOC_TYPEDEF,
-                                          &objfile->static_psymbols,
-                                          0, psymtab_language, objfile);
+                     if (pst != nullptr)
+                       pst->add_psymbol (std::string_view (sym_name, sym_len),
+                                         true, VAR_DOMAIN, LOC_TYPEDEF, -1,
+                                         psymbol_placement::STATIC,
+                                         unrelocated_addr (0),
+                                         psymtab_language,
+                                         partial_symtabs, objfile);
+                     else
+                       complaint (_("typedef `%*s' appears to be defined "
+                                    "outside of all compilation units"),
+                                  sym_len, sym_name);
                      p += 1;
                    }
                }
@@ -1532,10 +1558,17 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
            case 't':
              if (p != namestring)      /* a name is there, not just :T...  */
                {
-                 add_psymbol_to_list (sym_name, sym_len, 1,
-                                      VAR_DOMAIN, LOC_TYPEDEF,
-                                      &objfile->static_psymbols,
-                                      0, psymtab_language, objfile);
+                 if (pst != nullptr)
+                   pst->add_psymbol (std::string_view (sym_name, sym_len),
+                                     true, VAR_DOMAIN, LOC_TYPEDEF, -1,
+                                     psymbol_placement::STATIC,
+                                     unrelocated_addr (0),
+                                     psymtab_language,
+                                     partial_symtabs, objfile);
+                 else
+                   complaint (_("typename `%*s' appears to be defined "
+                                "outside of all compilation units"),
+                              sym_len, sym_name);
                }
            check_enum:
              /* If this is an enumerated type, we need to
@@ -1593,10 +1626,17 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
                        ;
                      /* Note that the value doesn't matter for
                         enum constants in psymtabs, just in symtabs.  */
-                     add_psymbol_to_list (p, q - p, 1,
-                                          VAR_DOMAIN, LOC_CONST,
-                                          &objfile->static_psymbols, 0,
-                                          psymtab_language, objfile);
+                     if (pst != nullptr)
+                       pst->add_psymbol (std::string_view (p, q - p), true,
+                                         VAR_DOMAIN, LOC_CONST, -1,
+                                         psymbol_placement::STATIC,
+                                         unrelocated_addr (0),
+                                         psymtab_language,
+                                         partial_symtabs, objfile);
+                     else
+                       complaint (_("enum constant `%*s' appears to be defined "
+                                    "outside of all compilation units"),
+                                  ((int) (q - p)), p);
                      /* Point past the name.  */
                      p = q;
                      /* Skip over the value.  */
@@ -1611,50 +1651,45 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
 
            case 'c':
              /* Constant, e.g. from "const" in Pascal.  */
-             add_psymbol_to_list (sym_name, sym_len, 1,
-                                  VAR_DOMAIN, LOC_CONST,
-                                  &objfile->static_psymbols, 0,
-                                  psymtab_language, objfile);
+             if (pst != nullptr)
+               pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+                                 VAR_DOMAIN, LOC_CONST, -1,
+                                 psymbol_placement::STATIC,
+                                 unrelocated_addr (0),
+                                 psymtab_language,
+                                 partial_symtabs, objfile);
+             else
+               complaint (_("constant `%*s' appears to be defined "
+                            "outside of all compilation units"),
+                          sym_len, sym_name);
+
              continue;
 
            case 'f':
              if (! pst)
                {
-                 int name_len = p - namestring;
-                 char *name = (char *) xmalloc (name_len + 1);
-
-                 memcpy (name, namestring, name_len);
-                 name[name_len] = '\0';
-                 function_outside_compilation_unit_complaint (name);
-                 xfree (name);
+                 std::string name (namestring, (p - namestring));
+                 function_outside_compilation_unit_complaint (name.c_str ());
                }
-             nlist.n_value += ANOFFSET (objfile->section_offsets, 
-                                        SECT_OFF_TEXT (objfile));
              /* Kludges for ELF/STABS with Sun ACC.  */
              last_function_name = namestring;
              /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
                 value for the bottom of the text seg in those cases.  */
-             if (nlist.n_value == ANOFFSET (objfile->section_offsets, 
-                                            SECT_OFF_TEXT (objfile))
+             if (nlist.n_value == 0
                  && gdbarch_sofun_address_maybe_missing (gdbarch))
                {
-                 CORE_ADDR minsym_valu = 
-                   find_stab_function_addr (namestring, 
-                                            pst ? pst->filename : NULL, 
-                                            objfile);
-
-                 /* find_stab_function_addr will return 0 if the minimal
-                    symbol wasn't found.  (Unfortunately, this might also
-                    be a valid address.)  Anyway, if it *does* return 0,
-                    it is likely that the value was set correctly to begin
-                    with...  */
-                 if (minsym_valu != 0)
-                   nlist.n_value = minsym_valu;
+                 struct bound_minimal_symbol minsym
+                   = find_stab_function (namestring,
+                                         pst ? pst->filename : NULL,
+                                         objfile);
+                 if (minsym.minsym != NULL)
+                   nlist.n_value
+                     = CORE_ADDR (minsym.minsym->unrelocated_address ());
                }
              if (pst && textlow_not_set
                  && gdbarch_sofun_address_maybe_missing (gdbarch))
                {
-                 pst->textlow = nlist.n_value;
+                 pst->set_text_low (unrelocated_addr (nlist.n_value));
                  textlow_not_set = 0;
                }
              /* End kludge.  */
@@ -1669,18 +1704,21 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
                 the partial symbol table.  */
              if (pst
                  && (textlow_not_set
-                     || (nlist.n_value < pst->textlow
-                         && (nlist.n_value
-                             != ANOFFSET (objfile->section_offsets,
-                                          SECT_OFF_TEXT (objfile))))))
+                     || (unrelocated_addr (nlist.n_value)
+                         < pst->unrelocated_text_low ()
+                         && (nlist.n_value != 0))))
                {
-                 pst->textlow = nlist.n_value;
+                 pst->set_text_low (unrelocated_addr (nlist.n_value));
                  textlow_not_set = 0;
                }
-             add_psymbol_to_list (sym_name, sym_len, 1,
-                                  VAR_DOMAIN, LOC_BLOCK,
-                                  &objfile->static_psymbols,
-                                  nlist.n_value, psymtab_language, objfile);
+             if (pst != nullptr)
+               pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+                                 VAR_DOMAIN, LOC_BLOCK,
+                                 SECT_OFF_TEXT (objfile),
+                                 psymbol_placement::STATIC,
+                                 unrelocated_addr (nlist.n_value),
+                                 psymtab_language,
+                                 partial_symtabs, objfile);
              continue;
 
              /* Global functions were ignored here, but now they
@@ -1689,41 +1727,28 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
            case 'F':
              if (! pst)
                {
-                 int name_len = p - namestring;
-                 char *name = (char *) xmalloc (name_len + 1);
-
-                 memcpy (name, namestring, name_len);
-                 name[name_len] = '\0';
-                 function_outside_compilation_unit_complaint (name);
-                 xfree (name);
+                 std::string name (namestring, (p - namestring));
+                 function_outside_compilation_unit_complaint (name.c_str ());
                }
-             nlist.n_value += ANOFFSET (objfile->section_offsets, 
-                                        SECT_OFF_TEXT (objfile));
              /* Kludges for ELF/STABS with Sun ACC.  */
              last_function_name = namestring;
              /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
                 value for the bottom of the text seg in those cases.  */
-             if (nlist.n_value == ANOFFSET (objfile->section_offsets, 
-                                            SECT_OFF_TEXT (objfile))
+             if (nlist.n_value == 0
                  && gdbarch_sofun_address_maybe_missing (gdbarch))
                {
-                 CORE_ADDR minsym_valu = 
-                   find_stab_function_addr (namestring, 
-                                            pst ? pst->filename : NULL, 
-                                            objfile);
-
-                 /* find_stab_function_addr will return 0 if the minimal
-                    symbol wasn't found.  (Unfortunately, this might also
-                    be a valid address.)  Anyway, if it *does* return 0,
-                    it is likely that the value was set correctly to begin
-                    with...  */
-                 if (minsym_valu != 0)
-                   nlist.n_value = minsym_valu;
+                 struct bound_minimal_symbol minsym
+                   = find_stab_function (namestring,
+                                         pst ? pst->filename : NULL,
+                                         objfile);
+                 if (minsym.minsym != NULL)
+                   nlist.n_value
+                     = CORE_ADDR (minsym.minsym->unrelocated_address ());
                }
              if (pst && textlow_not_set
                  && gdbarch_sofun_address_maybe_missing (gdbarch))
                {
-                 pst->textlow = nlist.n_value;
+                 pst->set_text_low (unrelocated_addr (nlist.n_value));
                  textlow_not_set = 0;
                }
              /* End kludge.  */
@@ -1738,18 +1763,21 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
                 the partial symbol table.  */
              if (pst
                  && (textlow_not_set
-                     || (nlist.n_value < pst->textlow
-                         && (nlist.n_value
-                             != ANOFFSET (objfile->section_offsets,
-                                          SECT_OFF_TEXT (objfile))))))
+                     || (unrelocated_addr (nlist.n_value)
+                         < pst->unrelocated_text_low ()
+                         && (nlist.n_value != 0))))
                {
-                 pst->textlow = nlist.n_value;
+                 pst->set_text_low (unrelocated_addr (nlist.n_value));
                  textlow_not_set = 0;
                }
-             add_psymbol_to_list (sym_name, sym_len, 1,
-                                  VAR_DOMAIN, LOC_BLOCK,
-                                  &objfile->global_psymbols,
-                                  nlist.n_value, psymtab_language, objfile);
+             if (pst != nullptr)
+               pst->add_psymbol (std::string_view (sym_name, sym_len), true,
+                                 VAR_DOMAIN, LOC_BLOCK,
+                                 SECT_OFF_TEXT (objfile),
+                                 psymbol_placement::GLOBAL,
+                                 unrelocated_addr (nlist.n_value),
+                                 psymtab_language,
+                                 partial_symtabs, objfile);
              continue;
 
              /* Two things show up here (hopefully); static symbols of
@@ -1805,7 +1833,7 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
          /* Find the corresponding bincl and mark that psymtab on the
             psymtab dependency list.  */
          {
-           struct partial_symtab *needed_pst =
+           legacy_psymtab *needed_pst =
              find_corresponding_bincl_psymtab (namestring, nlist.n_value);
 
            /* If this include file was defined earlier in this file,
@@ -1832,22 +1860,22 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
                dependency_list[dependencies_used++] = needed_pst;
                if (dependencies_used >= dependencies_allocated)
                  {
-                   struct partial_symtab **orig = dependency_list;
+                   legacy_psymtab **orig = dependency_list;
 
                    dependency_list =
-                     (struct partial_symtab **)
+                     (legacy_psymtab **)
                      alloca ((dependencies_allocated *= 2)
-                             * sizeof (struct partial_symtab *));
+                             * sizeof (legacy_psymtab *));
                    memcpy (dependency_list, orig,
                            (dependencies_used
-                            * sizeof (struct partial_symtab *)));
+                            * sizeof (legacy_psymtab *)));
 #ifdef DEBUG_INFO
-                   fprintf_unfiltered (gdb_stderr,
-                                       "Had to reallocate "
-                                       "dependency list.\n");
-                   fprintf_unfiltered (gdb_stderr,
-                                       "New dependencies allocated: %d\n",
-                                       dependencies_allocated);
+                   gdb_printf (gdb_stderr,
+                               "Had to reallocate "
+                               "dependency list.\n");
+                   gdb_printf (gdb_stderr,
+                               "New dependencies allocated: %d\n",
+                               dependencies_allocated);
 #endif
                  }
              }
@@ -1855,18 +1883,18 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
          continue;
 
        case N_ENDM:
-         /* Solaris 2 end of module, finish current partial symbol table.
-            dbx_end_psymtab will set pst->texthigh to the proper value, which
-            is necessary if a module compiled without debugging info
-            follows this module.  */
+         /* Solaris 2 end of module, finish current partial symbol
+            table.  dbx_end_psymtab will set the high text address of
+            PST to the proper value, which is necessary if a module
+            compiled without debugging info follows this module.  */
          if (pst && gdbarch_sofun_address_maybe_missing (gdbarch))
            {
-             dbx_end_psymtab (objfile, pst,
+             dbx_end_psymtab (objfile, partial_symtabs, pst,
                               psymtab_include_list, includes_used,
                               symnum * symbol_size,
-                              (CORE_ADDR) 0, dependency_list,
+                              (unrelocated_addr) 0, dependency_list,
                               dependencies_used, textlow_not_set);
-             pst = (struct partial_symtab *) 0;
+             pst = (legacy_psymtab *) 0;
              includes_used = 0;
              dependencies_used = 0;
              has_line_numbers = 0;
@@ -1919,17 +1947,20 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
   /* If there's stuff to be cleaned up, clean it up.  */
   if (pst)
     {
-      /* Don't set pst->texthigh lower than it already is.  */
-      CORE_ADDR text_end =
-       (lowest_text_address == (CORE_ADDR) -1
-        ? (text_addr + ANOFFSET (objfile->section_offsets,
-                                 SECT_OFF_TEXT (objfile)))
-        : lowest_text_address)
-       + text_size;
-
-      dbx_end_psymtab (objfile, pst, psymtab_include_list, includes_used,
+      /* Don't set high text address of PST lower than it already
+        is.  */
+      unrelocated_addr text_end
+       = (unrelocated_addr
+          ((lowest_text_address == (unrelocated_addr) -1
+            ? text_addr
+            : CORE_ADDR (lowest_text_address))
+           + text_size));
+
+      dbx_end_psymtab (objfile, partial_symtabs,
+                      pst, psymtab_include_list, includes_used,
                       symnum * symbol_size,
-                      text_end > pst->texthigh ? text_end : pst->texthigh,
+                      (text_end > pst->unrelocated_text_high ()
+                       ? text_end : pst->unrelocated_text_high ()),
                       dependency_list, dependencies_used, textlow_not_set);
     }
 }
@@ -1941,19 +1972,18 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
    is the address relative to which its symbols are (incremental) or 0
    (normal).  */
 
-static struct partial_symtab *
-start_psymtab (struct objfile *objfile, const char *filename, CORE_ADDR textlow,
-              int ldsymoff, std::vector<partial_symbol *> &global_psymbols,
-              std::vector<partial_symbol *> &static_psymbols)
+static legacy_psymtab *
+start_psymtab (psymtab_storage *partial_symtabs, struct objfile *objfile,
+              const char *filename, unrelocated_addr textlow, int ldsymoff)
 {
-  struct partial_symtab *result =
-    start_psymtab_common (objfile, filename, textlow,
-                         global_psymbols, static_psymbols);
+  legacy_psymtab *result = new legacy_psymtab (filename, partial_symtabs,
+                                              objfile->per_bfd, textlow);
 
   result->read_symtab_private =
     XOBNEW (&objfile->objfile_obstack, struct symloc);
   LDSYMOFF (result) = ldsymoff;
-  result->read_symtab = dbx_read_symtab;
+  result->legacy_read_symtab = dbx_read_symtab;
+  result->legacy_expand_psymtab = dbx_expand_psymtab;
   SYMBOL_SIZE (result) = symbol_size;
   SYMBOL_OFFSET (result) = symbol_table_offset;
   STRING_OFFSET (result) = string_table_offset;
@@ -1971,20 +2001,21 @@ start_psymtab (struct objfile *objfile, const char *filename, CORE_ADDR textlow,
 
    FIXME:  List variables and peculiarities of same.  */
 
-struct partial_symtab *
-dbx_end_psymtab (struct objfile *objfile, struct partial_symtab *pst,
+legacy_psymtab *
+dbx_end_psymtab (struct objfile *objfile, psymtab_storage *partial_symtabs,
+                legacy_psymtab *pst,
                 const char **include_list, int num_includes,
-                int capping_symbol_offset, CORE_ADDR capping_text,
-                struct partial_symtab **dependency_list,
+                int capping_symbol_offset, unrelocated_addr capping_text,
+                legacy_psymtab **dependency_list,
                 int number_dependencies,
                 int textlow_not_set)
 {
   int i;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
 
   if (capping_symbol_offset != -1)
     LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst);
-  pst->texthigh = capping_text;
+  pst->set_text_high (capping_text);
 
   /* Under Solaris, the N_SO symbols always have a value of 0,
      instead of the usual address of the .o file.  Therefore,
@@ -2001,7 +2032,7 @@ dbx_end_psymtab (struct objfile *objfile, struct partial_symtab *pst,
      a reliable texthigh by taking the address plus size of the
      last function in the file.  */
 
-  if (pst->texthigh == 0 && last_function_name
+  if (!pst->text_high_valid && last_function_name
       && gdbarch_sofun_address_maybe_missing (gdbarch))
     {
       int n;
@@ -2028,8 +2059,9 @@ dbx_end_psymtab (struct objfile *objfile, struct partial_symtab *pst,
        }
 
       if (minsym.minsym)
-       pst->texthigh = (BMSYMBOL_VALUE_ADDRESS (minsym)
-                        + MSYMBOL_SIZE (minsym.minsym));
+       pst->set_text_high
+         (unrelocated_addr (CORE_ADDR (minsym.minsym->unrelocated_address ())
+                            + minsym.minsym->size ()));
 
       last_function_name = NULL;
     }
@@ -2038,90 +2070,68 @@ dbx_end_psymtab (struct objfile *objfile, struct partial_symtab *pst,
     ;
   /* This test will be true if the last .o file is only data.  */
   else if (textlow_not_set)
-    pst->textlow = pst->texthigh;
+    pst->set_text_low (pst->unrelocated_text_high ());
   else
     {
-      struct partial_symtab *p1;
-
       /* If we know our own starting text address, then walk through all other
-         psymtabs for this objfile, and if any didn't know their ending text
-         address, set it to our starting address.  Take care to not set our
-         own ending address to our starting address, nor to set addresses on
-         `dependency' files that have both textlow and texthigh zero.  */
+        psymtabs for this objfile, and if any didn't know their ending text
+        address, set it to our starting address.  Take care to not set our
+        own ending address to our starting address.  */
 
-      ALL_OBJFILE_PSYMTABS (objfile, p1)
-      {
-       if (p1->texthigh == 0 && p1->textlow != 0 && p1 != pst)
-         {
-           p1->texthigh = pst->textlow;
-           /* If this file has only data, then make textlow match
-              texthigh.  */
-           if (p1->textlow == 0)
-             p1->textlow = p1->texthigh;
-         }
-      }
+      for (partial_symtab *p1 : partial_symtabs->range ())
+       if (!p1->text_high_valid && p1->text_low_valid && p1 != pst)
+         p1->set_text_high (pst->unrelocated_text_low ());
     }
 
   /* End of kludge for patching Solaris textlow and texthigh.  */
 
-  end_psymtab_common (objfile, pst);
+  pst->end ();
 
   pst->number_of_dependencies = number_dependencies;
   if (number_dependencies)
     {
-      pst->dependencies = XOBNEWVEC (&objfile->objfile_obstack,
-                                    struct partial_symtab *,
-                                    number_dependencies);
+      pst->dependencies
+       = partial_symtabs->allocate_dependencies (number_dependencies);
       memcpy (pst->dependencies, dependency_list,
-             number_dependencies * sizeof (struct partial_symtab *));
+             number_dependencies * sizeof (legacy_psymtab *));
     }
   else
     pst->dependencies = 0;
 
   for (i = 0; i < num_includes; i++)
     {
-      struct partial_symtab *subpst =
-       allocate_psymtab (include_list[i], objfile);
+      legacy_psymtab *subpst =
+       new legacy_psymtab (include_list[i], partial_symtabs, objfile->per_bfd);
 
       subpst->read_symtab_private =
        XOBNEW (&objfile->objfile_obstack, struct symloc);
       LDSYMOFF (subpst) =
-       LDSYMLEN (subpst) =
-       subpst->textlow =
-       subpst->texthigh = 0;
+       LDSYMLEN (subpst) = 0;
 
       /* We could save slight bits of space by only making one of these,
-         shared by the entire set of include files.  FIXME-someday.  */
+        shared by the entire set of include files.  FIXME-someday.  */
       subpst->dependencies =
-       XOBNEW (&objfile->objfile_obstack, struct partial_symtab *);
+       partial_symtabs->allocate_dependencies (1);
       subpst->dependencies[0] = pst;
       subpst->number_of_dependencies = 1;
 
-      subpst->globals_offset =
-       subpst->n_global_syms =
-       subpst->statics_offset =
-       subpst->n_static_syms = 0;
-
-      subpst->readin = 0;
-      subpst->compunit_symtab = 0;
-      subpst->read_symtab = pst->read_symtab;
+      subpst->legacy_read_symtab = pst->legacy_read_symtab;
+      subpst->legacy_expand_psymtab = pst->legacy_expand_psymtab;
     }
 
   if (num_includes == 0
       && number_dependencies == 0
-      && pst->n_global_syms == 0
-      && pst->n_static_syms == 0
+      && pst->empty ()
       && has_line_numbers == 0)
     {
-      /* Throw away this psymtab, it's empty.  We can't deallocate it, since
-         it is on the obstack, but we can forget to chain it on the list.  */
+      /* Throw away this psymtab, it's empty.  */
       /* Empty psymtabs happen as a result of header files which don't have
-         any symbols in them.  There can be a lot of them.  But this check
-         is wrong, in that a psymtab with N_SLINE entries but nothing else
-         is not empty, but we don't realize that.  Fixing that without slowing
-         things down might be tricky.  */
+        any symbols in them.  There can be a lot of them.  But this check
+        is wrong, in that a psymtab with N_SLINE entries but nothing else
+        is not empty, but we don't realize that.  Fixing that without slowing
+        things down might be tricky.  */
 
-      discard_psymtab (objfile, pst);
+      partial_symtabs->discard_psymtab (pst);
 
       /* Indicate that psymtab was thrown away.  */
       pst = NULL;
@@ -2130,77 +2140,39 @@ dbx_end_psymtab (struct objfile *objfile, struct partial_symtab *pst,
 }
 \f
 static void
-dbx_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
+dbx_expand_psymtab (legacy_psymtab *pst, struct objfile *objfile)
 {
-  int i;
-
-  if (pst->readin)
-    {
-      fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in.  "
-                         "Shouldn't happen.\n",
-                         pst->filename);
-      return;
-    }
+  gdb_assert (!pst->readin);
 
   /* Read in all partial symtabs on which this one is dependent.  */
-  for (i = 0; i < pst->number_of_dependencies; i++)
-    if (!pst->dependencies[i]->readin)
-      {
-       /* Inform about additional files that need to be read in.  */
-       if (info_verbose)
-         {
-           fputs_filtered (" ", gdb_stdout);
-           wrap_here ("");
-           fputs_filtered ("and ", gdb_stdout);
-           wrap_here ("");
-           printf_filtered ("%s...", pst->dependencies[i]->filename);
-           wrap_here ("");     /* Flush output.  */
-           gdb_flush (gdb_stdout);
-         }
-       dbx_psymtab_to_symtab_1 (objfile, pst->dependencies[i]);
-      }
+  pst->expand_dependencies (objfile);
 
   if (LDSYMLEN (pst))          /* Otherwise it's a dummy.  */
     {
       /* Init stuff necessary for reading in symbols */
       stabsread_init ();
-      buildsym_init ();
       scoped_free_pendings free_pending;
       file_string_table_offset = FILE_STRING_OFFSET (pst);
       symbol_size = SYMBOL_SIZE (pst);
 
       /* Read in this file's symbols.  */
-      bfd_seek (objfile->obfd, SYMBOL_OFFSET (pst), SEEK_SET);
-      read_ofile_symtab (objfile, pst);
+      if (bfd_seek (objfile->obfd.get (), SYMBOL_OFFSET (pst), SEEK_SET) == 0)
+       read_ofile_symtab (objfile, pst);
     }
 
-  pst->readin = 1;
+  pst->readin = true;
 }
 
 /* Read in all of the symbols for a given psymtab for real.
    Be verbose about it if the user wants that.  SELF is not NULL.  */
 
 static void
-dbx_read_symtab (struct partial_symtab *self, struct objfile *objfile)
+dbx_read_symtab (legacy_psymtab *self, struct objfile *objfile)
 {
-  if (self->readin)
-    {
-      fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in.  "
-                         "Shouldn't happen.\n",
-                         self->filename);
-      return;
-    }
+  gdb_assert (!self->readin);
 
   if (LDSYMLEN (self) || self->number_of_dependencies)
     {
-      /* Print the message now, before reading the string table,
-         to avoid disconcerting pauses.  */
-      if (info_verbose)
-       {
-         printf_filtered ("Reading in symbols for %s...", self->filename);
-         gdb_flush (gdb_stdout);
-       }
-
       next_symbol_text_func = dbx_next_symbol_text;
 
       {
@@ -2215,23 +2187,19 @@ dbx_read_symtab (struct partial_symtab *self, struct objfile *objfile)
            data_holder.reset (stabs_data);
          }
 
-       dbx_psymtab_to_symtab_1 (objfile, self);
+       self->expand_psymtab (objfile);
       }
 
       /* Match with global symbols.  This only needs to be done once,
-         after all of the symtabs and dependencies have been read in.   */
+        after all of the symtabs and dependencies have been read in.   */
       scan_file_globals (objfile);
-
-      /* Finish up the debug error message.  */
-      if (info_verbose)
-       printf_filtered ("done.\n");
     }
 }
 
 /* Read in a defined section of a specific object file's symbols.  */
 
 static void
-read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
+read_ofile_symtab (struct objfile *objfile, legacy_psymtab *pst)
 {
   const char *namestring;
   struct external_nlist *bufp;
@@ -2243,21 +2211,20 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
   int sym_size;                        /* Size of symbols to read */
   CORE_ADDR text_offset;       /* Start of text segment for symbols */
   int text_size;               /* Size of text segment for symbols */
-  struct section_offsets *section_offsets;
 
   sym_offset = LDSYMOFF (pst);
   sym_size = LDSYMLEN (pst);
-  text_offset = pst->textlow;
-  text_size = pst->texthigh - pst->textlow;
-  section_offsets = objfile->section_offsets;
+  text_offset = pst->text_low (objfile);
+  text_size = pst->text_high (objfile) - pst->text_low (objfile);
+  const section_offsets &section_offsets = objfile->section_offsets;
 
   dbxread_objfile = objfile;
 
   stringtab_global = DBX_STRINGTAB (objfile);
   set_last_source_file (NULL);
 
-  abfd = objfile->obfd;
-  symfile_bfd = objfile->obfd; /* Implicit param to next_text_symbol.  */
+  abfd = objfile->obfd.get ();
+  symfile_bfd = objfile->obfd.get ();  /* Implicit param to next_text_symbol.  */
   symbuf_end = symbuf_idx = 0;
   symbuf_read = 0;
   symbuf_left = sym_offset + sym_size;
@@ -2287,7 +2254,8 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
            processing_gcc_compilation = 1;
          else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
            processing_gcc_compilation = 2;
-         if (tempstring[0] == bfd_get_symbol_leading_char (symfile_bfd))
+         if (*tempstring != '\0'
+             && *tempstring == bfd_get_symbol_leading_char (symfile_bfd))
            ++tempstring;
          if (startswith (tempstring, "__gnu_compiled"))
            processing_gcc_compilation = 2;
@@ -2296,8 +2264,8 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
   else
     {
       /* The N_SO starting this symtab is the first symbol, so we
-         better not check the symbol before it.  I'm not this can
-         happen, but it doesn't hurt to check for it.  */
+        better not check the symbol before it.  I'm not this can
+        happen, but it doesn't hurt to check for it.  */
       stabs_seek (sym_offset);
       processing_gcc_compilation = 0;
     }
@@ -2345,7 +2313,7 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
                              PST_LANGUAGE (pst));
        }
       /* We skip checking for a new .o or -l file; that should never
-         happen in this routine.  */
+        happen in this routine.  */
       else if (type == N_TEXT)
        {
          /* I don't think this code will ever be executed, because
@@ -2362,7 +2330,7 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
       else if (type & N_EXT || type == (unsigned char) N_TEXT
               || type == (unsigned char) N_NBTEXT)
        {
-         /* Global symbol: see if we came across a dbx defintion for
+         /* Global symbol: see if we came across a dbx definition for
             a corresponding symbol.  If so, store the value.  Remove
             syms from the chain when their values are stored, but
             search the whole chain, as there may be several syms from
@@ -2375,20 +2343,19 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
        }
     }
 
-  /* In a Solaris elf file, this variable, which comes from the
-     value of the N_SO symbol, will still be 0.  Luckily, text_offset,
-     which comes from pst->textlow is correct.  */
+  /* In a Solaris elf file, this variable, which comes from the value
+     of the N_SO symbol, will still be 0.  Luckily, text_offset, which
+     comes from low text address of PST, is correct.  */
   if (get_last_source_start_addr () == 0)
     set_last_source_start_addr (text_offset);
 
   /* In reordered executables last_source_start_addr may not be the
      lower bound for this symtab, instead use text_offset which comes
-     from pst->textlow which is correct.  */
+     from the low text address of PST, which is correct.  */
   if (get_last_source_start_addr () > text_offset)
     set_last_source_start_addr (text_offset);
 
-  pst->compunit_symtab = end_symtab (text_offset + text_size,
-                                    SECT_OFF_TEXT (objfile));
+  pst->compunit_symtab = end_compunit_symtab (text_offset + text_size);
 
   end_stabs ();
 
@@ -2405,7 +2372,7 @@ cp_set_block_scope (const struct symbol *symbol,
                    struct block *block,
                    struct obstack *obstack)
 {
-  if (SYMBOL_DEMANGLED_NAME (symbol) != NULL)
+  if (symbol->demangled_name () != NULL)
     {
       /* Try to figure out the appropriate namespace from the
         demangled name.  */
@@ -2415,12 +2382,11 @@ cp_set_block_scope (const struct symbol *symbol,
         name of the class as well.  This should be harmless, but
         is a little unfortunate.  */
 
-      const char *name = SYMBOL_DEMANGLED_NAME (symbol);
+      const char *name = symbol->demangled_name ();
       unsigned int prefix_len = cp_entire_prefix_len (name);
 
-      block_set_scope (block,
-                      (const char *) obstack_copy0 (obstack, name, prefix_len),
-                      obstack);
+      block->set_scope (obstack_strndup (obstack, name, prefix_len),
+                       obstack);
     }
 }
 
@@ -2437,16 +2403,16 @@ cp_set_block_scope (const struct symbol *symbol,
    the pst->section_offsets.  All symbols that refer to memory
    locations need to be offset by these amounts.
    OBJFILE is the object file from which we are reading symbols.  It
-   is used in end_symtab.
+   is used in end_compunit_symtab.
    LANGUAGE is the language of the symtab.
 */
 
 void
 process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
-                   const struct section_offsets *section_offsets,
+                   const section_offsets &section_offsets,
                    struct objfile *objfile, enum language language)
 {
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct context_stack *newobj;
   struct context_stack cstk;
   /* This remembers the address of the start of a function.  It is
@@ -2471,15 +2437,18 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
      source file.  Used to detect the SunPRO solaris compiler.  */
   static int n_opt_found;
 
+  /* The section index for this symbol.  */
+  int section_index = -1;
+
   /* Something is wrong if we see real data before seeing a source
      file name.  */
 
   if (get_last_source_file () == NULL && type != (unsigned char) N_SO)
     {
       /* Ignore any symbols which appear before an N_SO symbol.
-         Currently no one puts symbols there, but we should deal
-         gracefully with the case.  A complain()t might be in order,
-         but this should not be an error ().  */
+        Currently no one puts symbols there, but we should deal
+        gracefully with the case.  A complain()t might be in order,
+        but this should not be an error ().  */
       return;
     }
 
@@ -2495,10 +2464,10 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
          struct block *block;
 
          if (outermost_context_p ())
-           {
+           {
              lbrac_mismatch_complaint (symnum);
-             break;
-           }
+             break;
+           }
 
          /* The following check is added before recording line 0 at
             end of function so as to handle hand-generated stabs
@@ -2508,8 +2477,10 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
            {
              CORE_ADDR addr = last_function_start + valu;
 
-             record_line (get_current_subfile (), 0,
-                          gdbarch_addr_bits_remove (gdbarch, addr));
+             record_line
+               (get_current_subfile (), 0,
+                unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, addr)
+                                  - objfile->text_section_offset ()));
            }
 
          within_function = 0;
@@ -2521,7 +2492,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
                                cstk.start_addr, cstk.start_addr + valu);
 
          /* For C++, set the block's scope.  */
-         if (SYMBOL_LANGUAGE (cstk.name) == language_cplus)
+         if (cstk.name->language () == language_cplus)
            cp_set_block_scope (cstk.name, block, &objfile->objfile_obstack);
 
          /* May be switching to an assembler file which may not be using
@@ -2534,7 +2505,8 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
       sline_found_in_function = 0;
 
       /* Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+      section_index = SECT_OFF_TEXT (objfile);
+      valu += section_offsets[SECT_OFF_TEXT (objfile)];
       valu = gdbarch_addr_bits_remove (gdbarch, valu);
       last_function_start = valu;
 
@@ -2542,7 +2514,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
 
     case N_LBRAC:
       /* This "symbol" just indicates the start of an inner lexical
-         context within a function.  */
+        context within a function.  */
 
       /* Ignore extra outermost context from SunPRO cc and acc.  */
       if (n_opt_found && desc == 1)
@@ -2555,7 +2527,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
 
     case N_RBRAC:
       /* This "symbol" just indicates the end of an inner lexical
-         context that was started with N_LBRAC.  */
+        context that was started with N_LBRAC.  */
 
       /* Ignore extra outermost context from SunPRO cc and acc.  */
       if (n_opt_found && desc == 1)
@@ -2573,7 +2545,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
       if (desc != cstk.depth)
        lbrac_mismatch_complaint (symnum);
 
-      if (local_symbols != NULL)
+      if (*get_local_symbols () != NULL)
        {
          /* GCC development snapshots from March to December of
             2000 would output N_LSYM entries after N_LBRAC
@@ -2582,7 +2554,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
          complaint (_("misplaced N_LBRAC entry; discarding local "
                       "symbols which have no enclosing block"));
        }
-      local_symbols = cstk.locals;
+      *get_local_symbols () = cstk.locals;
 
       if (get_context_stack_depth () > 1)
        {
@@ -2592,7 +2564,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
             for them (but don't bother if the block contains no
             symbols.  Should we complain on blocks without symbols?
             I can't think of any useful purpose for them).  */
-         if (local_symbols != NULL)
+         if (*get_local_symbols () != NULL)
            {
              /* Muzzle a compiler bug that makes end < start.
 
@@ -2621,16 +2593,18 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
     case N_FN:
     case N_FN_SEQ:
       /* This kind of symbol indicates the start of an object file.
-         Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+        Relocate for dynamic loading.  */
+      section_index = SECT_OFF_TEXT (objfile);
+      valu += section_offsets[SECT_OFF_TEXT (objfile)];
       break;
 
     case N_SO:
       /* This type of symbol indicates the start of data for one
-         source file.  Finish the symbol table of the previous source
-         file (if any) and start accumulating a new symbol table.
-         Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+        source file.  Finish the symbol table of the previous source
+        file (if any) and start accumulating a new symbol table.
+        Relocate for dynamic loading.  */
+      section_index = SECT_OFF_TEXT (objfile);
+      valu += section_offsets[SECT_OFF_TEXT (objfile)];
 
       n_opt_found = 0;
 
@@ -2645,28 +2619,29 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
              patch_subfile_names (get_current_subfile (), name);
              break;            /* Ignore repeated SOs.  */
            }
-         end_symtab (valu, SECT_OFF_TEXT (objfile));
+         end_compunit_symtab (valu);
          end_stabs ();
        }
 
       /* Null name means this just marks the end of text for this .o
-         file.  Don't start a new symtab in this case.  */
+        file.  Don't start a new symtab in this case.  */
       if (*name == '\000')
        break;
 
       function_start_offset = 0;
 
       start_stabs ();
-      start_symtab (objfile, name, NULL, valu, language);
+      start_compunit_symtab (objfile, name, NULL, valu, language);
       record_debugformat ("stabs");
       break;
 
     case N_SOL:
       /* This type of symbol indicates the start of data for a
-         sub-source-file, one whose contents were copied or included
-         in the compilation of the main source file (whose name was
-         given in the N_SO symbol).  Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+        sub-source-file, one whose contents were copied or included
+        in the compilation of the main source file (whose name was
+        given in the N_SO symbol).  Relocate for dynamic loading.  */
+      section_index = SECT_OFF_TEXT (objfile);
+      valu += section_offsets[SECT_OFF_TEXT (objfile)];
       start_subfile (name);
       break;
 
@@ -2686,14 +2661,14 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
 
     case N_SLINE:
       /* This type of "symbol" really just records one line-number --
-         core-address correspondence.  Enter it in the line list for
-         this symbol table.  */
+        core-address correspondence.  Enter it in the line list for
+        this symbol table.  */
 
       /* Relocate for dynamic loading and for ELF acc
-         function-relative symbols.  */
+        function-relative symbols.  */
       valu += function_start_offset;
 
-      /* GCC 2.95.3 emits the first N_SLINE stab somwehere in the
+      /* GCC 2.95.3 emits the first N_SLINE stab somewhere in the
         middle of the prologue instead of right at the start of the
         function.  To deal with this we record the address for the
         first N_SLINE stab to be the start of the function instead of
@@ -2712,13 +2687,17 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
          CORE_ADDR addr = processing_gcc_compilation == 2 ?
                           last_function_start : valu;
 
-         record_line (get_current_subfile (), desc,
-                      gdbarch_addr_bits_remove (gdbarch, addr));
+         record_line
+           (get_current_subfile (), desc,
+            unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, addr)
+                              - objfile->text_section_offset ()));
          sline_found_in_function = 1;
        }
       else
-       record_line (get_current_subfile (), desc,
-                    gdbarch_addr_bits_remove (gdbarch, valu));
+       record_line
+         (get_current_subfile (), desc,
+          unrelocated_addr (gdbarch_addr_bits_remove (gdbarch, valu)
+                            - objfile->text_section_offset ()));
       break;
 
     case N_BCOMM:
@@ -2730,22 +2709,22 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
       break;
 
       /* The following symbol types need to have the appropriate
-         offset added to their value; then we process symbol
-         definitions in the name.  */
+        offset added to their value; then we process symbol
+        definitions in the name.  */
 
     case N_STSYM:              /* Static symbol in data segment.  */
     case N_LCSYM:              /* Static symbol in BSS segment.  */
     case N_ROSYM:              /* Static symbol in read-only data segment.  */
       /* HORRID HACK DEPT.  However, it's Sun's furgin' fault.
-         Solaris 2's stabs-in-elf makes *most* symbols relative but
-         leaves a few absolute (at least for Solaris 2.1 and version
-         2.0.1 of the SunPRO compiler).  N_STSYM and friends sit on
-         the fence.  .stab "foo:S...",N_STSYM is absolute (ld
-         relocates it) .stab "foo:V...",N_STSYM is relative (section
-         base subtracted).  This leaves us no choice but to search for
-         the 'S' or 'V'...  (or pass the whole section_offsets stuff
-         down ONE MORE function call level, which we really don't want
-         to do).  */
+        Solaris 2's stabs-in-elf makes *most* symbols relative but
+        leaves a few absolute (at least for Solaris 2.1 and version
+        2.0.1 of the SunPRO compiler).  N_STSYM and friends sit on
+        the fence.  .stab "foo:S...",N_STSYM is absolute (ld
+        relocates it) .stab "foo:V...",N_STSYM is relative (section
+        base subtracted).  This leaves us no choice but to search for
+        the 'S' or 'V'...  (or pass the whole section_offsets stuff
+        down ONE MORE function call level, which we really don't want
+        to do).  */
       {
        const char *p;
 
@@ -2766,12 +2745,13 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
                   symbol_file_add as addr (this is known to affect
                   SunOS 4, and I suspect ELF too).  Since there is no
                   Ttext.text symbol, we can get addr from the text offset.  */
-               valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+               section_index = SECT_OFF_TEXT (objfile);
+               valu += section_offsets[SECT_OFF_TEXT (objfile)];
                goto define_a_symbol;
              }
          }
        /* Since it's not the kludge case, re-dispatch to the right
-           handler.  */
+          handler.  */
        switch (type)
          {
          case N_STSYM:
@@ -2781,34 +2761,37 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
          case N_ROSYM:
            goto case_N_ROSYM;
          default:
-           internal_error (__FILE__, __LINE__,
-                           _("failed internal consistency check"));
+           internal_error (_("failed internal consistency check"));
          }
       }
 
     case_N_STSYM:              /* Static symbol in data segment.  */
     case N_DSLINE:             /* Source line number, data segment.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile));
+      section_index = SECT_OFF_DATA (objfile);
+      valu += section_offsets[SECT_OFF_DATA (objfile)];
       goto define_a_symbol;
 
     case_N_LCSYM:              /* Static symbol in BSS segment.  */
     case N_BSLINE:             /* Source line number, BSS segment.  */
       /* N_BROWS: overlaps with N_BSLINE.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile));
+      section_index = SECT_OFF_BSS (objfile);
+      valu += section_offsets[SECT_OFF_BSS (objfile)];
       goto define_a_symbol;
 
     case_N_ROSYM:              /* Static symbol in read-only data segment.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_RODATA (objfile));
+      section_index = SECT_OFF_RODATA (objfile);
+      valu += section_offsets[SECT_OFF_RODATA (objfile)];
       goto define_a_symbol;
 
     case N_ENTRY:              /* Alternate entry point.  */
       /* Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+      section_index = SECT_OFF_TEXT (objfile);
+      valu += section_offsets[SECT_OFF_TEXT (objfile)];
       goto define_a_symbol;
 
       /* The following symbol types we don't know how to process.
-         Handle them in a "default" way, but complain to people who
-         care.  */
+        Handle them in a "default" way, but complain to people who
+        care.  */
     default:
     case N_CATCH:              /* Exception handler catcher.  */
     case N_EHDECL:             /* Exception handler name.  */
@@ -2823,11 +2806,11 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
     case N_NBSTS:
     case N_NBLCS:
       unknown_symtype_complaint (hex_string (type));
-      /* FALLTHROUGH */
 
     define_a_symbol:
+      [[fallthrough]];
       /* These symbol types don't need the address field relocated,
-         since it is either unused, or is absolute.  */
+        since it is either unused, or is absolute.  */
     case N_GSYM:               /* Global variable.  */
     case N_NSYMS:              /* Number of symbols (Ultrix).  */
     case N_NOMAP:              /* No map?  (Ultrix).  */
@@ -2852,24 +2835,16 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
            case 'f':
            case 'F':
              /* Deal with the SunPRO 3.0 compiler which omits the
-                address from N_FUN symbols.  */
+                address from N_FUN symbols.  */
              if (type == N_FUN
-                 && valu == ANOFFSET (section_offsets,
-                                      SECT_OFF_TEXT (objfile))
+                 && valu == section_offsets[SECT_OFF_TEXT (objfile)]
                  && gdbarch_sofun_address_maybe_missing (gdbarch))
                {
-                 CORE_ADDR minsym_valu = 
-                   find_stab_function_addr (name, get_last_source_file (),
-                                            objfile);
-
-                 /* The function find_stab_function_addr will return
-                    0 if the minimal symbol wasn't found.
-                    (Unfortunately, this might also be a valid
-                    address.)  Anyway, if it *does* return 0, it is
-                    likely that the value was set correctly to begin
-                    with...  */
-                 if (minsym_valu != 0)
-                   valu = minsym_valu;
+                 struct bound_minimal_symbol minsym
+                   = find_stab_function (name, get_last_source_file (),
+                                         objfile);
+                 if (minsym.minsym != NULL)
+                   valu = minsym.value_address ();
                }
 
              /* These addresses are absolute.  */
@@ -2895,25 +2870,32 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
                                        cstk.start_addr, valu);
 
                  /* For C++, set the block's scope.  */
-                 if (SYMBOL_LANGUAGE (cstk.name) == language_cplus)
+                 if (cstk.name->language () == language_cplus)
                    cp_set_block_scope (cstk.name, block,
                                        &objfile->objfile_obstack);
                }
 
              newobj = push_context (0, valu);
              newobj->name = define_symbol (valu, name, desc, type, objfile);
+             if (newobj->name != nullptr)
+               newobj->name->set_section_index (section_index);
              break;
 
            default:
-             define_symbol (valu, name, desc, type, objfile);
+             {
+               struct symbol *sym = define_symbol (valu, name, desc, type,
+                                                   objfile);
+               if (sym != nullptr)
+                 sym->set_section_index (section_index);
+             }
              break;
            }
        }
       break;
 
       /* We use N_OPT to carry the gcc2_compiled flag.  Sun uses it
-         for a bunch of other flags, too.  Someday we may parse their
-         flags; for now we ignore theirs and hope they'll ignore ours.  */
+        for a bunch of other flags, too.  Someday we may parse their
+        flags; for now we ignore theirs and hope they'll ignore ours.  */
     case N_OPT:                        /* Solaris 2: Compiler options.  */
       if (name)
        {
@@ -2944,7 +2926,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
     case N_PATCH:              /* Solaris 2: Patch Run Time Checker.  */
       /* N_UNDF:                   Solaris 2: File separator mark.  */
       /* N_UNDF: -- we will never encounter it, since we only process
-         one file's symbols at once.  */
+        one file's symbols at once.  */
     case N_ENDM:               /* Solaris 2: End of module.  */
     case N_ALIAS:              /* SunPro F77: alias name, ignore for now.  */
       break;
@@ -2959,17 +2941,17 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
   if (name[0] == '#')
     {
       /* Initialize symbol reference names and determine if this is a
-         definition.  If a symbol reference is being defined, go ahead
-         and add it.  Otherwise, just return.  */
+        definition.  If a symbol reference is being defined, go ahead
+        and add it.  Otherwise, just return.  */
 
       const char *s = name;
       int refnum;
 
       /* If this stab defines a new reference ID that is not on the
-         reference list, then put it on the reference list.
+        reference list, then put it on the reference list.
 
-         We go ahead and advance NAME past the reference, even though
-         it is not strictly necessary at this time.  */
+        We go ahead and advance NAME past the reference, even though
+        it is not strictly necessary at this time.  */
       refnum = symbol_reference_defined (&s);
       if (refnum >= 0)
        if (!ref_search (refnum))
@@ -3006,14 +2988,17 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
 void
 coffstab_build_psymtabs (struct objfile *objfile,
                         CORE_ADDR textaddr, unsigned int textsize,
-                        struct stab_section_list *stabsects,
+                        const std::vector<asection *> &stabsects,
                         file_ptr stabstroffset, unsigned int stabstrsize)
 {
   int val;
-  bfd *sym_bfd = objfile->obfd;
-  char *name = bfd_get_filename (sym_bfd);
+  bfd *sym_bfd = objfile->obfd.get ();
+  const char *name = bfd_get_filename (sym_bfd);
   unsigned int stabsize;
 
+  /* Allocate struct to keep track of stab reading.  */
+  dbx_objfile_data_key.emplace (objfile);
+
   DBX_TEXT_ADDR (objfile) = textaddr;
   DBX_TEXT_SIZE (objfile) = textsize;
 
@@ -3032,12 +3017,11 @@ coffstab_build_psymtabs (struct objfile *objfile,
   val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
   if (val < 0)
     perror_with_name (name);
-  val = bfd_bread (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
+  val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
   if (val != stabstrsize)
     perror_with_name (name);
 
   stabsread_new_init ();
-  buildsym_init ();
   free_header_files ();
   init_header_files ();
 
@@ -3046,27 +3030,28 @@ coffstab_build_psymtabs (struct objfile *objfile,
   /* In a coff file, we've already installed the minimal symbols that came
      from the coff (non-stab) symbol table, so always act like an
      incremental load here.  */
-  if (stabsects->next == NULL)
+  scoped_restore save_symbuf_sections
+    = make_scoped_restore (&symbuf_sections);
+  if (stabsects.size () == 1)
     {
-      stabsize = bfd_section_size (sym_bfd, stabsects->section);
+      stabsize = bfd_section_size (stabsects[0]);
       DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
-      DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
+      DBX_SYMTAB_OFFSET (objfile) = stabsects[0]->filepos;
     }
   else
     {
-      struct stab_section_list *stabsect;
-
       DBX_SYMCOUNT (objfile) = 0;
-      for (stabsect = stabsects; stabsect != NULL; stabsect = stabsect->next)
+      for (asection *section : stabsects)
        {
-         stabsize = bfd_section_size (sym_bfd, stabsect->section);
+         stabsize = bfd_section_size (section);
          DBX_SYMCOUNT (objfile) += stabsize / DBX_SYMBOL_SIZE (objfile);
        }
 
-      DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
+      DBX_SYMTAB_OFFSET (objfile) = stabsects[0]->filepos;
 
-      symbuf_sections = stabsects->next;
-      symbuf_left = bfd_section_size (sym_bfd, stabsects->section);
+      sect_idx = 1;
+      symbuf_sections = &stabsects;
+      symbuf_left = bfd_section_size (stabsects[0]);
       symbuf_read = 0;
     }
 
@@ -3094,8 +3079,13 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect,
                        file_ptr stabstroffset, unsigned int stabstrsize)
 {
   int val;
-  bfd *sym_bfd = objfile->obfd;
-  char *name = bfd_get_filename (sym_bfd);
+  bfd *sym_bfd = objfile->obfd.get ();
+  const char *name = bfd_get_filename (sym_bfd);
+
+  stabsread_new_init ();
+
+  /* Allocate struct to keep track of stab reading.  */
+  dbx_objfile_data_key.emplace (objfile);
 
   /* Find the first and last text address.  dbx_symfile_read seems to
      want this.  */
@@ -3104,7 +3094,7 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect,
 #define        ELF_STABS_SYMBOL_SIZE   12      /* XXX FIXME XXX */
   DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE;
   DBX_SYMCOUNT (objfile)
-    = bfd_section_size (objfile->obfd, stabsect) / DBX_SYMBOL_SIZE (objfile);
+    = bfd_section_size (stabsect) / DBX_SYMBOL_SIZE (objfile);
   DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
   DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos;
   DBX_STAB_SECTION (objfile) = stabsect;
@@ -3120,19 +3110,18 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect,
   val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
   if (val < 0)
     perror_with_name (name);
-  val = bfd_bread (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
+  val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
   if (val != stabstrsize)
     perror_with_name (name);
 
   stabsread_new_init ();
-  buildsym_init ();
   free_header_files ();
   init_header_files ();
 
   processing_acc_compilation = 1;
 
   symbuf_read = 0;
-  symbuf_left = bfd_section_size (objfile->obfd, stabsect);
+  symbuf_left = bfd_section_size (stabsect);
 
   scoped_restore restore_stabs_data = make_scoped_restore (&stabs_data);
   gdb::unique_xmalloc_ptr<gdb_byte> data_holder;
@@ -3171,12 +3160,11 @@ stabsect_build_psymtabs (struct objfile *objfile, char *stab_name,
                         char *stabstr_name, char *text_name)
 {
   int val;
-  bfd *sym_bfd = objfile->obfd;
-  char *name = bfd_get_filename (sym_bfd);
+  bfd *sym_bfd = objfile->obfd.get ();
+  const char *name = bfd_get_filename (sym_bfd);
   asection *stabsect;
   asection *stabstrsect;
   asection *text_sect;
-  struct dbx_symfile_info *dbx;
 
   stabsect = bfd_get_section_by_name (sym_bfd, stab_name);
   stabstrsect = bfd_get_section_by_name (sym_bfd, stabstr_name);
@@ -3189,19 +3177,18 @@ stabsect_build_psymtabs (struct objfile *objfile, char *stab_name,
             "but not string section (%s)"),
           stab_name, stabstr_name);
 
-  dbx = XCNEW (struct dbx_symfile_info);
-  set_objfile_data (objfile, dbx_objfile_data_key, dbx);
+  dbx_objfile_data_key.emplace (objfile);
 
   text_sect = bfd_get_section_by_name (sym_bfd, text_name);
   if (!text_sect)
     error (_("Can't find %s section in symbol file"), text_name);
-  DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
-  DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+  DBX_TEXT_ADDR (objfile) = bfd_section_vma (text_sect);
+  DBX_TEXT_SIZE (objfile) = bfd_section_size (text_sect);
 
   DBX_SYMBOL_SIZE (objfile) = sizeof (struct external_nlist);
-  DBX_SYMCOUNT (objfile) = bfd_section_size (sym_bfd, stabsect)
+  DBX_SYMCOUNT (objfile) = bfd_section_size (stabsect)
     / DBX_SYMBOL_SIZE (objfile);
-  DBX_STRINGTAB_SIZE (objfile) = bfd_section_size (sym_bfd, stabstrsect);
+  DBX_STRINGTAB_SIZE (objfile) = bfd_section_size (stabstrsect);
   DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos;     /* XXX - FIXME: POKING
                                                           INSIDE BFD DATA
                                                           STRUCTURES */
@@ -3227,7 +3214,6 @@ stabsect_build_psymtabs (struct objfile *objfile, char *stab_name,
     perror_with_name (name);
 
   stabsread_new_init ();
-  buildsym_init ();
   free_header_files ();
   init_header_files ();
 
@@ -3242,21 +3228,17 @@ static const struct sym_fns aout_sym_fns =
   dbx_new_init,                        /* init anything gbl to entire symtab */
   dbx_symfile_init,            /* read initial info, setup for sym_read() */
   dbx_symfile_read,            /* read a symbol file into symtab */
-  NULL,                                /* sym_read_psymbols */
   dbx_symfile_finish,          /* finished with file, cleanup */
   default_symfile_offsets,     /* parse user's offsets to internal form */
   default_symfile_segments,    /* Get segment information from a file.  */
   NULL,
   default_symfile_relocate,    /* Relocate a debug section.  */
   NULL,                                /* sym_probe_fns */
-  &psym_functions
 };
 
+void _initialize_dbxread ();
 void
-_initialize_dbxread (void)
+_initialize_dbxread ()
 {
   add_symtab_fns (bfd_target_aout_flavour, &aout_sym_fns);
-
-  dbx_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, dbx_free_symfile_info);
 }