Patchwork [RFA,09/15] Introduce class psymtab_storage

login
register
mail settings
Submitter Tom Tromey
Date May 10, 2018, 10:23 p.m.
Message ID <20180510222357.27332-10-tom@tromey.com>
Download mbox | patch
Permalink /patch/27218/
State New
Headers show

Comments

Tom Tromey - May 10, 2018, 10:23 p.m.
This introduces a new psymtab_storage class, which holds all
psymbol-related objects that are independent of the objfile.  (This
latter contraint explains why psymbol_map was not moved; though this
could still be done with some work.)

This patch does not yet change where psymtab allocation is done --
that comes later.  This just wraps everything in a single object to
make further transformations simpler.

Note that a shared_ptr is used to link from the objfile to the
psymtab_storage object.  The end goal here is to allow a given symbol
reader to simply attach to the psymtab_storage object to the BFD, then
reuse it in later invocations; shared_ptr makes this simple to reason
about.

2018-05-10  Tom Tromey  <tom@tromey.com>

	* symmisc.c (print_symbol_bcache_statistics): Update.
	(print_objfile_statistics): Update.
	* symfile.c (reread_symbols): Update.
	* psymtab.h (class psymtab_storage): New.
	* psymtab.c (psymtab_storage): New constructor.
	(~psymtab_storage): New destructor.
	(require_partial_symbols): Update.
	(ALL_OBJFILE_PSYMTABS_REQUIRED): Rewrite.
	(find_pc_sect_psymtab, find_pc_sect_psymbol)
	(match_partial_symbol, lookup_partial_symbol, dump_psymtab)
	(psym_dump, recursively_search_psymtabs, psym_has_symbols)
	(psym_find_compunit_symtab_by_address, sort_pst_symbols)
	(start_psymtab_common, end_psymtab_common)
	(add_psymbol_to_bcache, add_psymbol_to_list, init_psymbol_list)
	(allocate_psymtab): Update.
	(psymtab_storage::discard_psymtab): Rename from discard_psymtab.
	Update.
	(dump_psymtab_addrmap, maintenance_print_psymbols)
	(maintenance_check_psymtabs): Update.
	* psympriv.h (discard_psymtab): Now inline.
	(psymtab_discarder::psymtab_discarder): Update.
	(psymtab_discarder::~psymtab_discarder): Update.
	(ALL_OBJFILE_PSYMTABS): Rewrite.
	* objfiles.h (struct objfile) <psymtabs, psymtabs_addrmap,
	free_psymtabs, psymbol_cache, global_psymbols, static_psymbols>:
	Remove fields.
	<partial_symtabs>: New field.
	* objfiles.c (objfile::objfile): Initialize partial_symtabs, not
	psymbol_cache.
	(objfile::~objfile): Don't destroy psymbol_cache.
	* mdebugread.c (parse_partial_symbols): Update.
	* dwarf2read.c (create_addrmap_from_index)
	(create_addrmap_from_aranges, dw2_find_pc_sect_compunit_symtab)
	(process_psymtab_comp_unit_reader, dwarf2_build_psymtabs_hard)
	(add_partial_subprogram, dwarf2_ranges_read): Update.
	* dwarf-index-write.c (write_address_map)
	(write_one_signatured_type, recursively_write_psymbols)
	(class debug_names, class debug_names, write_psymtabs_to_index):
	Update.
---
 gdb/ChangeLog           |  42 ++++++++++++++
 gdb/dwarf-index-write.c |  27 +++++----
 gdb/dwarf2read.c        |  32 ++++++-----
 gdb/mdebugread.c        |  11 ++--
 gdb/objfiles.c          |   5 +-
 gdb/objfiles.h          |  29 +---------
 gdb/psympriv.h          |  17 ++++--
 gdb/psymtab.c           | 150 +++++++++++++++++++++++++++++-------------------
 gdb/psymtab.h           |  62 ++++++++++++++++++++
 gdb/symfile.c           |  14 ++---
 gdb/symmisc.c           |  12 ++--
 11 files changed, 265 insertions(+), 136 deletions(-)

Patch

