Patchwork [RFA,08/15] Remove readin and compunit_symtab fields from psymtab

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

Comments

Tom Tromey - May 10, 2018, 10:23 p.m.
In order to move psymtabs off of the objfile obstack, there must be no
backlinks from the psymtab (or associated objects) to anything
allocated on the objfile obstack.

This patch removes the readin and compunit_symtab fields from psymtab
to help achieve this goal, replacing them with per-objfile maps
indicating which psymtabs have been read in.  This split will allow
for psymtab reuse across objfiles in the future.

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

	* symfile.c (reread_symbols): Clear psymtab_map.
	* xcoffread.c (read_xcoff_symtab, xcoff_psymtab_to_symtab_1)
	(xcoff_read_symtab): Update.
	* psymtab.h (associate_psymtab_with_symtab, psymtab_read_in_p)
	(get_psymtab_compunit): Declare.
	* psymtab.c (partial_map_expand_apply)
	(psym_find_pc_sect_compunit_symtab, psym_lookup_symbol)
	(psymtab_to_symtab, psym_find_last_source_symtab, dump_psymtab)
	(psym_print_stats, psym_expand_symtabs_for_function)
	(psym_map_symbol_filenames, psym_map_matching_symbols)
	(psym_expand_symtabs_matching, allocate_psymtab): Update.
	(associate_psymtab_with_symtab, psymtab_read_in_p)
	(get_psymtab_compunit): New functions.
	(maintenance_info_psymtabs, maintenance_check_psymtabs): Update.
	* psympriv.h (struct partial_symtab) <readin, compunit_symtab>:
	Remove.
	* objfiles.h (objfile::psymtab_map): New member.
	* mdebugread.c (psymtab_to_symtab_1): Update.
	* dwarf2read.c (dw2_do_instantiate_symtab, dwarf2_read_symtab)
	(process_queue): Update.
	(psymtab_to_symtab_1): Add 'objfile' parameter.
	(get_compunit_symtab, process_full_comp_unit)
	(process_full_type_unit): Update.
	* dbxread.c (dbx_psymtab_to_symtab_1, read_ofile_symtab): Update.
---
 gdb/ChangeLog    | 27 +++++++++++++++++++
 gdb/dbxread.c    | 13 ++++-----
 gdb/dwarf2read.c | 38 +++++++++++++++------------
 gdb/mdebugread.c |  8 +++---
 gdb/objfiles.h   |  6 +++++
 gdb/psympriv.h   | 11 --------
 gdb/psymtab.c    | 80 ++++++++++++++++++++++++++++++++++++++++----------------
 gdb/psymtab.h    | 27 +++++++++++++++++++
 gdb/symfile.c    |  1 +
 gdb/xcoffread.c  | 16 ++++++------
 10 files changed, 159 insertions(+), 68 deletions(-)
Simon Marchi - July 18, 2018, 3:34 a.m.
On 2018-05-10 06:23 PM, Tom Tromey wrote:
> In order to move psymtabs off of the objfile obstack, there must be no
> backlinks from the psymtab (or associated objects) to anything
> allocated on the objfile obstack.
> 
> This patch removes the readin and compunit_symtab fields from psymtab
> to help achieve this goal, replacing them with per-objfile maps
> indicating which psymtabs have been read in.  This split will allow
> for psymtab reuse across objfiles in the future.

This LGTM, but I have two question.  In the future, is the intent to also
make symtabs (compunit_symtab) independent from program spaces, and
shareable across objfiles, or would that not be possible?  If it is
possible, would the compunit_symtab pointer in psymtab re-appear, since
there would now again be a single compunit_symtab for each psymtab?

As Pedro pointed out a few times, unordered_map is an hash map with open
hashing.  So we change what was previously a single pointer dereference
to a lookup in a hash table, followed with a linear search in a linked
list.  If this map is looked up very frequently, maybe we should consider
using an htab_t instead?  Some profiling data would help, but it seems
like psymtab_read_in_p is called quite a bit when looking up symbols...

Simon

Patch

diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 17d53331a4..c3741fda8a 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -2149,7 +2149,7 @@  dbx_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
 {
   int i;
 
-  if (pst->readin)
+  if (psymtab_read_in_p (objfile, pst))
     {
       fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in.  "
 			  "Shouldn't happen.\n",
@@ -2159,7 +2159,7 @@  dbx_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
 
   /* 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)
+    if (!psymtab_read_in_p (objfile, pst->dependencies[i]))
       {
 	/* Inform about additional files that need to be read in.  */
 	if (info_verbose)
@@ -2189,7 +2189,7 @@  dbx_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
       read_ofile_symtab (objfile, pst);
     }
 
-  pst->readin = 1;
+  associate_psymtab_with_symtab (objfile, pst, nullptr, false);
 }
 
 /* Read in all of the symbols for a given psymtab for real.
@@ -2198,7 +2198,7 @@  dbx_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
 static void
 dbx_read_symtab (struct partial_symtab *self, struct objfile *objfile)
 {
-  if (self->readin)
+  if (psymtab_read_in_p (objfile, self))
     {
       fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in.  "
 			  "Shouldn't happen.\n",
@@ -2406,8 +2406,9 @@  read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
   if (last_source_start_addr > text_offset)
     last_source_start_addr = text_offset;
 
-  pst->compunit_symtab = end_symtab (text_offset + text_size,
-				     SECT_OFF_TEXT (objfile));
+  associate_psymtab_with_symtab (objfile, pst,
+				 end_symtab (text_offset + text_size,
+					     SECT_OFF_TEXT (objfile)));
 
   end_stabs ();
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 9e846e75bb..bf6e4b865a 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -1458,7 +1458,7 @@  static void add_partial_subprogram (struct partial_die_info *pdi,
 static void dwarf2_read_symtab (struct partial_symtab *,
 				struct objfile *);
 
-static void psymtab_to_symtab_1 (struct partial_symtab *);
+static void psymtab_to_symtab_1 (struct objfile *, struct partial_symtab *);
 
 static abbrev_table_up abbrev_table_read_table
   (struct dwarf2_per_objfile *dwarf2_per_objfile, struct dwarf2_section_info *,
@@ -2867,7 +2867,9 @@  dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
 
   if (dwarf2_per_objfile->using_index
       ? per_cu->v.quick->compunit_symtab == NULL
-      : (per_cu->v.psymtab == NULL || !per_cu->v.psymtab->readin))
+      : (per_cu->v.psymtab == NULL
+	 || !psymtab_read_in_p (dwarf2_per_objfile->objfile,
+				per_cu->v.psymtab)))
     {
       queue_comp_unit (per_cu, language_minimal);
       load_cu (per_cu);
@@ -9330,7 +9332,7 @@  dwarf2_read_symtab (struct partial_symtab *self,
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = get_dwarf2_per_objfile (objfile);
 
-  if (self->readin)
+  if (psymtab_read_in_p (objfile, self))
     {
       warning (_("bug: psymtab for %s is already read in."),
 	       self->filename);
@@ -9359,7 +9361,7 @@  dwarf2_read_symtab (struct partial_symtab *self,
 
       dwarf2_per_objfile->reading_partial_symbols = 0;
 
-      psymtab_to_symtab_1 (self);
+      psymtab_to_symtab_1 (objfile, self);
 
       /* Finish up the debug error message.  */
       if (info_verbose)