diff --git a/gdb/dwarf-index-write.c b/gdb/dwarf-index-write.c
index 03e8542015..669d8bafb6 100644
--- a/gdb/dwarf-index-write.c
+++ b/gdb/dwarf-index-write.c
@@ -476,8 +476,8 @@  write_address_map (struct objfile *objfile, data_buf &addr_vec,
   addrmap_index_data.objfile = objfile;
   addrmap_index_data.previous_valid = 0;
 
-  addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker,
-		   &addrmap_index_data);
+  addrmap_foreach (objfile->partial_symtabs->psymtabs_addrmap,
+		   add_address_entry_worker, &addrmap_index_data);
 
   /* It's highly unlikely the last entry (end address = 0xff...ff)
      is valid, but we should still handle it.
@@ -584,13 +584,13 @@  write_one_signatured_type (void **slot, void *d)
 
   write_psymbols (info->symtab,
 		  info->psyms_seen,
-		  (info->objfile->global_psymbols.data ()
+		  (info->objfile->partial_symtabs->global_psymbols.data ()
 		   + psymtab->globals_offset),
 		  psymtab->n_global_syms, info->cu_index,
 		  0);
   write_psymbols (info->symtab,
 		  info->psyms_seen,
-		  (info->objfile->static_psymbols.data ()
+		  (info->objfile->partial_symtabs->static_psymbols.data ()
 		   + psymtab->statics_offset),
 		  psymtab->n_static_syms, info->cu_index,
 		  1);
@@ -641,12 +641,14 @@  recursively_write_psymbols (struct objfile *objfile,
 
   write_psymbols (symtab,
 		  psyms_seen,
-		  objfile->global_psymbols.data () + psymtab->globals_offset,
+		  (objfile->partial_symtabs->global_psymbols.data ()
+		   + psymtab->globals_offset),
 		  psymtab->n_global_syms, cu_index,
 		  0);
   write_psymbols (symtab,
 		  psyms_seen,
-		  objfile->static_psymbols.data () + psymtab->statics_offset,
+		  (objfile->partial_symtabs->static_psymbols.data ()
+		   + psymtab->statics_offset),
 		  psymtab->n_static_syms, cu_index,
 		  1);
 }
@@ -837,10 +839,12 @@  public:
 				    psyms_seen, cu_index);
 
     write_psymbols (psyms_seen,
-		    objfile->global_psymbols.data () + psymtab->globals_offset,
+		    (objfile->partial_symtabs->global_psymbols.data ()
+		     + psymtab->globals_offset),
 		    psymtab->n_global_syms, cu_index, false, unit_kind::cu);
     write_psymbols (psyms_seen,
-		    objfile->static_psymbols.data () + psymtab->statics_offset,
+		    (objfile->partial_symtabs->static_psymbols.data ()
+		     + psymtab->statics_offset),
 		    psymtab->n_static_syms, cu_index, true, unit_kind::cu);
   }
 
@@ -1198,12 +1202,12 @@  private:
     struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
 
     write_psymbols (info->psyms_seen,
-		    (info->objfile->global_psymbols.data ()
+		    (info->objfile->partial_symtabs->global_psymbols.data ()
 		     + psymtab->globals_offset),
 		    psymtab->n_global_syms, info->cu_index, false,
 		    unit_kind::tu);
     write_psymbols (info->psyms_seen,
-		    (info->objfile->static_psymbols.data ()
+		    (info->objfile->partial_symtabs->static_psymbols.data ()
 		     + psymtab->statics_offset),
 		    psymtab->n_static_syms, info->cu_index, true,
 		    unit_kind::tu);
@@ -1557,7 +1561,8 @@  write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
   if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
     error (_("Cannot make an index when the file has multiple .debug_types sections"));
 
-  if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
+  if (!objfile->partial_symtabs->psymtabs
+      || !objfile->partial_symtabs->psymtabs_addrmap)
     return;
 
   struct stat st;
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index bf6e4b865a..03cb4e9d1e 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -3186,8 +3186,8 @@  create_addrmap_from_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
 			 dwarf2_per_objfile->get_cu (cu_index));
     }
 
-  objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
-						    &objfile->objfile_obstack);
+  objfile->partial_symtabs->psymtabs_addrmap
+    = addrmap_create_fixed (mutable_map, &objfile->objfile_obstack);
 }
 
 /* Read the address map data from DWARF-5 .debug_aranges, and use it to
@@ -3347,8 +3347,8 @@  create_addrmap_from_aranges (struct dwarf2_per_objfile *dwarf2_per_objfile,
 	}
     }
 
-  objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
-						    &objfile->objfile_obstack);
+  objfile->partial_symtabs->psymtabs_addrmap
+    = addrmap_create_fixed (mutable_map, &objfile->objfile_obstack);
 }
 
 /* Find a slot in the mapped index INDEX for the object named NAME.
@@ -5233,13 +5233,13 @@  dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
   struct dwarf2_per_cu_data *data;
   struct compunit_symtab *result;
 
-  if (!objfile->psymtabs_addrmap)
+  if (!objfile->partial_symtabs->psymtabs_addrmap)
     return NULL;
 
   CORE_ADDR baseaddr;
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-  data = (struct dwarf2_per_cu_data *) addrmap_find (objfile->psymtabs_addrmap,
-						     pc - baseaddr);
+  data = (struct dwarf2_per_cu_data *) addrmap_find
+    (objfile->partial_symtabs->psymtabs_addrmap, pc - baseaddr);
   if (!data)
     return NULL;
 
@@ -7936,7 +7936,8 @@  process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
 	   - baseaddr - 1);
       /* Store the contiguous range if it is not empty; it can be
 	 empty for CUs with no code.  */
-      addrmap_set_empty (objfile->psymtabs_addrmap, low, high, pst);
+      addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+			 low, high, pst);
     }
 
   /* Check if comp unit has_children.
@@ -8400,7 +8401,7 @@  dwarf2_build_psymtabs_hard (struct dwarf2_per_objfile *dwarf2_per_objfile)
   auto_obstack temp_obstack;
 
   scoped_restore save_psymtabs_addrmap
-    = make_scoped_restore (&objfile->psymtabs_addrmap,
+    = make_scoped_restore (&objfile->partial_symtabs->psymtabs_addrmap,
 			   addrmap_create_mutable (&temp_obstack));
 
   for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
@@ -8421,8 +8422,9 @@  dwarf2_build_psymtabs_hard (struct dwarf2_per_objfile *dwarf2_per_objfile)
 
   set_partial_user (dwarf2_per_objfile);
 
-  objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
-						    &objfile->objfile_obstack);
+  objfile->partial_symtabs->psymtabs_addrmap
+    = addrmap_create_fixed (objfile->partial_symtabs->psymtabs_addrmap,
+			    &objfile->objfile_obstack);
   /* At this point we want to keep the address map.  */
   save_psymtabs_addrmap.release ();
 
@@ -9047,8 +9049,8 @@  add_partial_subprogram (struct partial_die_info *pdi,
 	      highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
 						    pdi->highpc + baseaddr)
 			- baseaddr);
-	      addrmap_set_empty (objfile->psymtabs_addrmap, lowpc, highpc - 1,
-				 cu->per_cu->v.psymtab);
+	      addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+				 lowpc, highpc - 1, cu->per_cu->v.psymtab);
 	    }
         }
 
@@ -14519,8 +14521,8 @@  dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
 					      range_beginning + baseaddr);
 	  highpc = gdbarch_adjust_dwarf2_addr (gdbarch,
 					       range_end + baseaddr);
-	  addrmap_set_empty (objfile->psymtabs_addrmap, lowpc, highpc - 1,
-			     ranges_pst);
+	  addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+			     lowpc, highpc - 1, ranges_pst);
 	}
 
       /* FIXME: This is recording everything as a low-high
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 785e9dbfa0..4e07d37f54 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -3784,11 +3784,12 @@  parse_partial_symbols (minimal_symbol_reader &reader,
 
   /* Remove the dummy psymtab created for -O3 images above, if it is
      still empty, to enable the detection of stripped executables.  */
-  if (objfile->psymtabs->next == NULL
-      && objfile->psymtabs->number_of_dependencies == 0
-      && objfile->psymtabs->n_global_syms == 0
-      && objfile->psymtabs->n_static_syms == 0)
-    objfile->psymtabs = NULL;
+  pst = objfile->partial_symtabs->psymtabs;
+  if (pst->next == NULL
+      && pst->number_of_dependencies == 0
+      && pst->n_global_syms == 0
+      && pst->n_static_syms == 0)
+    objfile->partial_symtabs->psymtabs = NULL;
   do_cleanups (old_chain);
 }
 
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index e0b6ac30a9..aaca3eff70 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -374,8 +374,8 @@  build_objfile_section_table (struct objfile *objfile)
 objfile::objfile (bfd *abfd, const char *name, objfile_flags flags_)
   : flags (flags_),
     pspace (current_program_space),
-    obfd (abfd),
-    psymbol_cache (psymbol_bcache_init ())
+    partial_symtabs (new psymtab_storage (this)),
+    obfd (abfd)
 {
   const char *expanded_name;
 
@@ -718,7 +718,6 @@  objfile::~objfile ()
   }
 
   /* Free the obstacks for non-reusable objfiles.  */
-  psymbol_bcache_free (psymbol_cache);
   obstack_free (&objfile_obstack, 0);
 
   /* Rebuild section map next time we need it.  */
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 225060d22f..a49954df60 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -27,6 +27,7 @@ 
 #include "progspace.h"
 #include "registry.h"
 #include "gdb_bfd.h"
+#include "psymtab.h"
 #include <vector>
 #include <unordered_map>
 
@@ -320,22 +321,9 @@  struct objfile
 
   struct compunit_symtab *compunit_symtabs = nullptr;
 
-  /* Each objfile points to a linked list of partial symtabs derived from
-     this file, one partial symtab structure for each compilation unit
-     (source file).  */
+  /* The partial symbol tables.  */
 
-  struct partial_symtab *psymtabs = nullptr;
-
-  /* Map addresses to the entries of PSYMTABS.  It would be more efficient to
-     have a map per the whole process but ADDRMAP cannot selectively remove
-     its items during FREE_OBJFILE.  This mapping is already present even for
-     PARTIAL_SYMTABs which still have no corresponding full SYMTABs read.  */
-
-  struct addrmap *psymtabs_addrmap = nullptr;
-
-  /* List of freed partial symtabs, available for re-use.  */
-
-  struct partial_symtab *free_psymtabs = nullptr;
+  std::shared_ptr<psymtab_storage> partial_symtabs;
 
   /* The object file's BFD.  Can be null if the objfile contains only
      minimal symbols, e.g. the run time common symbols for SunOS4.  */
@@ -357,22 +345,11 @@  struct objfile
 
   struct obstack objfile_obstack {};
 
-  /* A byte cache where we can stash arbitrary "chunks" of bytes that
-     will not change.  */
-
-  struct psymbol_bcache *psymbol_cache;
-
   /* Map symbol addresses to the partial symtab that defines the
      object at that address.  */
 
   std::vector<std::pair<CORE_ADDR, partial_symtab *>> psymbol_map;
 
-  /* Vectors of all partial symbols read in from file.  The actual data
-     is stored in the objfile_obstack.  */
-
-  std::vector<partial_symbol *> global_psymbols;
-  std::vector<partial_symbol *> static_psymbols;
-
   /* Map from a psymtab to its corresponding full symtab.  If a
      psymtab is read in but fails to resolve to a full symtab, this
      map will hold an entry for the psymtab that maps to nullptr.  */