@@ -9460,7 +9462,9 @@  process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile)
     {
       if ((dwarf2_per_objfile->using_index
 	   ? !item->per_cu->v.quick->compunit_symtab
-	   : (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
+	   : (item->per_cu->v.psymtab
+	      && !psymtab_read_in_p (dwarf2_per_objfile->objfile,
+				     item->per_cu->v.psymtab)))
 	  /* Skip dummy CUs.  */
 	  && item->per_cu->cu != NULL)
 	{
@@ -9516,16 +9520,16 @@  process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile)
 /* Read in full symbols for PST, and anything it depends on.  */
 
 static void
-psymtab_to_symtab_1 (struct partial_symtab *pst)
+psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
 {
   struct dwarf2_per_cu_data *per_cu;
   int i;
 
-  if (pst->readin)
+  if (psymtab_read_in_p (objfile, pst))
     return;
 
   for (i = 0; i < pst->number_of_dependencies; i++)
-    if (!pst->dependencies[i]->readin
+    if (!psymtab_read_in_p (objfile, pst->dependencies[i])
 	&& pst->dependencies[i]->user == NULL)
       {
         /* Inform about additional files that need to be read in.  */
@@ -9540,7 +9544,7 @@  psymtab_to_symtab_1 (struct partial_symtab *pst)
             wrap_here ("");     /* Flush output.  */
             gdb_flush (gdb_stdout);
           }
-        psymtab_to_symtab_1 (pst->dependencies[i]);
+        psymtab_to_symtab_1 (objfile, pst->dependencies[i]);
       }
 
   per_cu = (struct dwarf2_per_cu_data *) pst->read_symtab_private;
@@ -9549,7 +9553,7 @@  psymtab_to_symtab_1 (struct partial_symtab *pst)
     {
       /* It's an include file, no symbols to read for it.
          Everything is in the parent symtab.  */
-      pst->readin = 1;
+      associate_psymtab_with_symtab (objfile, pst, nullptr);
       return;
     }
 
@@ -10108,9 +10112,11 @@  rust_union_quirks (struct dwarf2_cu *cu)
 static struct compunit_symtab *
 get_compunit_symtab (struct dwarf2_per_cu_data *per_cu)
 {
-  return (per_cu->dwarf2_per_objfile->using_index
-	  ? per_cu->v.quick->compunit_symtab
-	  : per_cu->v.psymtab->compunit_symtab);
+  if (per_cu->dwarf2_per_objfile->using_index)
+    return per_cu->v.quick->compunit_symtab;
+
+  struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile;
+  return get_psymtab_compunit (objfile, per_cu->v.psymtab);
 }
 
 /* A helper function for computing the list of all symbol tables
@@ -10344,8 +10350,7 @@  process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
   else
     {
       struct partial_symtab *pst = per_cu->v.psymtab;
-      pst->compunit_symtab = cust;
-      pst->readin = 1;
+      associate_psymtab_with_symtab (objfile, pst, cust);
     }
 
   /* Push it for inclusion processing later.  */
@@ -10425,8 +10430,7 @@  process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
   else
     {
       struct partial_symtab *pst = per_cu->v.psymtab;
-      pst->compunit_symtab = cust;
-      pst->readin = 1;
+      associate_psymtab_with_symtab (objfile, pst, cust);
     }
 }
 
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 29fe3455db..785e9dbfa0 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -3902,16 +3902,16 @@  psymtab_to_symtab_1 (struct objfile *objfile,
   int last_symtab_ended = 0;
   struct section_offsets *section_offsets = objfile->section_offsets;
 
-  if (pst->readin)
+  if (psymtab_read_in_p (objfile, pst))
     return;
-  pst->readin = 1;
+  associate_psymtab_with_symtab (objfile, pst, nullptr, false);
 
   /* Read in all partial symbtabs on which this one is dependent.
      NOTE that we do have circular dependencies, sigh.  We solved
      that by setting pst->readin before this point.  */
 
   for (i = 0; i < pst->number_of_dependencies; i++)
-    if (!pst->dependencies[i]->readin)
+    if (!psymtab_read_in_p (objfile, pst->dependencies[i]))
       {
 	/* Inform about additional files to be read in.  */
 	if (info_verbose)
@@ -4291,7 +4291,7 @@  psymtab_to_symtab_1 (struct objfile *objfile,
     }
 
   /* Now link the psymtab and the symtab.  */
-  pst->compunit_symtab = cust;
+  associate_psymtab_with_symtab (objfile, pst, cust);
 
   mdebugread_objfile = NULL;
 }
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 28e66eca36..225060d22f 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -28,6 +28,7 @@ 
 #include "registry.h"
 #include "gdb_bfd.h"
 #include <vector>
+#include <unordered_map>
 
 struct bcache;
 struct htab;
@@ -372,6 +373,11 @@  struct objfile
   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.  */
+  std::unordered_map<partial_symtab *, compunit_symtab *> psymtab_map;
+
   /* Structure which keeps track of functions that manipulate objfile's
      of the same type as this objfile.  I.e. the function to read partial
      symbols for example.  Note that this structure is in statically
diff --git a/gdb/psympriv.h b/gdb/psympriv.h
index 7673eaef39..969215e2f1 100644
--- a/gdb/psympriv.h
+++ b/gdb/psympriv.h
@@ -193,12 +193,6 @@  struct partial_symtab
   int statics_offset;
   int n_static_syms;
 
-  /* Non-zero if the symtab corresponding to this psymtab has been
-     readin.  This is located here so that this structure packs better
-     on 64-bit systems.  */
-
-  unsigned char readin;
-
   /* True iff objfile->psymtabs_addrmap is properly populated for this
      partial_symtab.  For discontiguous overlapping psymtabs is the only usable
      info in PSYMTABS_ADDRMAP.  */
@@ -218,11 +212,6 @@  struct partial_symtab
   unsigned int textlow_valid : 1;
   unsigned int texthigh_valid : 1;
 
-  /* Pointer to compunit eventually allocated for this source file, 0 if
-     !readin or if we haven't looked for the symtab after it was readin.  */
-
-  struct compunit_symtab *compunit_symtab;
-
   /* Pointer to function which will read in the symtab corresponding to
      this psymtab.  */
 
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index a966b39730..f2177c76ee 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -142,7 +142,7 @@  partial_map_expand_apply (struct objfile *objfile,
   gdb_assert (pst->user == NULL);
 
   /* Don't visit already-expanded psymtabs.  */
-  if (pst->readin)
+  if (psymtab_read_in_p (objfile, pst))
     return 0;
 
   /* This may expand more than one symtab, and we want to iterate over
@@ -390,7 +390,7 @@  psym_find_pc_sect_compunit_symtab (struct objfile *objfile,
 						    msymbol);
   if (ps != NULL)
     {
-      if (warn_if_readin && ps->readin)
+      if (warn_if_readin && psymtab_read_in_p (objfile, ps))
 	/* Might want to error() here (in case symtab is corrupt and
 	   will cause a core dump), but maybe we can successfully
 	   continue, so let's not.  */
@@ -398,7 +398,7 @@  psym_find_pc_sect_compunit_symtab (struct objfile *objfile,
 (Internal error: pc %s in read in psymtab, but not in symtab.)\n"),
 		 paddress (get_objfile_arch (objfile), pc));
       psymtab_to_symtab (objfile, ps);
-      return ps->compunit_symtab;
+      return get_psymtab_compunit (objfile, ps);
     }
   return NULL;
 }
@@ -488,8 +488,8 @@  psym_lookup_symbol (struct objfile *objfile,
 
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
   {
-    if (!ps->readin && lookup_partial_symbol (objfile, ps, name,
-					      psymtab_index, domain))
+    if (!psymtab_read_in_p (objfile, ps)
+	&& lookup_partial_symbol (objfile, ps, name, psymtab_index, domain))
       {
 	struct symbol *sym, *with_opaque = NULL;
 	struct compunit_symtab *stab = psymtab_to_symtab (objfile, ps);
@@ -753,19 +753,15 @@  psymtab_to_symtab (struct objfile *objfile, struct partial_symtab *pst)
   while (pst->user != NULL)
     pst = pst->user;
 
-  /* If it's been looked up before, return it.  */
-  if (pst->compunit_symtab)
-    return pst->compunit_symtab;
-
   /* If it has not yet been read in, read it.  */
-  if (!pst->readin)
+  if (!psymtab_read_in_p (objfile, pst))
     {
       scoped_restore decrementer = increment_reading_symtab ();
 
       (*pst->read_symtab) (pst, objfile);
     }
 
-  return pst->compunit_symtab;
+  return get_psymtab_compunit (objfile, pst);
 }
 
 /* Psymtab version of find_last_source_symtab.  See its definition in
@@ -789,7 +785,7 @@  psym_find_last_source_symtab (struct objfile *ofp)
 
   if (cs_pst)
     {
-      if (cs_pst->readin)
+      if (psymtab_read_in_p (ofp, cs_pst))
 	{
 	  internal_error (__FILE__, __LINE__,
 			  _("select_source_symtab: "
@@ -943,11 +939,12 @@  dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
   gdb_print_host_address (objfile, outfile);
   fprintf_unfiltered (outfile, ")\n");
 
-  if (psymtab->readin)
+  if (psymtab_read_in_p (objfile, psymtab))
     {
       fprintf_filtered (outfile,
 			"  Full symtab was read (at ");
-      gdb_print_host_address (psymtab->compunit_symtab, outfile);
+      gdb_print_host_address (get_psymtab_compunit (objfile, psymtab),
+			      outfile);
       fprintf_filtered (outfile, " by function at ");
       gdb_print_host_address (psymtab->read_symtab, outfile);
       fprintf_filtered (outfile, ")\n");
@@ -1004,7 +1001,7 @@  psym_print_stats (struct objfile *objfile)
   i = 0;
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
     {
-      if (ps->readin == 0)
+      if (psymtab_read_in_p (objfile, ps) == 0)
 	i++;
     }
   printf_filtered (_("  Number of psym tables (not yet expanded): %d\n"), i);
@@ -1046,7 +1043,7 @@  psym_expand_symtabs_for_function (struct objfile *objfile,
 
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
   {
-    if (ps->readin)
+    if (psymtab_read_in_p (objfile, ps))
       continue;
 
     if ((lookup_partial_symbol (objfile, ps, func_name, 1, VAR_DOMAIN)
@@ -1109,7 +1106,7 @@  psym_map_symbol_filenames (struct objfile *objfile,
     {
       const char *fullname;
 
-      if (ps->readin)
+      if (psymtab_read_in_p (objfile, ps))
 	continue;
 
       /* We can skip shared psymtabs here, because any file name will be
@@ -1224,7 +1221,7 @@  psym_map_matching_symbols (struct objfile *objfile,
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
     {
       QUIT;
-      if (ps->readin
+      if (psymtab_read_in_p (objfile, ps)
 	  || match_partial_symbol (objfile, ps, global, name, domain, match,
 				   ordered_compare))
 	{
@@ -1356,7 +1353,7 @@  psym_expand_symtabs_matching
     {
       QUIT;
 
-      if (ps->readin)
+      if (psymtab_read_in_p (objfile, ps))
 	continue;
 
       /* We skip shared psymtabs because file-matching doesn't apply
@@ -1762,7 +1759,6 @@  allocate_psymtab (const char *filename, struct objfile *objfile)
   psymtab->filename
     = (const char *) bcache (filename, strlen (filename) + 1,
 			     objfile->per_bfd->filename_cache);
-  psymtab->compunit_symtab = NULL;
 
   /* Prepend it to the psymtab list for the objfile it belongs to.
      Psymtabs are searched in most recent inserted -> least recent
@@ -1821,6 +1817,45 @@  discard_psymtab (struct objfile *objfile, struct partial_symtab *pst)
 
 
 
+/* See psympriv.h.  */
+
+void
+associate_psymtab_with_symtab (struct objfile *objfile,
+			       partial_symtab *pst,
+			       compunit_symtab *symtab,
+			       bool always_set)
+{
+  if (!always_set)
+    {
+      auto iter = objfile->psymtab_map.find (pst);
+      if (iter != objfile->psymtab_map.end ())
+	return;
+    }
+  objfile->psymtab_map[pst] = symtab;
+}
+
+/* See psympriv.h.  */
+
+bool
+psymtab_read_in_p (struct objfile *objfile, partial_symtab *pst)
+{
+  auto iter = objfile->psymtab_map.find (pst);
+  return iter != objfile->psymtab_map.end ();
+}
+
+/* See psympriv.h.  */
+
+compunit_symtab *
+get_psymtab_compunit (struct objfile *objfile, partial_symtab *pst)
+{
+  auto iter = objfile->psymtab_map.find (pst);
+  if (iter == objfile->psymtab_map.end ())
+    return nullptr;
+  return iter->second;
+}
+
+
+
 /* We need to pass a couple of items to the addrmap_foreach function,
    so use a struct.  */
 
@@ -2094,7 +2129,8 @@  maintenance_info_psymtabs (const char *regexp, int from_tty)
 			       host_address_to_string (psymtab));
 
 	      printf_filtered ("    readin %s\n",
-			       psymtab->readin ? "yes" : "no");
+			       psymtab_read_in_p (objfile, psymtab)
+			       ? "yes" : "no");
 	      printf_filtered ("    fullname %s\n",
 			       psymtab->fullname
 			       ? psymtab->fullname : "(null)");
@@ -2181,7 +2217,7 @@  maintenance_check_psymtabs (const char *ignore, int from_tty)
     /* We don't call psymtab_to_symtab here because that may cause symtab
        expansion.  When debugging a problem it helps if checkers leave
        things unchanged.  */
-    cust = ps->compunit_symtab;
+    cust = get_psymtab_compunit (objfile, ps);
 
     /* First do some checks that don't require the associated symtab.  */
     if (PSYMTAB_TEXTHIGH (objfile, ps) < PSYMTAB_TEXTLOW (objfile, ps))
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
index 6d9f257f31..7c5bf80e70 100644
--- a/gdb/psymtab.h
+++ b/gdb/psymtab.h
@@ -24,6 +24,8 @@ 
 
 /* A bcache for partial symbols.  */
 
+struct compunit_symtab;
+struct partial_symtab;
 struct psymbol_bcache;
 
 extern struct psymbol_bcache *psymbol_bcache_init (void);
@@ -43,4 +45,29 @@  extern const struct quick_symbol_functions dwarf2_debug_names_functions;
 extern struct objfile *require_partial_symbols (struct objfile *objfile,
 						int verbose);
 
+/* Record that, for the given objfile, PST has expanded to SYMTAB.
+   SYMTAB may be nullptr, indicating that an attempt to expand PST was
+   made, but yielded no results (perhaps this was an included
+   psymtab).  By default, this association is always made, but if
+   ALWAYS_SET is false, then an association is only made if one has
+   not been made previously.  */
+
+extern void associate_psymtab_with_symtab (struct objfile *objfile,
+					   partial_symtab *pst,
+					   compunit_symtab *symtab,
+					   bool always_set = true);
+
+/* Return true if PST was ever read in for the given objfile, false
+   otherwise.  This only records whether an attempt was made -- not
+   whether it yielded a full symtab.  */
+
+extern bool psymtab_read_in_p (struct objfile *objfile, partial_symtab *pst);
+
+/* Return the full symtab corresponding to PST.  Returns NULL if the
+   partial symtab was never read, or if the attempt to read it yielded
+   no results.  */
+
+extern compunit_symtab *get_psymtab_compunit (struct objfile *objfile,
+					      partial_symtab *pst);
+
 #endif /* PSYMTAB_H */
diff --git a/gdb/symfile.c b/gdb/symfile.c
index b0a5f11834..8a63fe34d3 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2399,6 +2399,7 @@  reread_symbols (void)
 	     enough?  */
 	  objfile->global_psymbols.clear ();
 	  objfile->static_psymbols.clear ();
+	  objfile->psymtab_map.clear ();
 
 	  /* Free the obstacks for non-reusable objfiles.  */
 	  psymbol_bcache_free (objfile->psymbol_cache);
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 7ec367a7ac..218cfaef5e 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -1134,8 +1134,9 @@  read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
 	{
 	  if (get_last_source_file ())
 	    {
-	      pst->compunit_symtab = end_symtab (cur_src_end_addr,
-						 SECT_OFF_TEXT (objfile));
+	      associate_psymtab_with_symtab
+		(objfile, pst, end_symtab (cur_src_end_addr,
+					   SECT_OFF_TEXT (objfile)));
 	      end_stabs ();
 	    }
 
@@ -1530,8 +1531,7 @@  read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
          to make sure that we set pst->compunit_symtab to the symtab for the
          file, not to the _globals_ symtab.  I'm not sure whether this
          actually works right or when/if it comes up.  */
-      if (pst->compunit_symtab == NULL)
-	pst->compunit_symtab = cust;
+      associate_psymtab_with_symtab (objfile, pst, cust, false);
       end_stabs ();
     }
 }
@@ -1843,7 +1843,7 @@  xcoff_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
   if (!pst)
     return;
 
-  if (pst->readin)
+  if (psymtab_read_in_p (objfile, pst))
     {
       fprintf_unfiltered
 	(gdb_stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",
@@ -1853,7 +1853,7 @@  xcoff_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
 
   /* 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)
+    if (!psymtab_read_in_p (objfile, pst->dependencies[i]))
       {
 	/* Inform about additional files that need to be read in.  */
 	if (info_verbose)
@@ -1879,7 +1879,7 @@  xcoff_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
       read_xcoff_symtab (objfile, pst);
     }
 
-  pst->readin = 1;
+  associate_psymtab_with_symtab (objfile, pst, nullptr, false);
 }
 
 /* Read in all of the symbols for a given psymtab for real.
@@ -1888,7 +1888,7 @@  xcoff_psymtab_to_symtab_1 (struct objfile *objfile, struct partial_symtab *pst)
 static void
 xcoff_read_symtab (struct partial_symtab *self, struct objfile *objfile)
 {
-  if (self->readin)
+  if (psymtab_read_in_p (objfile, self))
     {
       fprintf_unfiltered
 	(gdb_stderr, "Psymtab for %s already read in.  Shouldn't happen.\n",