diff --git a/gdb/psympriv.h b/gdb/psympriv.h
index 969215e2f1..c299ce7c18 100644
--- a/gdb/psympriv.h
+++ b/gdb/psympriv.h
@@ -305,7 +305,11 @@  extern struct partial_symtab *allocate_psymtab (const char *filename,
 						struct objfile *objfile)
   ATTRIBUTE_NONNULL (1);
 
-extern void discard_psymtab (struct objfile *, struct partial_symtab *);
+static inline void
+discard_psymtab (struct objfile *objfile, struct partial_symtab *pst)
+{
+  objfile->partial_symtabs->discard_psymtab (pst);
+}
 
 /* Used when recording partial symbol tables.  On destruction,
    discards any partial symbol tables that have been built.  However,
@@ -316,15 +320,14 @@  class psymtab_discarder
 
   psymtab_discarder (struct objfile *objfile)
     : m_objfile (objfile),
-      m_psymtab (objfile->psymtabs)
+      m_psymtab (objfile->partial_symtabs->psymtabs)
   {
   }
 
   ~psymtab_discarder ()
   {
     if (m_objfile != NULL)
-      while (m_objfile->psymtabs != m_psymtab)
-	discard_psymtab (m_objfile, m_objfile->psymtabs);
+      m_objfile->partial_symtabs->discard_psymtabs_to (m_psymtab);
   }
 
   /* Keep any partial symbol tables that were built.  */
@@ -344,7 +347,9 @@  class psymtab_discarder
 
 /* Traverse all psymtabs in one objfile.  */
 
-#define	ALL_OBJFILE_PSYMTABS(objfile, p) \
-    for ((p) = (objfile) -> psymtabs; (p) != NULL; (p) = (p) -> next)
+#define	ALL_OBJFILE_PSYMTABS(objfile, p)		\
+    for ((p) = (objfile) -> partial_symtabs->psymtabs;	\
+	 (p) != NULL;					\
+	 (p) = (p) -> next)
 
 #endif /* PSYMPRIV_H */
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index f2177c76ee..f50d0576f8 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -65,6 +65,21 @@  static struct partial_symbol *find_pc_sect_psymbol (struct objfile *,
 static struct compunit_symtab *psymtab_to_symtab (struct objfile *objfile,
 						  struct partial_symtab *pst);
 
+
+
+psymtab_storage::psymtab_storage (struct objfile *objfile)
+  : obstack (&objfile->objfile_obstack),
+    psymbol_cache (psymbol_bcache_init ())
+{
+}
+
+psymtab_storage::~psymtab_storage ()
+{
+  psymbol_bcache_free (psymbol_cache);
+}
+
+
+
 /* Ensure that the partial symbols for OBJFILE have been loaded.  This
    function always returns its argument, as a convenience.  */
 
@@ -87,8 +102,8 @@  require_partial_symbols (struct objfile *objfile, int verbose)
 
 	  /* Partial symbols list are not expected to changed after this
 	     point.  */
-	  objfile->global_psymbols.shrink_to_fit ();
-	  objfile->static_psymbols.shrink_to_fit ();
+	  objfile->partial_symtabs->global_psymbols.shrink_to_fit ();
+	  objfile->partial_symtabs->static_psymbols.shrink_to_fit ();
 
 	  if (verbose)
 	    {
@@ -110,9 +125,10 @@  require_partial_symbols (struct objfile *objfile, int verbose)
 /* Traverse all psymtabs in one objfile, requiring that the psymtabs
    be read in.  */
 
-#define ALL_OBJFILE_PSYMTABS_REQUIRED(objfile, p)		\
-    for ((p) = require_partial_symbols (objfile, 1)->psymtabs;	\
-	 (p) != NULL;						\
+#define ALL_OBJFILE_PSYMTABS_REQUIRED(objfile, p)			\
+    for ((p) = require_partial_symbols (objfile,			\
+					1)->partial_symtabs->psymtabs;	\
+	 (p) != NULL;							\
 	 (p) = (p)->next)
 
 /* We want to make sure this file always requires psymtabs.  */
@@ -315,10 +331,11 @@  find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc,
   /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
      than the later used TEXTLOW/TEXTHIGH one.  */
 
-  if (objfile->psymtabs_addrmap != NULL)
+  if (objfile->partial_symtabs->psymtabs_addrmap != NULL)
     {
       pst = ((struct partial_symtab *)
-	     addrmap_find (objfile->psymtabs_addrmap, pc - baseaddr));
+	     addrmap_find (objfile->partial_symtabs->psymtabs_addrmap,
+			   pc - baseaddr));
       if (pst != NULL)
 	{
 	  /* FIXME: addrmaps currently do not handle overlayed sections,
@@ -425,7 +442,9 @@  find_pc_sect_psymbol (struct objfile *objfile,
      cache a bad endaddr.  */
   for (int i = 0; i < psymtab->n_global_syms; i++)
     {
-      partial_symbol *p = objfile->global_psymbols[psymtab->globals_offset + i];
+      partial_symbol *p
+	= objfile->partial_symtabs->global_psymbols[psymtab->globals_offset
+						    + i];
 
       if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
 	  && PSYMBOL_CLASS (p) == LOC_BLOCK
@@ -448,7 +467,9 @@  find_pc_sect_psymbol (struct objfile *objfile,
 
   for (int i = 0; i < psymtab->n_static_syms; i++)
     {
-      partial_symbol *p = objfile->static_psymbols[psymtab->statics_offset + i];
+      partial_symbol *p
+	= objfile->partial_symtabs->static_psymbols[psymtab->statics_offset
+						    + i];
 
       if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
 	  && PSYMBOL_CLASS (p) == LOC_BLOCK
@@ -559,8 +580,8 @@  match_partial_symbol (struct objfile *objfile,
   lookup_name_info lookup_name (name, match_type);
 
   start = (global ?
-	   &objfile->global_psymbols[pst->globals_offset] :
-	   &objfile->static_psymbols[pst->statics_offset]);
+	   &objfile->partial_symtabs->global_psymbols[pst->globals_offset] :
+	   &objfile->partial_symtabs->static_psymbols[pst->statics_offset]);
 
   if (global && ordered_compare)  /* Can use a binary search.  */
     {
@@ -669,8 +690,8 @@  lookup_partial_symbol (struct objfile *objfile,
   lookup_name_info lookup_name (search_name.get (), symbol_name_match_type::FULL);
 
   start = (global ?
-	   &objfile->global_psymbols[pst->globals_offset] :
-	   &objfile->static_psymbols[pst->statics_offset]);
+	   &objfile->partial_symtabs->global_psymbols[pst->globals_offset] :
+	   &objfile->partial_symtabs->static_psymbols[pst->statics_offset]);
 
   if (global)			/* This means we can use a binary search.  */
     {
@@ -976,15 +997,17 @@  dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
     }
   if (psymtab->n_global_syms > 0)
     {
-      print_partial_symbols (gdbarch, objfile,
-			     &objfile->global_psymbols[psymtab->globals_offset],
-			     psymtab->n_global_syms, "Global", outfile);
+      print_partial_symbols
+	(gdbarch, objfile,
+	 &objfile->partial_symtabs->global_psymbols[psymtab->globals_offset],
+	 psymtab->n_global_syms, "Global", outfile);
     }
   if (psymtab->n_static_syms > 0)
     {
-      print_partial_symbols (gdbarch, objfile,
-			     &objfile->static_psymbols[psymtab->statics_offset],
-			     psymtab->n_static_syms, "Static", outfile);
+      print_partial_symbols
+	(gdbarch, objfile,
+	 &objfile->partial_symtabs->static_psymbols[psymtab->statics_offset],
+	 psymtab->n_static_syms, "Static", outfile);
     }
   fprintf_filtered (outfile, "\n");
 }
@@ -1015,10 +1038,10 @@  psym_dump (struct objfile *objfile)
 {
   struct partial_symtab *psymtab;
 
-  if (objfile->psymtabs)
+  if (objfile->partial_symtabs->psymtabs)
     {
       printf_filtered ("Psymtabs:\n");
-      for (psymtab = objfile->psymtabs;
+      for (psymtab = objfile->partial_symtabs->psymtabs;
 	   psymtab != NULL;
 	   psymtab = psymtab->next)
 	{
@@ -1279,21 +1302,25 @@  recursively_search_psymtabs
     }
 
   partial_symbol **gbound
-    = objfile->global_psymbols.data () + ps->globals_offset + ps->n_global_syms;
+    = (objfile->partial_symtabs->global_psymbols.data ()
+       + ps->globals_offset + ps->n_global_syms);
   partial_symbol **sbound
-    = objfile->static_psymbols.data () + ps->statics_offset + ps->n_static_syms;
+    = (objfile->partial_symtabs->static_psymbols.data ()
+       + ps->statics_offset + ps->n_static_syms);
   partial_symbol **bound = gbound;
 
   /* Go through all of the symbols stored in a partial
      symtab in one loop.  */
-  partial_symbol **psym = objfile->global_psymbols.data () + ps->globals_offset;
+  partial_symbol **psym = (objfile->partial_symtabs->global_psymbols.data ()
+			   + ps->globals_offset);
   while (keep_going)
     {
       if (psym >= bound)
 	{
 	  if (bound == gbound && ps->n_static_syms != 0)
 	    {
-	      psym = objfile->static_psymbols.data () + ps->statics_offset;
+	      psym = (objfile->partial_symtabs->static_psymbols.data ()
+		      + ps->statics_offset);
 	      bound = sbound;
 	    }
 	  else
@@ -1399,7 +1426,7 @@  psym_expand_symtabs_matching
 static int
 psym_has_symbols (struct objfile *objfile)
 {
-  return objfile->psymtabs != NULL;
+  return objfile->partial_symtabs->psymtabs != NULL;
 }
 
 /* Helper function for psym_find_compunit_symtab_by_address that fills
@@ -1446,12 +1473,12 @@  psym_find_compunit_symtab_by_address (struct objfile *objfile,
       {
 	psym_fill_psymbol_map (objfile, pst,
 			       &seen_addrs,
-			       objfile->global_psymbols,
+			       objfile->partial_symtabs->global_psymbols,
 			       pst->globals_offset,
 			       pst->n_global_syms);
 	psym_fill_psymbol_map (objfile, pst,
 			       &seen_addrs,
-			       objfile->static_psymbols,
+			       objfile->partial_symtabs->static_psymbols,
 			       pst->statics_offset,
 			       pst->n_static_syms);
       }
@@ -1505,12 +1532,12 @@  static void
 sort_pst_symbols (struct objfile *objfile, struct partial_symtab *pst)
 {
   /* Sort the global list; don't sort the static list.  */
-  auto begin = objfile->global_psymbols.begin ();
+  auto begin = objfile->partial_symtabs->global_psymbols.begin ();
   std::advance (begin, pst->globals_offset);
 
   /* The psymbols for this partial_symtab are currently at the end of the
      vector.  */
-  auto end = objfile->global_psymbols.end ();
+  auto end = objfile->partial_symtabs->global_psymbols.end ();
 
   std::sort (begin, end, [] (partial_symbol *s1, partial_symbol *s2)
     {
@@ -1534,8 +1561,8 @@  start_psymtab_common (struct objfile *objfile,
   psymtab = allocate_psymtab (filename, objfile);
   SET_PSYMTAB_TEXTLOW (psymtab, textlow);
   SET_PSYMTAB_TEXTHIGH (psymtab, PSYMTAB_RAW_TEXTLOW (psymtab)); /* default */
-  psymtab->globals_offset = objfile->global_psymbols.size ();
-  psymtab->statics_offset = objfile->static_psymbols.size ();
+  psymtab->globals_offset = objfile->partial_symtabs->global_psymbols.size ();
+  psymtab->statics_offset = objfile->partial_symtabs->static_psymbols.size ();
   return psymtab;
 }
 
@@ -1544,8 +1571,10 @@  start_psymtab_common (struct objfile *objfile,
 void
 end_psymtab_common (struct objfile *objfile, struct partial_symtab *pst)
 {
-  pst->n_global_syms = objfile->global_psymbols.size () - pst->globals_offset;
-  pst->n_static_syms = objfile->static_psymbols.size () - pst->statics_offset;
+  pst->n_global_syms = (objfile->partial_symtabs->global_psymbols.size ()
+			- pst->globals_offset);
+  pst->n_static_syms = (objfile->partial_symtabs->static_psymbols.size ()
+			- pst->statics_offset);
 
   sort_pst_symbols (objfile, pst);
 }
@@ -1673,7 +1702,9 @@  add_psymbol_to_bcache (const char *name, int namelength, int copy_name,
   PSYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile->per_bfd);
 
   /* Stash the partial symbol away in the cache.  */
-  return psymbol_bcache_full (&psymbol, objfile->psymbol_cache, added);
+  return psymbol_bcache_full (&psymbol,
+			      objfile->partial_symtabs->psymbol_cache,
+			      added);
 }
 
 /* Helper function, adds partial symbol to the given partial symbol list.  */
@@ -1717,8 +1748,8 @@  add_psymbol_to_list (const char *name, int namelength, int copy_name,
   /* Save pointer to partial symbol in psymtab, growing symtab if needed.  */
   std::vector<partial_symbol *> *list
     = (where == psymbol_placement::STATIC
-       ? &objfile->static_psymbols
-       : &objfile->global_psymbols);
+       ? &objfile->partial_symtabs->static_psymbols
+       : &objfile->partial_symtabs->global_psymbols);
   append_psymbol_to_list (list, psym, objfile);
 }
 
@@ -1727,15 +1758,15 @@  add_psymbol_to_list (const char *name, int namelength, int copy_name,
 void
 init_psymbol_list (struct objfile *objfile, int total_symbols)
 {
-  if (objfile->global_psymbols.capacity () == 0
-      && objfile->static_psymbols.capacity () == 0)
+  if (objfile->partial_symtabs->global_psymbols.capacity () == 0
+      && objfile->partial_symtabs->static_psymbols.capacity () == 0)
     return;
 
   /* Current best guess is that approximately a twentieth
      of the total symbols (in a debugging file) are global or static
      oriented symbols, then multiply that by slop factor of two.  */
-  objfile->global_psymbols.reserve (total_symbols / 10);
-  objfile->static_psymbols.reserve (total_symbols / 10);
+  objfile->partial_symtabs->global_psymbols.reserve (total_symbols / 10);
+  objfile->partial_symtabs->static_psymbols.reserve (total_symbols / 10);
 }
 
 /* See psympriv.h.  */
@@ -1745,10 +1776,10 @@  allocate_psymtab (const char *filename, struct objfile *objfile)
 {
   struct partial_symtab *psymtab;
 
-  if (objfile->free_psymtabs)
+  if (objfile->partial_symtabs->free_psymtabs)
     {
-      psymtab = objfile->free_psymtabs;
-      objfile->free_psymtabs = psymtab->next;
+      psymtab = objfile->partial_symtabs->free_psymtabs;
+      objfile->partial_symtabs->free_psymtabs = psymtab->next;
     }
   else
     psymtab = (struct partial_symtab *)
@@ -1764,8 +1795,8 @@  allocate_psymtab (const char *filename, struct objfile *objfile)
      Psymtabs are searched in most recent inserted -> least recent
      inserted order.  */
 
-  psymtab->next = objfile->psymtabs;
-  objfile->psymtabs = psymtab;
+  psymtab->next = objfile->partial_symtabs->psymtabs;
+  objfile->partial_symtabs->psymtabs = psymtab;
 
   if (symtab_create_debug)
     {
@@ -1791,7 +1822,7 @@  allocate_psymtab (const char *filename, struct objfile *objfile)
 }
 
 void
-discard_psymtab (struct objfile *objfile, struct partial_symtab *pst)
+psymtab_storage::discard_psymtab (struct partial_symtab *pst)
 {
   struct partial_symtab **prev_pst;
 
@@ -1804,15 +1835,15 @@  discard_psymtab (struct objfile *objfile, struct partial_symtab *pst)
 
   /* First, snip it out of the psymtab chain.  */
 
-  prev_pst = &(objfile->psymtabs);
+  prev_pst = &psymtabs;
   while ((*prev_pst) != pst)
     prev_pst = &((*prev_pst)->next);
   (*prev_pst) = pst->next;
 
   /* Next, put it on a free list for recycling.  */
 
-  pst->next = objfile->free_psymtabs;
-  objfile->free_psymtabs = pst;
+  pst->next = free_psymtabs;
+  free_psymtabs = pst;
 }
 
 
@@ -1917,7 +1948,7 @@  dump_psymtab_addrmap (struct objfile *objfile, struct partial_symtab *psymtab,
 
   if ((psymtab == NULL
        || psymtab->psymtabs_addrmap_supported)
-      && objfile->psymtabs_addrmap != NULL)
+      && objfile->partial_symtabs->psymtabs_addrmap != NULL)
     {
       addrmap_dump_data.objfile = objfile;
       addrmap_dump_data.psymtab = psymtab;
@@ -1925,8 +1956,8 @@  dump_psymtab_addrmap (struct objfile *objfile, struct partial_symtab *psymtab,
       addrmap_dump_data.previous_matched = 0;
       fprintf_filtered (outfile, "%sddress map:\n",
 			psymtab == NULL ? "Entire a" : "  A");
-      addrmap_foreach (objfile->psymtabs_addrmap, dump_psymtab_addrmap_1,
-		       &addrmap_dump_data);
+      addrmap_foreach (objfile->partial_symtabs->psymtabs_addrmap,
+		       dump_psymtab_addrmap_1, &addrmap_dump_data);
     }
 }
 
@@ -2070,7 +2101,7 @@  maintenance_print_psymbols (const char *args, int from_tty)
 
       if (address_arg == NULL
 	  && source_arg == NULL
-	  && objfile->psymtabs_addrmap != NULL)
+	  && objfile->partial_symtabs->psymtabs_addrmap != NULL)
 	{
 	  outfile->puts ("\n");
 	  dump_psymtab_addrmap (objfile, NULL, outfile);
@@ -2149,7 +2180,8 @@  maintenance_info_psymtabs (const char *regexp, int from_tty)
 	      printf_filtered ("    globals ");
 	      if (psymtab->n_global_syms)
 		{
-		  auto p = &objfile->global_psymbols[psymtab->globals_offset];
+		  int off = psymtab->globals_offset;
+		  auto p = &objfile->partial_symtabs->global_psymbols[off];
 
 		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
 				   host_address_to_string (p),
@@ -2160,7 +2192,8 @@  maintenance_info_psymtabs (const char *regexp, int from_tty)
 	      printf_filtered ("    statics ");
 	      if (psymtab->n_static_syms)
 		{
-		  auto p = &objfile->static_psymbols[psymtab->statics_offset];
+		  int off = psymtab->statics_offset;
+		  auto p = &objfile->partial_symtabs->static_psymbols[off];
 
 		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
 				   host_address_to_string (p),
@@ -2239,7 +2272,8 @@  maintenance_check_psymtabs (const char *ignore, int from_tty)
       continue;
     bv = COMPUNIT_BLOCKVECTOR (cust);
     b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-    partial_symbol **psym = &objfile->static_psymbols[ps->statics_offset];
+    partial_symbol **psym
+      = &objfile->partial_symtabs->static_psymbols[ps->statics_offset];
     length = ps->n_static_syms;
     while (length--)
       {
@@ -2257,7 +2291,7 @@  maintenance_check_psymtabs (const char *ignore, int from_tty)
 	psym++;
       }
     b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-    psym = &objfile->global_psymbols[ps->globals_offset];
+    psym = &objfile->partial_symtabs->global_psymbols[ps->globals_offset];
     length = ps->n_global_syms;
     while (length--)
       {
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
index 7c5bf80e70..58c4bee98a 100644
--- a/gdb/psymtab.h
+++ b/gdb/psymtab.h
@@ -25,9 +25,71 @@ 
 /* A bcache for partial symbols.  */
 
 struct compunit_symtab;
+struct partial_symbol;
 struct partial_symtab;
 struct psymbol_bcache;
 
+/* An instance of this class manages the partial symbol tables and
+   partial symbols for a given objfile.  */
+
+class psymtab_storage
+{
+public:
+
+  explicit psymtab_storage (struct objfile *objfile);
+
+  ~psymtab_storage ();
+
+  DISABLE_COPY_AND_ASSIGN (psymtab_storage);
+
+  /* Discard all partial symbol tables starting with "psymtabs" and
+     proceeding until "to" has been discarded.  */
+
+  void discard_psymtabs_to (struct partial_symtab *to)
+  {
+    while (psymtabs != to)
+      discard_psymtab (psymtabs);
+  }
+
+  /* Discard the partial symbol table.  */
+
+  void discard_psymtab (struct partial_symtab *pst);
+
+
+  /* Each objfile points to a linked list of partial symtabs derived from
+     this file, one partial symtab structure for each compilation unit
+     (source file).  */
+
+  struct partial_symtab *psymtabs = nullptr;
+
+  /* Map addresses to the entries of PSYMTABS.  It would be more efficient to
+     have a map per the whole process but ADDRMAP cannot selectively remove
+     its items during FREE_OBJFILE.  This mapping is already present even for
+     PARTIAL_SYMTABs which still have no corresponding full SYMTABs read.  */
+
+  struct addrmap *psymtabs_addrmap = nullptr;
+
+  /* List of freed partial symtabs, available for re-use.  */
+
+  struct partial_symtab *free_psymtabs = nullptr;
+
+  /* The obstack where allocations are made.  */
+
+  struct obstack *obstack;
+
+  /* A byte cache where we can stash arbitrary "chunks" of bytes that
+     will not change.  */
+
+  struct psymbol_bcache *psymbol_cache;
+
+  /* Vectors of all partial symbols read in from file.  The actual data
+     is stored in the objfile_obstack.  */
+
+  std::vector<partial_symbol *> global_psymbols;
+  std::vector<partial_symbol *> static_psymbols;
+};
+
+
 extern struct psymbol_bcache *psymbol_bcache_init (void);
 extern void psymbol_bcache_free (struct psymbol_bcache *);
 extern struct bcache *psymbol_bcache_get_bcache (struct psymbol_bcache *);
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 8a63fe34d3..a23c051c3e 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2397,22 +2397,22 @@  reread_symbols (void)
 
 	  /* FIXME: Do we have to free a whole linked list, or is this
 	     enough?  */
-	  objfile->global_psymbols.clear ();
-	  objfile->static_psymbols.clear ();
+	  objfile->partial_symtabs->global_psymbols.clear ();
+	  objfile->partial_symtabs->static_psymbols.clear ();
 	  objfile->psymtab_map.clear ();
 
 	  /* Free the obstacks for non-reusable objfiles.  */
-	  psymbol_bcache_free (objfile->psymbol_cache);
-	  objfile->psymbol_cache = psymbol_bcache_init ();
+	  psymbol_bcache_free (objfile->partial_symtabs->psymbol_cache);
+	  objfile->partial_symtabs->psymbol_cache = psymbol_bcache_init ();
 
 	  /* NB: after this call to obstack_free, objfiles_changed
 	     will need to be called (see discussion below).  */
 	  obstack_free (&objfile->objfile_obstack, 0);
 	  objfile->sections = NULL;
 	  objfile->compunit_symtabs = NULL;
-	  objfile->psymtabs = NULL;
-	  objfile->psymtabs_addrmap = NULL;
-	  objfile->free_psymtabs = NULL;
+	  objfile->partial_symtabs->psymtabs = NULL;
+	  objfile->partial_symtabs->psymtabs_addrmap = NULL;
+	  objfile->partial_symtabs->free_psymtabs = NULL;
 	  objfile->template_symbols = NULL;
 
 	  /* obstack_init also initializes the obstack so it is
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 91ddc578a8..919c09a5c2 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -70,8 +70,9 @@  print_symbol_bcache_statistics (void)
     QUIT;
     printf_filtered (_("Byte cache statistics for '%s':\n"),
 		     objfile_name (objfile));
-    print_bcache_statistics (psymbol_bcache_get_bcache (objfile->psymbol_cache),
-                             "partial symbol cache");
+    print_bcache_statistics
+      (psymbol_bcache_get_bcache (objfile->partial_symtabs->psymbol_cache),
+       "partial symbol cache");
     print_bcache_statistics (objfile->per_bfd->macro_cache,
 			     "preprocessor macro cache");
     print_bcache_statistics (objfile->per_bfd->filename_cache,
@@ -134,9 +135,10 @@  print_objfile_statistics (void)
     printf_filtered (_("  Total memory used for BFD obstack: %s\n"),
 		     pulongest (obstack_memory_used (&objfile->per_bfd
 						     ->storage_obstack)));
-    printf_filtered (_("  Total memory used for psymbol cache: %d\n"),
-		     bcache_memory_used (psymbol_bcache_get_bcache
-		                          (objfile->psymbol_cache)));
+    printf_filtered
+      (_("  Total memory used for psymbol cache: %d\n"),
+       bcache_memory_used (psymbol_bcache_get_bcache
+			   (objfile->partial_symtabs->psymbol_cache)));
     printf_filtered (_("  Total memory used for macro cache: %d\n"),
 		     bcache_memory_used (objfile->per_bfd->macro_cache));
     printf_filtered (_("  Total memory used for file name cache: %d\n"),