This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[5/7] RFC: psymtab changes


This patch is big but mostly mechanical.

Currently, psymtabs are created on the objfile obstack.  We can't safely
do that in the background, because other things use this obstack.  So,
this patch changes the psymtab code so that the caller can provide an
obstack to use.

To make this change simpler, I consolidated a lot of the psymtab state
into a new structure and made some of its details a bit more opaque to
users.

This patch also includes other little psymtab-related changes.  I added
OBJF_MAIN and OBJF_SYMTABS_READ.  There is a new sym_read_psymbols
method and the psymtab code now understands that psymtabs might be read
lazily.  These are all used in a later patch.

I think most of this patch is actually a cleanup, and should probably go
in even if the rest of the changes are rejected.  The lazy psymtab
change also is a nice bit of infrastructure; e.g., I wrote some
.debug_aranges-read code based on this as well.

Tom

>From 26cb17f4cdc44234c056f53315cfce7b6c29f06a Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Fri, 11 Jun 2010 15:20:37 -0600
Subject: [PATCH 5/7] psymtab changes

2010-06-14  Tom Tromey  <tromey@redhat.com>

	* xcoffread.c (xcoff_start_psymtab): Remove global_syms,
	static_syms arguments.
	(xcoff_end_psymtab): Update.
	(scan_xcoff_symtab): Update.
	(xcoff_initial_scan): Update.
	(xcoff_sym_fns: Update.
	* symtab.h (SYMBOL_SET_NAMES_FULL): Add 'obstack' argument.
	* symtab.c (symbol_set_names): Add 'obstack' argument.
	(find_main_filename): Search OBJF_MAIN objfiles first.
	* symmisc.c (print_symbol_bcache_statistics): Update.
	(print_objfile_statistics): Likewise.
	* symfile.h (struct psymbol_allocation_list): Remove.
	(struct quick_symbol_functions) <has_symbols>: Add try_read
	argument.
	(struct sym_fns) <sym_read_psymbols>: New field.
	(extend_psymbol_list, add_psymbol_to_list, init_psymbol_list):
	Remove.
	(start_psymtab_common, allocate_psymtab, discard_psymtab):
	Remove.
	* symfile.c (has_any_debug_symbols): New function.
	(symbol_file_add_with_addrs_or_offsets): Set OBJF_MAIN.  Use
	has_any_debug_symbols.
	(reread_symbols): Use destroy_psymtab_state and
	allocate_psymtab_state.  Handle OBJF_SYMTABS_READ.
	* somread.c (som_sym_fns): Update.
	* solib.c (info_sharedlibrary_command): Use
	objfile_has_full_symbols and objfile_has_partial_symbols.
	* psymtab.h (allocate_psymtab_state): Declare.
	(destroy_psymtab_state): Declare.
	* psymtab.c (lookup_partial_symtab): Call
	require_partial_symbols.
	(find_pc_sect_psymtab): Likewise.
	(lookup_symbol_aux_psymtabs): Likewise.
	(lookup_partial_symbol): Update.
	(relocate_psymtabs): Update.
	(find_last_source_symtab_from_partial): Call
	require_partial_symbols.
	(dump_psymtab): Update.
	(dump_psymtabs_for_objfile): Update.
	(read_symtabs_for_function): Call require_partial_symbols.
	(expand_partial_symbol_tables): Likewise.
	(read_psymtabs_with_filename): Likewise.
	(map_symbol_names_psymtab): Update.
	(find_symbol_file_from_partial): Call require_partial_symbols.
	(ada_lookup_partial_symbol): Update.
	(expand_symtabs_matching_via_partial): Call
	require_partial_symbols.
	(objfile_has_psyms): New function.
	(require_partial_symbols): New function.
	(check_writeable): New function.
	(sort_pst_symbols): Add 'state' argument.
	(start_psymtab_common_full): New function.
	(start_psymtab_common): Use it.
	(add_psymbol_to_bcache): Add 'state' argument.
	(extend_psymbol_list): Move earlier.
	(append_psymbol_to_list): Use it.
	(add_psymbol_to_list_full): New function.
	(add_psymbol_to_list): Use it.
	(init_psymbol_list): Remove.
	(allocate_psymtab_full): New function.
	(allocate_psymtab): Use it.
	(discard_psymtab): Add 'state' argument.
	(finalize_psymtab): New function.
	(destroy_psymtab_state): New function.
	(allocate_psymtab_state): Likewise.
	(switch_psymtab_state_obstack): Likewise.
	(readonly_psymtab_state): New global.
	(maintenance_info_psymtabs): Update.
	(maintenance_check_symtabs): Update.
	* psympriv.h (ALL_OBJFILE_PSYMTABS): Update.
	(ALL_PSYMTABS_REQUIRED): New macro.
	(struct psymbol_allocation_list): New.
	(struct psymtab_state): New.
	(sort_pst_symbols, allocate_psymtab_full, allocate_psymtab)
	(add_psymbol_to_list_full, add_psymbol_to_list)
	(start_psymtab_common_full, start_psymtab_common)
	(finalize_psymtab, switch_psymtab_state_obstack)
	(readonly_psymtab_state): Declare.
	* objfiles.h (struct objfile): <psymtabs, psymtabs_addrmap,
	free_psymtabs, psymbol_cache, global_psymbols, static_psymbols>:
	Remove.
	<psyms>: New field.
	(OBJF_SYMTABS_READ, OBJF_MAIN): New defines.
	* objfiles.c (allocate_objfile): Use allocate_psymtab_state.
	(free_objfile): Use destroy_psymtab_state.
	(objfile_relocate1): Update.
	(objfile_has_partial_symbols): Update.
	(have_partial_symbols): Update.
	* mipsread.c (ecoff_sym_fns): Update.
	* mdebugread.c (parse_partial_symbols): Update.
	(handle_psymbol_enumerators): Update.
	* machoread.c (macho_sym_fns): Update.
	* elfread.c (elf_sym_fns): Update.
	* dwarf2read.c (dwarf2_build_psymtabs): Don't call
	init_psymbol_list.
	(dwarf2_create_include_psymtab): Use allocate_psymtab_full.
	(process_psymtab_comp_unit): Use start_psymtab_common_full,
	finalize_psymtab, sort_pst_symbols.
	(dwarf2_build_psymtabs_hard): Update.
	(add_partial_symbol): Update.
	(add_partial_subprogram): Update.
	(dwarf2_ranges_read): Update.
	(load_partial_dies): Update.
	* dbxread.c (dbx_symfile_read): Don't call init_psymbol_list.
	(read_dbx_symtab): Update.
	(start_psymtab): Remove global_syms and static_syms arguments.
	(end_psymtab): Call finalize_psymtab, sort_pst_symbols,
	discard_psymtab.
	(aout_sym_fns): Update.
	* coffread.c (coff_sym_fns): Update.
---
 gdb/coffread.c   |    1 +
 gdb/dbxread.c    |   47 +++-----
 gdb/dwarf2read.c |  166 ++++++++++++-------------
 gdb/elfread.c    |    1 +
 gdb/machoread.c  |    1 +
 gdb/mdebugread.c |   44 +++----
 gdb/mipsread.c   |    1 +
 gdb/objfiles.c   |   32 ++++--
 gdb/objfiles.h   |   34 ++----
 gdb/psympriv.h   |  152 ++++++++++++++++++++++-
 gdb/psymtab.c    |  369 +++++++++++++++++++++++++++++++++---------------------
 gdb/psymtab.h    |   13 ++-
 gdb/solib.c      |    3 +-
 gdb/somread.c    |    1 +
 gdb/symfile.c    |   49 +++++---
 gdb/symfile.h    |   72 ++---------
 gdb/symmisc.c    |   10 +-
 gdb/symtab.c     |   20 ++-
 gdb/symtab.h     |    8 +-
 gdb/xcoffread.c  |   55 +++------
 20 files changed, 631 insertions(+), 448 deletions(-)

diff --git a/gdb/coffread.c b/gdb/coffread.c
index 52417b2..38ce8eb 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -2132,6 +2132,7 @@ static struct sym_fns coff_sym_fns =
   coff_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   coff_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   coff_symfile_read,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   coff_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets:  xlate external to internal form */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 25bf07b..c147ff3 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -290,9 +290,7 @@ static void add_old_header_file (char *, int);
 static void add_this_object_header_file (int);
 
 static struct partial_symtab *start_psymtab (struct objfile *, char *,
-					     CORE_ADDR, int,
-					     struct partial_symbol **,
-					     struct partial_symbol **);
+					     CORE_ADDR, int);
 
 /* Free up old header file tables */
 
@@ -555,10 +553,6 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags)
   if (val < 0)
     perror_with_name (objfile->name);
 
-  /* Size the symbol table.  */
-  if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)
-    init_psymbol_list (objfile, DBX_SYMCOUNT (objfile));
-
   symbol_size = DBX_SYMBOL_SIZE (objfile);
   symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
 
@@ -1545,9 +1539,7 @@ read_dbx_symtab (struct objfile *objfile)
 	      {
 		pst = start_psymtab (objfile,
 				     namestring, valu,
-				     first_so_symnum * symbol_size,
-				     objfile->global_psymbols.next,
-				     objfile->static_psymbols.next);
+				     first_so_symnum * symbol_size);
 		pst->dirname = dirname_nso;
 		dirname_nso = NULL;
 	      }
@@ -1731,7 +1723,7 @@ pos %d"),
 
 	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_STATIC,
-				   &objfile->static_psymbols,
+				   0,
 				   0, nlist.n_value,
 				   psymtab_language, objfile);
 	      continue;
@@ -1743,7 +1735,7 @@ pos %d"),
 		 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,
+				   1,
 				   0, nlist.n_value,
 				   psymtab_language, objfile);
 	      continue;
@@ -1761,7 +1753,7 @@ pos %d"),
 		{
 		  add_psymbol_to_list (sym_name, sym_len, 1,
 				       STRUCT_DOMAIN, LOC_TYPEDEF,
-				       &objfile->static_psymbols,
+				       0,
 				       nlist.n_value, 0,
 				       psymtab_language, objfile);
 		  if (p[2] == 't')
@@ -1769,7 +1761,7 @@ pos %d"),
 		      /* Also a typedef with the same name.  */
 		      add_psymbol_to_list (sym_name, sym_len, 1,
 					   VAR_DOMAIN, LOC_TYPEDEF,
-					   &objfile->static_psymbols,
+					   0,
 					   nlist.n_value, 0,
 					   psymtab_language, objfile);
 		      p += 1;
@@ -1782,7 +1774,7 @@ pos %d"),
 		{
 		  add_psymbol_to_list (sym_name, sym_len, 1,
 				       VAR_DOMAIN, LOC_TYPEDEF,
-				       &objfile->static_psymbols,
+				       0,
 				       nlist.n_value, 0,
 				       psymtab_language, objfile);
 		}
@@ -1844,7 +1836,7 @@ pos %d"),
 			 enum constants in psymtabs, just in symtabs.  */
 		      add_psymbol_to_list (p, q - p, 1,
 					   VAR_DOMAIN, LOC_CONST,
-					   &objfile->static_psymbols, 0,
+					   0, 0,
 					   0, psymtab_language, objfile);
 		      /* Point past the name.  */
 		      p = q;
@@ -1862,7 +1854,7 @@ pos %d"),
 	      /* Constant, e.g. from "const" in Pascal.  */
 	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_CONST,
-				   &objfile->static_psymbols, nlist.n_value,
+				   0, nlist.n_value,
 				   0, psymtab_language, objfile);
 	      continue;
 
@@ -1928,7 +1920,7 @@ pos %d"),
 		}
 	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_BLOCK,
-				   &objfile->static_psymbols,
+				   0,
 				   0, nlist.n_value,
 				   psymtab_language, objfile);
 	      continue;
@@ -1998,7 +1990,7 @@ pos %d"),
 		}
 	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_BLOCK,
-				   &objfile->global_psymbols,
+				   1,
 				   0, nlist.n_value,
 				   psymtab_language, objfile);
 	      continue;
@@ -2193,12 +2185,11 @@ pos %d"),
 
 static struct partial_symtab *
 start_psymtab (struct objfile *objfile, char *filename, CORE_ADDR textlow,
-	       int ldsymoff, struct partial_symbol **global_syms,
-	       struct partial_symbol **static_syms)
+	       int ldsymoff)
 {
   struct partial_symtab *result =
     start_psymtab_common (objfile, objfile->section_offsets,
-			  filename, textlow, global_syms, static_syms);
+			  filename, textlow);
 
   result->read_symtab_private = obstack_alloc (&objfile->objfile_obstack,
 					       sizeof (struct symloc));
@@ -2318,12 +2309,7 @@ end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes,
 
   /* End of kludge for patching Solaris textlow and texthigh.  */
 
-  pst->n_global_syms =
-    objfile->global_psymbols.next - (objfile->global_psymbols.list
-				     + pst->globals_offset);
-  pst->n_static_syms =
-    objfile->static_psymbols.next - (objfile->static_psymbols.list
-				     + pst->statics_offset);
+  finalize_psymtab (objfile->psyms, pst);
 
   pst->number_of_dependencies = number_dependencies;
   if (number_dependencies)
@@ -2369,7 +2355,7 @@ end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes,
       subpst->read_symtab = pst->read_symtab;
     }
 
-  sort_pst_symbols (pst);
+  sort_pst_symbols (objfile->psyms, pst);
 
   if (num_includes == 0
       && number_dependencies == 0
@@ -2385,7 +2371,7 @@ end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes,
          is not empty, but we don't realize that.  Fixing that without slowing
          things down might be tricky.  */
 
-      discard_psymtab (pst);
+      discard_psymtab (pst->objfile->psyms, pst);
 
       /* Indicate that psymtab was thrown away.  */
       pst = (struct partial_symtab *) NULL;
@@ -3579,6 +3565,7 @@ static struct sym_fns aout_sym_fns =
   dbx_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   dbx_symfile_init,	/* sym_init: read initial info, setup for sym_read() */
   dbx_symfile_read,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   dbx_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets, /* sym_offsets: parse user's offsets to
 			      internal form */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 05fbd09..a8715a2 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -1429,11 +1429,6 @@ dwarf2_get_section_info (struct objfile *objfile, const char *section_name,
 void
 dwarf2_build_psymtabs (struct objfile *objfile)
 {
-  if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)
-    {
-      init_psymbol_list (objfile, 1024);
-    }
-
   dwarf2_build_psymtabs_hard (objfile);
 }
 
@@ -1544,7 +1539,9 @@ static void
 dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst,
                                struct objfile *objfile)
 {
-  struct partial_symtab *subpst = allocate_psymtab (name, objfile);
+  struct partial_symtab *subpst;
+
+  subpst = allocate_psymtab_full (objfile->psyms, name, objfile);
 
   subpst->section_offsets = pst->section_offsets;
   subpst->textlow = 0;
@@ -1869,16 +1866,11 @@ process_psymtab_comp_unit (struct objfile *objfile,
 
   /* Allocate a new partial symbol table structure.  */
   attr = dwarf2_attr (comp_unit_die, DW_AT_name, &cu);
-  pst = start_psymtab_common (objfile, objfile->section_offsets,
-			      (attr != NULL) ? DW_STRING (attr) : "",
-			      /* TEXTLOW and TEXTHIGH are set below.  */
-			      0,
-			      objfile->global_psymbols.next,
-			      objfile->static_psymbols.next);
-
-  attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu);
-  if (attr != NULL)
-    pst->dirname = DW_STRING (attr);
+  pst = start_psymtab_common_full (objfile->psyms,
+				   objfile, objfile->section_offsets,
+				   (attr != NULL) ? DW_STRING (attr) : "",
+				   /* TEXTLOW and TEXTHIGH are set below.  */
+				   0);
 
   pst->read_symtab_private = this_cu;
 
@@ -1898,7 +1890,7 @@ process_psymtab_comp_unit (struct objfile *objfile,
   if (has_pc_info == 1 && best_lowpc < best_highpc)
     /* Store the contiguous range if it is not empty; it can be empty for
        CUs with no code.  */
-    addrmap_set_empty (objfile->psymtabs_addrmap,
+    addrmap_set_empty (objfile->psyms->psymtabs_addrmap,
 		       best_lowpc + baseaddr,
 		       best_highpc + baseaddr - 1, pst);
 
@@ -1934,11 +1926,8 @@ process_psymtab_comp_unit (struct objfile *objfile,
   pst->textlow = best_lowpc + baseaddr;
   pst->texthigh = best_highpc + baseaddr;
 
-  pst->n_global_syms = objfile->global_psymbols.next -
-    (objfile->global_psymbols.list + pst->globals_offset);
-  pst->n_static_syms = objfile->static_psymbols.next -
-    (objfile->static_psymbols.list + pst->statics_offset);
-  sort_pst_symbols (pst);
+  finalize_psymtab (objfile->psyms, pst);
+  sort_pst_symbols (objfile->psyms, pst);
 
   info_ptr = (beg_of_comp_unit + cu.header.length
 	      + cu.header.initial_length_size);
@@ -2015,7 +2004,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
 
   create_all_comp_units (objfile);
 
-  objfile->psymtabs_addrmap =
+  objfile->psyms->psymtabs_addrmap =
     addrmap_create_mutable (&objfile->objfile_obstack);
 
   /* Since the objects we're extracting from .debug_info vary in
@@ -2046,8 +2035,9 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
 					    dwarf2_per_objfile->info.size);
     }
 
-  objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
-						    &objfile->objfile_obstack);
+  objfile->psyms->psymtabs_addrmap
+    = addrmap_create_fixed (objfile->psyms->psymtabs_addrmap,
+			    &objfile->objfile_obstack);
 
   do_cleanups (back_to);
 }
@@ -2395,23 +2385,23 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
              in the global scope.  */
 	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_text, objfile); */
-	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
-				      built_actual_name,
-				      VAR_DOMAIN, LOC_BLOCK,
-				      &objfile->global_psymbols,
-				      0, pdi->lowpc + baseaddr,
-				      cu->language, objfile);
+	  psym = add_psymbol_to_list_full (objfile->psyms,
+					   actual_name, strlen (actual_name),
+					   built_actual_name,
+					   VAR_DOMAIN, LOC_BLOCK,
+					   0, pdi->lowpc + baseaddr,
+					   cu->language, objfile, 1);
 	}
       else
 	{
 	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_file_text, objfile); */
-	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
-				      built_actual_name,
-				      VAR_DOMAIN, LOC_BLOCK,
-				      &objfile->static_psymbols,
-				      0, pdi->lowpc + baseaddr,
-				      cu->language, objfile);
+	  psym = add_psymbol_to_list_full (objfile->psyms,
+					   actual_name, strlen (actual_name),
+					   built_actual_name,
+					   VAR_DOMAIN, LOC_BLOCK,
+					   0, pdi->lowpc + baseaddr,
+					   cu->language, objfile, 0);
 	}
       break;
     case DW_TAG_variable:
@@ -2433,12 +2423,12 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	  if (pdi->locdesc)
 	    addr = decode_locdesc (pdi->locdesc, cu);
 	  if (pdi->locdesc || pdi->has_type)
-	    psym = add_psymbol_to_list (actual_name, strlen (actual_name),
-					built_actual_name,
-					VAR_DOMAIN, LOC_STATIC,
-					&objfile->global_psymbols,
-					0, addr + baseaddr,
-					cu->language, objfile);
+	    psym = add_psymbol_to_list_full (objfile->psyms,
+					     actual_name, strlen (actual_name),
+					     built_actual_name,
+					     VAR_DOMAIN, LOC_STATIC,
+					     0, addr + baseaddr,
+					     cu->language, objfile, 1);
 	}
       else
 	{
@@ -2452,29 +2442,29 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	  addr = decode_locdesc (pdi->locdesc, cu);
 	  /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
 	     mst_file_data, objfile); */
-	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
-				      built_actual_name,
-				      VAR_DOMAIN, LOC_STATIC,
-				      &objfile->static_psymbols,
-				      0, addr + baseaddr,
-				      cu->language, objfile);
+	  psym = add_psymbol_to_list_full (objfile->psyms,
+					   actual_name, strlen (actual_name),
+					   built_actual_name,
+					   VAR_DOMAIN, LOC_STATIC,
+					   0, addr + baseaddr,
+					   cu->language, objfile, 0);
 	}
       break;
     case DW_TAG_typedef:
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
-      add_psymbol_to_list (actual_name, strlen (actual_name),
-			   built_actual_name,
-			   VAR_DOMAIN, LOC_TYPEDEF,
-			   &objfile->static_psymbols,
-			   0, (CORE_ADDR) 0, cu->language, objfile);
+      add_psymbol_to_list_full (objfile->psyms,
+				actual_name, strlen (actual_name),
+				built_actual_name,
+				VAR_DOMAIN, LOC_TYPEDEF,
+				0, (CORE_ADDR) 0, cu->language, objfile, 0);
       break;
     case DW_TAG_namespace:
-      add_psymbol_to_list (actual_name, strlen (actual_name),
-			   built_actual_name,
-			   VAR_DOMAIN, LOC_TYPEDEF,
-			   &objfile->global_psymbols,
-			   0, (CORE_ADDR) 0, cu->language, objfile);
+      add_psymbol_to_list_full (objfile->psyms,
+				actual_name, strlen (actual_name),
+				built_actual_name,
+				VAR_DOMAIN, LOC_TYPEDEF,
+				0, (CORE_ADDR) 0, cu->language, objfile, 1);
       break;
     case DW_TAG_class_type:
     case DW_TAG_interface_type:
@@ -2495,25 +2485,23 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 
       /* NOTE: carlton/2003-10-07: See comment in new_symbol about
 	 static vs. global.  */
-      add_psymbol_to_list (actual_name, strlen (actual_name),
-			   built_actual_name,
-			   STRUCT_DOMAIN, LOC_TYPEDEF,
-			   (cu->language == language_cplus
-			    || cu->language == language_java)
-			   ? &objfile->global_psymbols
-			   : &objfile->static_psymbols,
-			   0, (CORE_ADDR) 0, cu->language, objfile);
+      add_psymbol_to_list_full (objfile->psyms,
+				actual_name, strlen (actual_name),
+				built_actual_name,
+				STRUCT_DOMAIN, LOC_TYPEDEF,
+				0, (CORE_ADDR) 0, cu->language, objfile,
+				(cu->language == language_cplus
+				 || cu->language == language_java));
 
       break;
     case DW_TAG_enumerator:
-      add_psymbol_to_list (actual_name, strlen (actual_name),
-			   built_actual_name,
-			   VAR_DOMAIN, LOC_CONST,
-			   (cu->language == language_cplus
-			    || cu->language == language_java)
-			   ? &objfile->global_psymbols
-			   : &objfile->static_psymbols,
-			   0, (CORE_ADDR) 0, cu->language, objfile);
+      add_psymbol_to_list_full (objfile->psyms,
+				actual_name, strlen (actual_name),
+				built_actual_name,
+				VAR_DOMAIN, LOC_CONST,
+				0, (CORE_ADDR) 0, cu->language, objfile,
+				(cu->language == language_cplus
+				 || cu->language == language_java));
       break;
     default:
       break;
@@ -2584,7 +2572,7 @@ add_partial_subprogram (struct partial_die_info *pdi,
 
 	      baseaddr = ANOFFSET (objfile->section_offsets,
 				   SECT_OFF_TEXT (objfile));
-	      addrmap_set_empty (objfile->psymtabs_addrmap,
+	      addrmap_set_empty (objfile->psyms->psymtabs_addrmap,
 				 pdi->lowpc + baseaddr,
 				 pdi->highpc - 1 + baseaddr,
 				 cu->per_cu->psymtab);
@@ -4164,7 +4152,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
       range_end += base;
 
       if (ranges_pst != NULL && range_beginning < range_end)
-	addrmap_set_empty (objfile->psymtabs_addrmap,
+	addrmap_set_empty (objfile->psyms->psymtabs_addrmap,
 			   range_beginning + baseaddr, range_end - 1 + baseaddr,
 			   ranges_pst);
 
@@ -6825,10 +6813,11 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
 	      || part_die->tag == DW_TAG_subrange_type))
 	{
 	  if (building_psymtab && part_die->name != NULL)
-	    add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
-				 VAR_DOMAIN, LOC_TYPEDEF,
-				 &cu->objfile->static_psymbols,
-				 0, (CORE_ADDR) 0, cu->language, cu->objfile);
+	    add_psymbol_to_list_full (cu->objfile->psyms,
+				      part_die->name, strlen (part_die->name),
+				      0, VAR_DOMAIN, LOC_TYPEDEF,
+				      0, (CORE_ADDR) 0, cu->language,
+				      cu->objfile, 1);
 	  info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
 	  continue;
 	}
@@ -6846,13 +6835,14 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
 	  if (part_die->name == NULL)
 	    complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
 	  else if (building_psymtab)
-	    add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
-				 VAR_DOMAIN, LOC_CONST,
-				 (cu->language == language_cplus
-				  || cu->language == language_java)
-				 ? &cu->objfile->global_psymbols
-				 : &cu->objfile->static_psymbols,
-				 0, (CORE_ADDR) 0, cu->language, cu->objfile);
+	    add_psymbol_to_list_full (cu->objfile->psyms,
+				      part_die->name, strlen (part_die->name),
+				      0,
+				      VAR_DOMAIN, LOC_CONST,
+				      0, (CORE_ADDR) 0, cu->language,
+				      cu->objfile,
+				      (cu->language == language_cplus
+				       || cu->language == language_java));
 
 	  info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
 	  continue;
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 8c00938..8c64ead 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1039,6 +1039,7 @@ static struct sym_fns elf_sym_fns =
   elf_new_init,			/* sym_new_init: init anything gbl to entire symtab */
   elf_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   elf_symfile_read,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   elf_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets:  Translate ext. to int. relocation */
   elf_symfile_segments,		/* sym_segments: Get segment information from
diff --git a/gdb/machoread.c b/gdb/machoread.c
index bb3268c..efe5ddd 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -843,6 +843,7 @@ static struct sym_fns macho_sym_fns = {
   macho_new_init,               /* sym_new_init: init anything gbl to entire symtab */
   macho_symfile_init,           /* sym_init: read initial info, setup for sym_read() */
   macho_symfile_read,           /* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   macho_symfile_finish,         /* sym_finish: finished with file, cleanup */
   macho_symfile_offsets,        /* sym_offsets:  xlate external to internal form */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 2e18fa4..24a27f9 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -2661,9 +2661,7 @@ parse_partial_symbols (struct objfile *objfile)
 	textlow = 0;
       pst = start_psymtab_common (objfile, objfile->section_offsets,
 				  fdr_name (fh),
-				  textlow,
-				  objfile->global_psymbols.next,
-				  objfile->static_psymbols.next);
+				  textlow);
       pst->read_symtab_private = obstack_alloc (&objfile->objfile_obstack,
 						sizeof (struct symloc));
       memset (pst->read_symtab_private, 0, sizeof (struct symloc));
@@ -3104,7 +3102,7 @@ parse_partial_symbols (struct objfile *objfile)
 
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_STATIC,
-					     &objfile->static_psymbols,
+					     0,
 					     0, sh.value,
 					     psymtab_language, objfile);
 			continue;
@@ -3114,7 +3112,7 @@ parse_partial_symbols (struct objfile *objfile)
 			   wrong.  See the code that reads 'G's for symtabs. */
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_STATIC,
-					     &objfile->global_psymbols,
+					     1,
 					     0, sh.value,
 					     psymtab_language, objfile);
 			continue;
@@ -3132,7 +3130,7 @@ parse_partial_symbols (struct objfile *objfile)
 			  {
 			    add_psymbol_to_list (namestring, p - namestring, 1,
 						 STRUCT_DOMAIN, LOC_TYPEDEF,
-						 &objfile->static_psymbols,
+						 0,
 						 sh.value, 0,
 						 psymtab_language, objfile);
 			    if (p[2] == 't')
@@ -3141,7 +3139,7 @@ parse_partial_symbols (struct objfile *objfile)
 				add_psymbol_to_list (namestring, p - namestring,
 						     1,
 						     VAR_DOMAIN, LOC_TYPEDEF,
-						     &objfile->static_psymbols,
+						     0,
 						     sh.value, 0,
 						     psymtab_language, objfile);
 				p += 1;
@@ -3153,7 +3151,7 @@ parse_partial_symbols (struct objfile *objfile)
 			  {
 			    add_psymbol_to_list (namestring, p - namestring, 1,
 						 VAR_DOMAIN, LOC_TYPEDEF,
-						 &objfile->static_psymbols,
+						 0,
 						 sh.value, 0,
 						 psymtab_language, objfile);
 			  }
@@ -3215,7 +3213,7 @@ parse_partial_symbols (struct objfile *objfile)
 				   enum constants in psymtabs, just in symtabs.  */
 				add_psymbol_to_list (p, q - p, 1,
 						     VAR_DOMAIN, LOC_CONST,
-						     &objfile->static_psymbols, 0,
+						     0, 0,
 						     0, psymtab_language, objfile);
 				/* Point past the name.  */
 				p = q;
@@ -3232,7 +3230,7 @@ parse_partial_symbols (struct objfile *objfile)
 			/* Constant, e.g. from "const" in Pascal.  */
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_CONST,
-					     &objfile->static_psymbols, sh.value,
+					     0, sh.value,
 					     0, psymtab_language, objfile);
 			continue;
 
@@ -3250,7 +3248,7 @@ parse_partial_symbols (struct objfile *objfile)
 			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_BLOCK,
-					     &objfile->static_psymbols,
+					     0,
 					     0, sh.value,
 					     psymtab_language, objfile);
 			continue;
@@ -3272,7 +3270,7 @@ parse_partial_symbols (struct objfile *objfile)
 			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_BLOCK,
-					     &objfile->global_psymbols,
+					     1,
 					     0, sh.value,
 					     psymtab_language, objfile);
 			continue;
@@ -3501,12 +3499,12 @@ parse_partial_symbols (struct objfile *objfile)
 		  if (sh.st == stProc)
 		    add_psymbol_to_list (name, strlen (name), 1,
 					 VAR_DOMAIN, LOC_BLOCK,
-					 &objfile->global_psymbols,
+					 1,
 				    0, sh.value, psymtab_language, objfile);
 		  else
 		    add_psymbol_to_list (name, strlen (name), 1,
 					 VAR_DOMAIN, LOC_BLOCK,
-					 &objfile->static_psymbols,
+					 0,
 				    0, sh.value, psymtab_language, objfile);
 
 		  procaddr = sh.value;
@@ -3575,7 +3573,7 @@ parse_partial_symbols (struct objfile *objfile)
 		    {
 		      add_psymbol_to_list (name, strlen (name), 1,
 					   STRUCT_DOMAIN, LOC_TYPEDEF,
-					   &objfile->static_psymbols,
+					   0,
 					   0, (CORE_ADDR) 0,
 					   psymtab_language, objfile);
 		    }
@@ -3616,7 +3614,7 @@ parse_partial_symbols (struct objfile *objfile)
 	      /* Use this gdb symbol */
 	      add_psymbol_to_list (name, strlen (name), 1,
 				   VAR_DOMAIN, class,
-				   &objfile->static_psymbols,
+				   0,
 				   0, sh.value, psymtab_language, objfile);
 	    skip:
 	      cur_sdx++;	/* Go to next file symbol */
@@ -3692,7 +3690,7 @@ parse_partial_symbols (struct objfile *objfile)
 	      name = debug_info->ssext + psh->iss;
 	      add_psymbol_to_list (name, strlen (name), 1,
 				   VAR_DOMAIN, class,
-				   &objfile->global_psymbols,
+				   1,
 				   0, svalue,
 				   psymtab_language, objfile);
 	    }
@@ -3785,11 +3783,11 @@ parse_partial_symbols (struct objfile *objfile)
 
   /* 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;
+  if (objfile->psyms->psymtabs->next == NULL
+      && objfile->psyms->psymtabs->number_of_dependencies == 0
+      && objfile->psyms->psymtabs->n_global_syms == 0
+      && objfile->psyms->psymtabs->n_static_syms == 0)
+    objfile->psyms->psymtabs = NULL;
   do_cleanups (old_chain);
 }
 
@@ -3855,7 +3853,7 @@ handle_psymbol_enumerators (struct objfile *objfile, FDR *fh, int stype,
          in psymtabs, just in symtabs.  */
       add_psymbol_to_list (name, strlen (name), 1,
 			   VAR_DOMAIN, LOC_CONST,
-			   &objfile->static_psymbols, 0,
+			   0, 0,
 			   (CORE_ADDR) 0, psymtab_language, objfile);
       ext_sym += external_sym_size;
     }
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index cb186b1..c53006c 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -396,6 +396,7 @@ static struct sym_fns ecoff_sym_fns =
   mipscoff_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   mipscoff_symfile_init,	/* sym_init: read initial info, setup for sym_read() */
   mipscoff_symfile_read,	/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   mipscoff_symfile_finish,	/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets: dummy FIXME til implem sym reloc */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 953bc88..7face4c 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -53,6 +53,7 @@
 #include "observer.h"
 #include "complaints.h"
 #include "psymtab.h"
+#include "psympriv.h"		/* FIXME */
 #include "solist.h"
 
 /* Prototypes for local functions */
@@ -199,12 +200,12 @@ allocate_objfile (bfd *abfd, int flags)
   struct objfile *objfile;
 
   objfile = (struct objfile *) xzalloc (sizeof (struct objfile));
-  objfile->psymbol_cache = bcache_xmalloc ();
   objfile->macro_cache = bcache_xmalloc ();
   objfile->filename_cache = bcache_xmalloc ();
   /* We could use obstack_specify_allocation here instead, but
      gdb_obstack.h specifies the alloc/dealloc functions.  */
   obstack_init (&objfile->objfile_obstack);
+  objfile->psyms = allocate_psymtab_state (&objfile->objfile_obstack);
   terminate_minimal_symbol_table (objfile);
 
   objfile_alloc_data (objfile);
@@ -653,12 +654,8 @@ free_objfile (struct objfile *objfile)
     {
       xfree (objfile->name);
     }
-  if (objfile->global_psymbols.list)
-    xfree (objfile->global_psymbols.list);
-  if (objfile->static_psymbols.list)
-    xfree (objfile->static_psymbols.list);
+  destroy_psymtab_state (objfile->psyms);
   /* Free the obstacks for non-reusable objfiles */
-  bcache_xfree (objfile->psymbol_cache);
   bcache_xfree (objfile->macro_cache);
   bcache_xfree (objfile->filename_cache);
   if (objfile->demangled_names_hash)
@@ -785,8 +782,8 @@ objfile_relocate1 (struct objfile *objfile,
     }
   }
 
-  if (objfile->psymtabs_addrmap)
-    addrmap_relocate (objfile->psymtabs_addrmap,
+  if (objfile->psyms->psymtabs_addrmap)
+    addrmap_relocate (objfile->psyms->psymtabs_addrmap,
 		      ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
 
   if (objfile->sf)
@@ -895,7 +892,11 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
 int
 objfile_has_partial_symbols (struct objfile *objfile)
 {
-  return objfile->sf ? objfile->sf->qf->has_symbols (objfile) : 0;
+  /* It is cheaper to try the non-reading form first.  */
+  if (!objfile->sf)
+    return 0;
+  return (objfile->sf->qf->has_symbols (objfile, 0)
+	  || objfile->sf->qf->has_symbols (objfile, 1));
 }
 
 /* Return non-zero if OBJFILE has full symbols.  */
@@ -932,9 +933,20 @@ have_partial_symbols (void)
 
   ALL_OBJFILES (ofp)
   {
-    if (objfile_has_partial_symbols (ofp))
+    if (ofp->sf->qf->has_symbols (ofp, 0))
       return 1;
   }
+
+  /* Try again, after reading partial symbols.  We do this in two
+     passes because objfiles are always added to the head of the list,
+     and there might be a later objfile for which we've already read
+     partial symbols.  */
+  ALL_OBJFILES (ofp)
+  {
+    if (ofp->sf->qf->has_symbols (ofp, 1))
+      return 1;
+  }
+
   return 0;
 }
 
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 76410fd..92cc22a 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -29,6 +29,7 @@ struct bcache;
 struct htab;
 struct symtab;
 struct objfile_data;
+struct psymtab_state;
 
 /* This structure maintains information on a per-objfile basis about the
    "entry point" of the objfile, and the scope within which the entry point
@@ -207,22 +208,9 @@ struct objfile
 
     struct symtab *symtabs;
 
-    /* Each objfile points to a linked list of partial symtabs derived from
-       this file, one partial symtab structure for each compilation unit
-       (source file). */
+    /* All the state for partial symbol tables.  */
 
-    struct partial_symtab *psymtabs;
-
-    /* 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;
-
-    /* List of freed partial symtabs, available for re-use */
-
-    struct partial_symtab *free_psymtabs;
+    struct psymtab_state *psyms;
 
     /* The object file's BFD.  Can be null if the objfile contains only
        minimal symbols, e.g. the run time common symbols for SunOS4.  */
@@ -249,7 +237,6 @@ struct objfile
     /* A byte cache where we can stash arbitrary "chunks" of bytes that
        will not change. */
 
-    struct bcache *psymbol_cache;	/* Byte cache for partial syms */
     struct bcache *macro_cache;          /* Byte cache for macros */
     struct bcache *filename_cache;	 /* Byte cache for file names.  */
 
@@ -260,12 +247,6 @@ struct objfile
        if the name doesn't demangle.  */
     struct htab *demangled_names_hash;
 
-    /* Vectors of all partial symbols read in from file.  The actual data
-       is stored in the objfile_obstack. */
-
-    struct psymbol_allocation_list global_psymbols;
-    struct psymbol_allocation_list static_psymbols;
-
     /* Each file contains a pointer to an array of minimal symbols for all
        global symbols that are defined within the file.  The array is terminated
        by a "null symbol", one that has a NULL pointer for the name and a zero
@@ -426,6 +407,15 @@ struct objfile
 
 #define OBJF_USERLOADED	(1 << 3)	/* User loaded */
 
+/* Set if we have tried to read partial symtabs for this objfile.
+   This is used to allow lazy reading of partial symtabs.  */
+
+#define OBJF_SYMTABS_READ (1 << 4)
+
+/* This flag is set for the main objfile.  */
+
+#define OBJF_MAIN (1 << 5)
+
 /* The object file that contains the runtime common minimal symbols
    for SunOS4. Note that this objfile has no associated BFD.  */
 
diff --git a/gdb/psympriv.h b/gdb/psympriv.h
index 52f6e03..eabca4c 100644
--- a/gdb/psympriv.h
+++ b/gdb/psympriv.h
@@ -1,6 +1,6 @@
 /* Private partial symbol table definitions.
 
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -149,12 +149,10 @@ struct partial_symtab
   unsigned char readin;
 };
 
-extern void sort_pst_symbols (struct partial_symtab *);
-
 /* Traverse all psymtabs in one objfile.  */
 
 #define	ALL_OBJFILE_PSYMTABS(objfile, p) \
-    for ((p) = (objfile) -> psymtabs; (p) != NULL; (p) = (p) -> next)
+    for ((p) = (objfile)->psyms->psymtabs; (p) != NULL; (p) = (p) -> next)
 
 /* Traverse all psymtabs in all objfiles.  */
 
@@ -162,4 +160,150 @@ extern void sort_pst_symbols (struct partial_symtab *);
   ALL_OBJFILES (objfile)	 \
     ALL_OBJFILE_PSYMTABS (objfile, p)
 
+/* Like ALL_PSYMTABS, but ensure that partial symbols have been read
+   before examining the objfile.  */
+
+#define ALL_PSYMTABS_REQUIRED(objfile, p)			\
+  ALL_OBJFILES (objfile)					\
+    ALL_OBJFILE_PSYMTABS (require_partial_symbols (objfile), p)
+
+
+/* Partial symbols are stored in the psymbol_cache and pointers to
+   them are kept in a dynamically grown array that is obtained from
+   malloc and grown as necessary via realloc.  Each objfile typically
+   has two of these, one for global symbols and one for static
+   symbols.  Although this adds a level of indirection for storing or
+   accessing the partial symbols, it allows us to throw away duplicate
+   psymbols and set all pointers to the single saved instance.  */
+
+struct psymbol_allocation_list
+{
+
+  /* Pointer to beginning of dynamically allocated array of pointers
+     to partial symbols.  The array is dynamically expanded as
+     necessary to accommodate more pointers.  */
+
+  struct partial_symbol **list;
+
+  /* Pointer to next available slot in which to store a pointer to a
+     partial symbol.  */
+
+  struct partial_symbol **next;
+
+  /* Number of allocated pointer slots in current dynamic array (not
+     the number of bytes of storage).  The "next" pointer will always
+     point somewhere between list[0] and list[size], and when at
+     list[size] the array will be expanded on the next attempt to
+     store a pointer.  */
+
+  int size;
+};
+
+/* Partial symbols and partial symbol tables are managed using an
+   instance of this structure.  In normal use, a structure is
+   allocated on an objfile's obstack and assigned to the objfile's
+   'psyms' field.  */
+struct psymtab_state
+{
+  int writeable;
+
+  /* The obstack on which psymbols are allocated.  */
+  struct obstack *obstack;
+
+  /* Vectors of all partial symbols read in from file.  The actual data
+     is stored in the objfile_obstack. */
+  struct psymbol_allocation_list global_psymbols;
+  struct psymbol_allocation_list static_psymbols;
+
+  /* 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;
+
+  /* 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;
+
+  /* List of freed partial symtabs, available for re-use */
+  struct partial_symtab *free_psymtabs;
+
+  /* Byte cache for partial syms.  */
+  struct bcache *psymbol_cache;
+};
+
+
+/* Sort the global symbols associated with PST which are held in
+   STATE.  */
+void sort_pst_symbols (struct psymtab_state *state,
+		       struct partial_symtab *pst);
+
+/* Allocate a partial symbol table in STATE.  FILENAME and OBJFILE are
+   the file name and objfile associated with the new table.  */
+struct partial_symtab *allocate_psymtab_full (struct psymtab_state *state,
+					      const char *filename,
+					      struct objfile *objfile);
+
+/* A legacy function that calls allocate_psymtab_full using the
+   objfile's psymtab_state.  */
+struct partial_symtab *allocate_psymtab (const char *, struct objfile *);
+
+/* Discard a partial symbol table.  */
+void discard_psymtab (struct psymtab_state *state, struct partial_symtab *);
+
+/* Add any kind of symbol to a psymbol_allocation_list.  */
+const struct partial_symbol *add_psymbol_to_list_full
+    (struct psymtab_state *state,
+     const char *name, int namelength, int copy_name, domain_enum domain,
+     enum address_class class,
+     long val,	/* Value as a long */
+     CORE_ADDR coreaddr,	/* Value as a CORE_ADDR */
+     enum language language, struct objfile *objfile,
+     int is_global);
+
+/* A legacy function that calls add_psymbol_to_list_full using the
+   objfile's psymtab_state.  */
+const struct partial_symbol *add_psymbol_to_list
+    (const char *, int, int, domain_enum,
+     enum address_class,
+     int,
+     long, CORE_ADDR,
+     enum language, struct objfile *);
+
+/* Allocate and partially fill a partial symtab.  It will be
+   completely filled at the end of the symbol list.
+
+   STATE is the psymtab state object holding all the necessary state.
+   OBJFILE is the objfile associated with the symbol table.
+   FILENAME is the name of the symbol-file we are reading from.  */
+struct partial_symtab *start_psymtab_common_full
+    (struct psymtab_state *state,
+     struct objfile *objfile,
+     struct section_offsets *section_offsets,
+     const char *filename,
+     CORE_ADDR textlow);
+
+/* A legacy function that calls start_psymtab_common_full with the
+   objfile's psymtab_state.  */
+struct partial_symtab *start_psymtab_common
+    (struct objfile *objfile,
+     struct section_offsets *section_offsets, const char *filename,
+     CORE_ADDR textlow);
+
+/* Set n_global_syms and n_static_syms on PSYMTAB.  */
+void finalize_psymtab (struct psymtab_state *state,
+		       struct partial_symtab *psymtab);
+
+/* Change the obstack associated with a psymtab_state.  STATE is the
+   psymtab_state, which must be writeable.  OBSTACK is the new
+   obstack.  */
+void switch_psymtab_state_obstack (struct psymtab_state *state,
+				   struct obstack *new_obstack);
+
+/* A readonly psymtab_state.  This is temporarily put into an
+   objfile's psyms slot when reading psymtabs in a background
+   thread.  */
+extern struct psymtab_state readonly_psymtab_state;
+
 #endif /* PSYMPRIV_H */
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index dc63040..3932a64 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -58,6 +58,8 @@ static struct partial_symbol *fixup_psymbol_section (struct partial_symbol
 
 static struct symtab *psymtab_to_symtab (struct partial_symtab *pst);
 
+static struct objfile *require_partial_symbols (struct objfile *);
+
 /* Lookup the partial symbol table of a source file named NAME.
    *If* there is no '/' in the name, a match after a '/'
    in the psymtab filename will also work.  */
@@ -68,6 +70,7 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
 {
   struct partial_symtab *pst;
 
+  require_partial_symbols (objfile);
   ALL_OBJFILE_PSYMTABS (objfile, pst)
   {
     if (FILENAME_CMP (name, pst->filename) == 0)
@@ -225,9 +228,10 @@ 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)
+  require_partial_symbols (objfile);
+  if (objfile->psyms->psymtabs_addrmap != NULL)
     {
-      pst = addrmap_find (objfile->psymtabs_addrmap, pc);
+      pst = addrmap_find (objfile->psyms->psymtabs_addrmap, pc);
       if (pst != NULL)
 	{
 	  /* FIXME: addrmaps currently do not handle overlayed sections,
@@ -322,8 +326,8 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
   /* Search the global symbols as well as the static symbols, so that
      find_pc_partial_function doesn't use a minimal symbol and thus
      cache a bad endaddr.  */
-  for (pp = psymtab->objfile->global_psymbols.list + psymtab->globals_offset;
-    (pp - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset)
+  for (pp = psymtab->objfile->psyms->global_psymbols.list + psymtab->globals_offset;
+    (pp - (psymtab->objfile->psyms->global_psymbols.list + psymtab->globals_offset)
      < psymtab->n_global_syms);
        pp++)
     {
@@ -346,8 +350,8 @@ find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
 	}
     }
 
-  for (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
-    (pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
+  for (pp = psymtab->objfile->psyms->static_psymbols.list + psymtab->statics_offset;
+    (pp - (psymtab->objfile->psyms->static_psymbols.list + psymtab->statics_offset)
      < psymtab->n_static_syms);
        pp++)
     {
@@ -412,6 +416,7 @@ lookup_symbol_aux_psymtabs (struct objfile *objfile,
   struct partial_symtab *ps;
   const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
 
+  require_partial_symbols (objfile);
   ALL_OBJFILE_PSYMTABS (objfile, ps)
   {
     if (!ps->readin && lookup_partial_symbol (ps, name, psymtab_index, domain))
@@ -438,8 +443,8 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name,
       return (NULL);
     }
   start = (global ?
-	   pst->objfile->global_psymbols.list + pst->globals_offset :
-	   pst->objfile->static_psymbols.list + pst->statics_offset);
+	   pst->objfile->psyms->global_psymbols.list + pst->globals_offset :
+	   pst->objfile->psyms->static_psymbols.list + pst->statics_offset);
 
   if (global)			/* This means we can use a binary search. */
     {
@@ -541,8 +546,8 @@ relocate_psymtabs (struct objfile *objfile,
       p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
     }
 
-  for (psym = objfile->global_psymbols.list;
-       psym < objfile->global_psymbols.next;
+  for (psym = objfile->psyms->global_psymbols.list;
+       psym < objfile->psyms->global_psymbols.next;
        psym++)
     {
       fixup_psymbol_section (*psym, objfile);
@@ -550,8 +555,8 @@ relocate_psymtabs (struct objfile *objfile,
 	SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
 						  SYMBOL_SECTION (*psym));
     }
-  for (psym = objfile->static_psymbols.list;
-       psym < objfile->static_psymbols.next;
+  for (psym = objfile->psyms->static_psymbols.list;
+       psym < objfile->psyms->static_psymbols.next;
        psym++)
     {
       fixup_psymbol_section (*psym, objfile);
@@ -567,6 +572,7 @@ find_last_source_symtab_from_partial (struct objfile *ofp)
   struct partial_symtab *ps;
   struct partial_symtab *cs_pst = 0;
 
+  require_partial_symbols (ofp);
   ALL_OBJFILE_PSYMTABS (ofp, ps)
     {
       const char *name = ps->filename;
@@ -752,14 +758,14 @@ dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
   if (psymtab->n_global_syms > 0)
     {
       print_partial_symbols (gdbarch,
-			     objfile->global_psymbols.list
+			     objfile->psyms->global_psymbols.list
 			     + psymtab->globals_offset,
 			     psymtab->n_global_syms, "Global", outfile);
     }
   if (psymtab->n_static_syms > 0)
     {
       print_partial_symbols (gdbarch,
-			     objfile->static_psymbols.list
+			     objfile->psyms->static_psymbols.list
 			     + psymtab->statics_offset,
 			     psymtab->n_static_syms, "Static", outfile);
     }
@@ -786,10 +792,10 @@ dump_psymtabs_for_objfile (struct objfile *objfile)
 {
   struct partial_symtab *psymtab;
 
-  if (objfile->psymtabs)
+  if (objfile->psyms->psymtabs)
     {
       printf_filtered ("Psymtabs:\n");
-      for (psymtab = objfile->psymtabs;
+      for (psymtab = objfile->psyms->psymtabs;
 	   psymtab != NULL;
 	   psymtab = psymtab->next)
 	{
@@ -815,6 +821,7 @@ read_symtabs_for_function (struct objfile *objfile, const char *func_name)
 {
   struct partial_symtab *ps;
 
+  require_partial_symbols (objfile);
   ALL_OBJFILE_PSYMTABS (objfile, ps)
   {
     if (ps->readin)
@@ -833,7 +840,9 @@ expand_partial_symbol_tables (struct objfile *objfile)
 {
   struct partial_symtab *psymtab;
 
-  for (psymtab = objfile->psymtabs;
+  require_partial_symbols (objfile);
+
+  for (psymtab = objfile->psyms->psymtabs;
        psymtab != NULL;
        psymtab = psymtab->next)
     {
@@ -846,6 +855,7 @@ read_psymtabs_with_filename (struct objfile *objfile, const char *filename)
 {
   struct partial_symtab *p;
 
+  require_partial_symbols (objfile);
   ALL_OBJFILE_PSYMTABS (objfile, p)
     {
       if (strcmp (filename, p->filename) == 0)
@@ -868,8 +878,8 @@ map_symbol_names_psymtab (struct objfile *objfile,
       if (ps->readin)
 	continue;
 
-      for (psym = objfile->global_psymbols.list + ps->globals_offset;
-	   psym < (objfile->global_psymbols.list + ps->globals_offset
+      for (psym = objfile->psyms->global_psymbols.list + ps->globals_offset;
+	   psym < (objfile->psyms->global_psymbols.list + ps->globals_offset
 		   + ps->n_global_syms);
 	   psym++)
 	{
@@ -878,8 +888,8 @@ map_symbol_names_psymtab (struct objfile *objfile,
 	  (*fun) (SYMBOL_NATURAL_NAME (*psym), data);
 	}
 
-      for (psym = objfile->static_psymbols.list + ps->statics_offset;
-	   psym < (objfile->static_psymbols.list + ps->statics_offset
+      for (psym = objfile->psyms->static_psymbols.list + ps->statics_offset;
+	   psym < (objfile->psyms->static_psymbols.list + ps->statics_offset
 		   + ps->n_static_syms);
 	   psym++)
 	{
@@ -899,6 +909,7 @@ map_symbol_filenames_psymtab (struct objfile *objfile,
 
   ALL_OBJFILE_PSYMTABS (objfile, ps)
     {
+      /* FIXME: require psymtab?? */
       const char *fullname;
 
       if (ps->readin)
@@ -946,6 +957,7 @@ find_symbol_file_from_partial (struct objfile *objfile, const char *name)
 {
   struct partial_symtab *pst;
 
+  require_partial_symbols (objfile);
   ALL_OBJFILE_PSYMTABS (objfile, pst)
     {
       if (lookup_partial_symbol (pst, name, 1, VAR_DOMAIN))
@@ -975,8 +987,8 @@ ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name,
     }
 
   start = (global ?
-           pst->objfile->global_psymbols.list + pst->globals_offset :
-           pst->objfile->static_psymbols.list + pst->statics_offset);
+           pst->objfile->psyms->global_psymbols.list + pst->globals_offset :
+           pst->objfile->psyms->static_psymbols.list + pst->statics_offset);
 
   if (wild)
     {
@@ -1132,6 +1144,7 @@ expand_symtabs_matching_via_partial (struct objfile *objfile,
 {
   struct partial_symtab *ps;
 
+  require_partial_symbols (objfile);
   ALL_OBJFILE_PSYMTABS (objfile, ps)
     {
       struct partial_symbol **psym;
@@ -1144,20 +1157,20 @@ expand_symtabs_matching_via_partial (struct objfile *objfile,
       if (! (*file_matcher) (ps->filename, data))
 	continue;
 
-      gbound = objfile->global_psymbols.list + ps->globals_offset + ps->n_global_syms;
-      sbound = objfile->static_psymbols.list + ps->statics_offset + ps->n_static_syms;
+      gbound = objfile->psyms->global_psymbols.list + ps->globals_offset + ps->n_global_syms;
+      sbound = objfile->psyms->static_psymbols.list + ps->statics_offset + ps->n_static_syms;
       bound = gbound;
 
       /* Go through all of the symbols stored in a partial
 	 symtab in one loop. */
-      psym = objfile->global_psymbols.list + ps->globals_offset;
+      psym = objfile->psyms->global_psymbols.list + ps->globals_offset;
       while (keep_going)
 	{
 	  if (psym >= bound)
 	    {
 	      if (bound == gbound && ps->n_static_syms != 0)
 		{
-		  psym = objfile->static_psymbols.list + ps->statics_offset;
+		  psym = objfile->psyms->static_psymbols.list + ps->statics_offset;
 		  bound = sbound;
 		}
 	      else
@@ -1187,9 +1200,11 @@ expand_symtabs_matching_via_partial (struct objfile *objfile,
 }
 
 static int
-objfile_has_psyms (struct objfile *objfile)
+objfile_has_psyms (struct objfile *objfile, int try_read)
 {
-  return objfile->psymtabs != NULL;
+  if (try_read)
+    require_partial_symbols (objfile);
+  return objfile->psyms->psymtabs != NULL;
 }
 
 const struct quick_symbol_functions psym_functions =
@@ -1215,6 +1230,32 @@ const struct quick_symbol_functions psym_functions =
 
 
 
+/* Ensure that the partial symbols for OBJFILE have been loaded.  This
+   function always returns its argument, as a convenience.  */
+
+static struct objfile *
+require_partial_symbols (struct objfile *objfile)
+{
+  if ((objfile->flags & OBJF_SYMTABS_READ) == 0)
+    {
+      objfile->flags |= OBJF_SYMTABS_READ;
+
+      if (objfile->sf->sym_read_psymbols)
+	(*objfile->sf->sym_read_psymbols) (objfile);
+    }
+  return objfile;
+}
+
+
+
+static void
+check_writeable (struct psymtab_state *state)
+{
+  if (!state->writeable)
+    internal_error (__FILE__, __LINE__,
+		    _("attempt to write to readonly psymtab_state"));
+}
+
 /* This compares two partial symbols by names, using strcmp_iw_ordered
    for the comparison.  */
 
@@ -1229,38 +1270,46 @@ compare_psymbols (const void *s1p, const void *s2p)
 }
 
 void
-sort_pst_symbols (struct partial_symtab *pst)
+sort_pst_symbols (struct psymtab_state *state, struct partial_symtab *pst)
 {
-  /* Sort the global list; don't sort the static list */
-
-  qsort (pst->objfile->global_psymbols.list + pst->globals_offset,
+  check_writeable (state);
+  qsort (state->global_psymbols.list + pst->globals_offset,
 	 pst->n_global_syms, sizeof (struct partial_symbol *),
 	 compare_psymbols);
 }
 
-/* Allocate and partially fill a partial symtab.  It will be
-   completely filled at the end of the symbol list.
-
-   FILENAME is the name of the symbol-file we are reading from. */
-
 struct partial_symtab *
-start_psymtab_common (struct objfile *objfile,
-		      struct section_offsets *section_offsets,
-		      const char *filename,
-		      CORE_ADDR textlow, struct partial_symbol **global_syms,
-		      struct partial_symbol **static_syms)
+start_psymtab_common_full (struct psymtab_state *state,
+			   struct objfile *objfile,
+			   struct section_offsets *section_offsets,
+			   const char *filename,
+			   CORE_ADDR textlow)
 {
   struct partial_symtab *psymtab;
 
-  psymtab = allocate_psymtab (filename, objfile);
+  check_writeable (state);
+
+  psymtab = allocate_psymtab_full (state, filename, objfile);
   psymtab->section_offsets = section_offsets;
   psymtab->textlow = textlow;
   psymtab->texthigh = psymtab->textlow;		/* default */
-  psymtab->globals_offset = global_syms - objfile->global_psymbols.list;
-  psymtab->statics_offset = static_syms - objfile->static_psymbols.list;
+  psymtab->globals_offset = (state->global_psymbols.next
+			     - state->global_psymbols.list);
+  psymtab->statics_offset = (state->static_psymbols.next
+			     - state->static_psymbols.list);
   return (psymtab);
 }
 
+struct partial_symtab *
+start_psymtab_common (struct objfile *objfile,
+		      struct section_offsets *section_offsets,
+		      const char *filename,
+		      CORE_ADDR textlow)
+{
+  return start_psymtab_common_full (objfile->psyms, objfile,
+				    section_offsets, filename, textlow);
+}
+
 /* Helper function, initialises partial symbol structure and stashes 
    it into objfile's bcache.  Note that our caching mechanism will
    use all fields of struct partial_symbol to determine hash value of the
@@ -1268,7 +1317,8 @@ start_psymtab_common (struct objfile *objfile,
    different domain (or address) is possible and correct.  */
 
 static const struct partial_symbol *
-add_psymbol_to_bcache (char *name, int namelength, int copy_name,
+add_psymbol_to_bcache (struct psymtab_state *state,
+		       const char *name, int namelength, int copy_name,
 		       domain_enum domain,
 		       enum address_class class,
 		       long val,	/* Value as a long */
@@ -1280,7 +1330,7 @@ add_psymbol_to_bcache (char *name, int namelength, int copy_name,
      structure which might contain random data, causing cache misses in
      bcache. */
   static struct partial_symbol psymbol;
-
+  
   /* However, we must ensure that the entire 'value' field has been
      zeroed before assigning to it, because an assignment may not
      write the entire field.  */
@@ -1299,11 +1349,39 @@ add_psymbol_to_bcache (char *name, int namelength, int copy_name,
   PSYMBOL_DOMAIN (&psymbol) = domain;
   PSYMBOL_CLASS (&psymbol) = class;
 
-  SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
+  SYMBOL_SET_NAMES_FULL (&psymbol, name, namelength, copy_name,
+			 objfile, state->obstack);
 
   /* Stash the partial symbol away in the cache */
   return bcache_full (&psymbol, sizeof (struct partial_symbol),
-		      objfile->psymbol_cache, added);
+		      state->psymbol_cache, added);
+}
+
+/* Increase the space allocated for LISTP, which is probably
+   global_psymbols or static_psymbols. This space will eventually
+   be freed in free_objfile().  */
+
+static void
+extend_psymbol_list (struct psymbol_allocation_list *listp)
+{
+  int new_size;
+  if (listp->size == 0)
+    {
+      new_size = 255;
+      listp->list = (struct partial_symbol **)
+	xmalloc (new_size * sizeof (struct partial_symbol *));
+    }
+  else
+    {
+      new_size = listp->size * 2;
+      listp->list = (struct partial_symbol **)
+	xrealloc ((char *) listp->list,
+		  new_size * sizeof (struct partial_symbol *));
+    }
+  /* Next assumes we only went one over.  Should be good if
+     program works correctly */
+  listp->next = listp->list + listp->size;
+  listp->size = new_size;
 }
 
 /* Helper function, adds partial symbol to the given partial symbol
@@ -1315,7 +1393,7 @@ append_psymbol_to_list (struct psymbol_allocation_list *list,
 			struct objfile *objfile)
 {
   if (list->next >= list->list + list->size)
-    extend_psymbol_list (list, objfile);
+    extend_psymbol_list (list);
   *list->next++ = (struct partial_symbol *) psym;
   OBJSTAT (objfile, n_psyms++);
 }
@@ -1336,89 +1414,71 @@ append_psymbol_to_list (struct psymbol_allocation_list *list,
    cache.  */
 
 const struct partial_symbol *
-add_psymbol_to_list (char *name, int namelength, int copy_name,
-		     domain_enum domain,
-		     enum address_class class,
-		     struct psymbol_allocation_list *list, 
-		     long val,	/* Value as a long */
-		     CORE_ADDR coreaddr,	/* Value as a CORE_ADDR */
-		     enum language language, struct objfile *objfile)
+add_psymbol_to_list_full (struct psymtab_state *state,
+			  const char *name, int namelength, int copy_name,
+			  domain_enum domain,
+			  enum address_class class,
+			  long val,	/* Value as a long */
+			  CORE_ADDR coreaddr,	/* Value as a CORE_ADDR */
+			  enum language language, struct objfile *objfile,
+			  int is_global)
 {
   const struct partial_symbol *psym;
-
   int added;
 
+  check_writeable (state);
+
   /* Stash the partial symbol away in the cache */
-  psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
+  psym = add_psymbol_to_bcache (state, name, namelength, copy_name,
+				domain, class,
 				val, coreaddr, language, objfile, &added);
 
   /* Do not duplicate global partial symbols.  */
-  if (list == &objfile->global_psymbols
-      && !added)
+  if (is_global && !added)
     return psym;
 
   /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
-  append_psymbol_to_list (list, psym, objfile);
+  append_psymbol_to_list ((is_global ? &state->global_psymbols
+			   : &state->static_psymbols),
+			  psym, objfile);
   return psym;
 }
 
-/* Initialize storage for partial symbols.  */
-
-void
-init_psymbol_list (struct objfile *objfile, int total_symbols)
+const struct partial_symbol *
+add_psymbol_to_list (const char *name, int namelength, int copy_name,
+		     domain_enum domain,
+		     enum address_class class,
+		     int is_global,
+		     long val,	/* Value as a long */
+		     CORE_ADDR coreaddr,	/* Value as a CORE_ADDR */
+		     enum language language, struct objfile *objfile)
 {
-  /* Free any previously allocated psymbol lists.  */
-
-  if (objfile->global_psymbols.list)
-    {
-      xfree (objfile->global_psymbols.list);
-    }
-  if (objfile->static_psymbols.list)
-    {
-      xfree (objfile->static_psymbols.list);
-    }
-
-  /* Current best guess is that approximately a twentieth
-     of the total symbols (in a debugging file) are global or static
-     oriented symbols */
-
-  objfile->global_psymbols.size = total_symbols / 10;
-  objfile->static_psymbols.size = total_symbols / 10;
-
-  if (objfile->global_psymbols.size > 0)
-    {
-      objfile->global_psymbols.next =
-	objfile->global_psymbols.list = (struct partial_symbol **)
-	xmalloc ((objfile->global_psymbols.size
-		  * sizeof (struct partial_symbol *)));
-    }
-  if (objfile->static_psymbols.size > 0)
-    {
-      objfile->static_psymbols.next =
-	objfile->static_psymbols.list = (struct partial_symbol **)
-	xmalloc ((objfile->static_psymbols.size
-		  * sizeof (struct partial_symbol *)));
-    }
+  return add_psymbol_to_list_full (objfile->psyms,
+				   name, namelength, copy_name, domain, class,
+				   val, coreaddr, language, objfile,
+				   is_global);
 }
 
 struct partial_symtab *
-allocate_psymtab (const char *filename, struct objfile *objfile)
+allocate_psymtab_full (struct psymtab_state *state,
+		       const char *filename, struct objfile *objfile)
 {
   struct partial_symtab *psymtab;
 
-  if (objfile->free_psymtabs)
+  check_writeable (state);
+
+  if (state->free_psymtabs)
     {
-      psymtab = objfile->free_psymtabs;
-      objfile->free_psymtabs = psymtab->next;
+      psymtab = state->free_psymtabs;
+      state->free_psymtabs = psymtab->next;
     }
   else
     psymtab = (struct partial_symtab *)
-      obstack_alloc (&objfile->objfile_obstack,
-		     sizeof (struct partial_symtab));
+      obstack_alloc (state->obstack, sizeof (struct partial_symtab));
 
   memset (psymtab, 0, sizeof (struct partial_symtab));
   psymtab->filename = obsavestring (filename, strlen (filename),
-				    &objfile->objfile_obstack);
+				    state->obstack);
   psymtab->symtab = NULL;
 
   /* Prepend it to the psymtab list for the objfile it belongs to.
@@ -1426,17 +1486,25 @@ allocate_psymtab (const char *filename, struct objfile *objfile)
      inserted order. */
 
   psymtab->objfile = objfile;
-  psymtab->next = objfile->psymtabs;
-  objfile->psymtabs = psymtab;
+  psymtab->next = state->psymtabs;
+  state->psymtabs = psymtab;
 
-  return (psymtab);
+  return psymtab;
+}
+
+struct partial_symtab *
+allocate_psymtab (const char *filename, struct objfile *objfile)
+{
+  return allocate_psymtab_full (objfile->psyms, filename, objfile);
 }
 
 void
-discard_psymtab (struct partial_symtab *pst)
+discard_psymtab (struct psymtab_state *state, struct partial_symtab *pst)
 {
   struct partial_symtab **prev_pst;
 
+  check_writeable (state);
+
   /* From dbxread.c:
      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
@@ -1446,46 +1514,67 @@ discard_psymtab (struct partial_symtab *pst)
 
   /* First, snip it out of the psymtab chain */
 
-  prev_pst = &(pst->objfile->psymtabs);
+  prev_pst = &(state->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 = pst->objfile->free_psymtabs;
-  pst->objfile->free_psymtabs = pst;
+  pst->next = state->free_psymtabs;
+  state->free_psymtabs = pst;
 }
 
-/* Increase the space allocated for LISTP, which is probably
-   global_psymbols or static_psymbols. This space will eventually
-   be freed in free_objfile().  */
+void
+finalize_psymtab (struct psymtab_state *state,
+		  struct partial_symtab *psymtab)
+{
+  check_writeable (state);
+
+  psymtab->n_global_syms
+    = state->global_psymbols.next - (state->global_psymbols.list
+				     + psymtab->globals_offset);
+  psymtab->n_static_syms =
+    state->static_psymbols.next - (state->static_psymbols.list
+				   + psymtab->statics_offset);
+}
 
 void
-extend_psymbol_list (struct psymbol_allocation_list *listp,
-		     struct objfile *objfile)
+destroy_psymtab_state (struct psymtab_state *state)
 {
-  int new_size;
+  xfree (state->global_psymbols.list);
+  memset (&state->global_psymbols, 0, sizeof (state->global_psymbols));
+  xfree (state->static_psymbols.list);
+  memset (&state->static_psymbols, 0, sizeof (state->static_psymbols));
+  bcache_xfree (state->psymbol_cache);
+}
 
-  if (listp->size == 0)
-    {
-      new_size = 255;
-      listp->list = (struct partial_symbol **)
-	xmalloc (new_size * sizeof (struct partial_symbol *));
-    }
-  else
-    {
-      new_size = listp->size * 2;
-      listp->list = (struct partial_symbol **)
-	xrealloc ((char *) listp->list,
-		  new_size * sizeof (struct partial_symbol *));
-    }
-  /* Next assumes we only went one over.  Should be good if
-     program works correctly */
-  listp->next = listp->list + listp->size;
-  listp->size = new_size;
+struct psymtab_state *
+allocate_psymtab_state (struct obstack *obstack)
+{
+  struct psymtab_state *state;
+
+  state
+    = (struct psymtab_state *) obstack_alloc (obstack,
+					      sizeof (struct psymtab_state));
+  memset (state, 0, sizeof (struct psymtab_state));
+  state->writeable = 1;
+  state->obstack = obstack;
+  state->psymbol_cache = bcache_xmalloc ();
+  return state;
 }
 
+void
+switch_psymtab_state_obstack (struct psymtab_state *state,
+			      struct obstack *new_obstack)
+{
+  check_writeable (state);
+  state->obstack = new_obstack;
+}
+
+/* A global readonly state.  */
+struct psymtab_state readonly_psymtab_state;
+
 
 
 void
@@ -1590,7 +1679,7 @@ maintenance_info_psymtabs (char *regexp, int from_tty)
 	      if (psymtab->n_global_syms)
 		{
 		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
-				   host_address_to_string (psymtab->objfile->global_psymbols.list
+				   host_address_to_string (psymtab->objfile->psyms->global_psymbols.list
 				    + psymtab->globals_offset),
 				   psymtab->n_global_syms);
 		}
@@ -1600,7 +1689,7 @@ maintenance_info_psymtabs (char *regexp, int from_tty)
 	      if (psymtab->n_static_syms)
 		{
 		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
-				   host_address_to_string (psymtab->objfile->static_psymbols.list
+				   host_address_to_string (psymtab->objfile->psyms->static_psymbols.list
 				    + psymtab->statics_offset),
 				   psymtab->n_static_syms);
 		}
@@ -1658,7 +1747,7 @@ maintenance_check_symtabs (char *ignore, int from_tty)
       continue;
     bv = BLOCKVECTOR (s);
     b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-    psym = ps->objfile->static_psymbols.list + ps->statics_offset;
+    psym = ps->objfile->psyms->static_psymbols.list + ps->statics_offset;
     length = ps->n_static_syms;
     while (length--)
       {
@@ -1675,7 +1764,7 @@ maintenance_check_symtabs (char *ignore, int from_tty)
 	psym++;
       }
     b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-    psym = ps->objfile->global_psymbols.list + ps->globals_offset;
+    psym = ps->objfile->psyms->global_psymbols.list + ps->globals_offset;
     length = ps->n_global_syms;
     while (length--)
       {
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
index 9b8c8df..a6f0113 100644
--- a/gdb/psymtab.h
+++ b/gdb/psymtab.h
@@ -1,6 +1,6 @@
 /* Public partial symbol table definitions.
 
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,6 +26,17 @@ void map_partial_symbol_filenames (void (*) (const char *, const char *,
 					     void *),
 				   void *);
 
+struct psymtab_state;
+
+/* Allocate a new psymtab_state on OBSTACK.  The new psymtab_state is
+   initialized.  */
+struct psymtab_state *allocate_psymtab_state (struct obstack *obstack);
+
+/* Free any memory allocated by the psymtab_state object.  After this
+   call, the contents of the object are invalid.  The object itself is
+   not deallocated, however.  */
+void destroy_psymtab_state (struct psymtab_state *state);
+
 extern const struct quick_symbol_functions psym_functions;
 
 #endif /* PSYMTAB_H */
diff --git a/gdb/solib.c b/gdb/solib.c
index 837814b..58e1511 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1068,7 +1068,8 @@ info_sharedlibrary_command (char *pattern, int from_tty)
 
       if (! ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))
 	  && so->symbols_loaded
-	  && !objfile_has_symbols (so->objfile))
+	  && !objfile_has_full_symbols (so->objfile)
+	  && !objfile_has_partial_symbols (so->objfile))
 	{
 	  so_missing_debug_info = 1;
 	  ui_out_field_string (uiout, "syms-read", "Yes (*)");
diff --git a/gdb/somread.c b/gdb/somread.c
index cc36042..023c8a2 100644
--- a/gdb/somread.c
+++ b/gdb/somread.c
@@ -433,6 +433,7 @@ static struct sym_fns som_sym_fns =
   som_new_init,			/* sym_new_init: init anything gbl to entire symtab */
   som_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   som_symfile_read,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   som_symfile_finish,		/* sym_finish: finished with file, cleanup */
   som_symfile_offsets,		/* sym_offsets:  Translate ext. to int. relocation */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/symfile.c b/gdb/symfile.c
index ab51fa4..169b482 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1030,6 +1030,22 @@ new_symfile_objfile (struct objfile *objfile, int add_flags)
   clear_complaints (&symfile_complaints, 0, add_flags & SYMFILE_VERBOSE);
 }
 
+/* A helper function which returns true if OBJFILE has any debug
+   symbols, and false otherwise.  */
+static int
+has_any_debug_symbols (struct objfile *objfile)
+{
+  /* This is ordered according to the cost of calling each
+     function.  */
+  return
+    (objfile_has_full_symbols (objfile)
+     || (objfile->separate_debug_objfile
+	 && objfile_has_full_symbols (objfile->separate_debug_objfile))
+     || objfile_has_partial_symbols (objfile)
+     || (objfile->separate_debug_objfile
+	 && objfile_has_partial_symbols (objfile->separate_debug_objfile)));
+}
+
 /* Process a symbol file, as either the main file or as a dynamically
    loaded file.
 
@@ -1064,13 +1080,16 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
   /* Give user a chance to burp if we'd be
      interactively wiping out any existing symbols.  */
 
-  if ((have_full_symbols () || have_partial_symbols ())
-      && (add_flags & SYMFILE_MAINLINE)
+  if ((add_flags & SYMFILE_MAINLINE)
+      && (have_full_symbols () || have_partial_symbols ())
       && from_tty
+      && (have_full_symbols () || have_partial_symbols ())
       && !query (_("Load new symbol table from \"%s\"? "), name))
     error (_("Not confirmed."));
 
   objfile = allocate_objfile (abfd, flags);
+  if (add_flags & SYMFILE_MAINLINE)
+    objfile->flags |= OBJF_MAIN;
   discard_cleanups (my_cleanups);
 
   /* We either created a new mapped symbol table, mapped an existing
@@ -1108,8 +1127,10 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
 	objfile->sf->qf->expand_all_symtabs (objfile);
     }
 
+  /* has_any_debug_symbols is not fully compatible with the former calls which
+     would just be needlessly expensive here.  */
   if ((from_tty || info_verbose)
-      && !objfile_has_symbols (objfile))
+      && !has_any_debug_symbols (objfile))
     {
       wrap_here ("");
       printf_unfiltered (_("(no debugging symbols found)..."));
@@ -2389,20 +2410,9 @@ reread_symbols (void)
 	     automatically recreated by sym_read.  */
           free_objfile_separate_debug (objfile);
 
-	  /* FIXME: Do we have to free a whole linked list, or is this
-	     enough?  */
-	  if (objfile->global_psymbols.list)
-	    xfree (objfile->global_psymbols.list);
-	  memset (&objfile->global_psymbols, 0,
-		  sizeof (objfile->global_psymbols));
-	  if (objfile->static_psymbols.list)
-	    xfree (objfile->static_psymbols.list);
-	  memset (&objfile->static_psymbols, 0,
-		  sizeof (objfile->static_psymbols));
+	  destroy_psymtab_state (objfile->psyms);
 
 	  /* Free the obstacks for non-reusable objfiles */
-	  bcache_xfree (objfile->psymbol_cache);
-	  objfile->psymbol_cache = bcache_xmalloc ();
 	  bcache_xfree (objfile->macro_cache);
 	  objfile->macro_cache = bcache_xmalloc ();
 	  bcache_xfree (objfile->filename_cache);
@@ -2415,9 +2425,6 @@ reread_symbols (void)
 	  obstack_free (&objfile->objfile_obstack, 0);
 	  objfile->sections = NULL;
 	  objfile->symtabs = NULL;
-	  objfile->psymtabs = NULL;
-	  objfile->psymtabs_addrmap = NULL;
-	  objfile->free_psymtabs = NULL;
 	  objfile->cp_namespace_symtab = NULL;
 	  objfile->msymbols = NULL;
 	  objfile->deprecated_sym_private = NULL;
@@ -2427,7 +2434,6 @@ reread_symbols (void)
 	  memset (&objfile->msymbol_demangled_hash, 0,
 		  sizeof (objfile->msymbol_demangled_hash));
 
-	  objfile->psymbol_cache = bcache_xmalloc ();
 	  objfile->macro_cache = bcache_xmalloc ();
 	  objfile->filename_cache = bcache_xmalloc ();
 	  /* obstack_init also initializes the obstack so it is
@@ -2442,6 +2448,9 @@ reread_symbols (void)
 	    }
 	  terminate_minimal_symbol_table (objfile);
 
+	  objfile->psyms
+	    = allocate_psymtab_state (&objfile->objfile_obstack);
+
 	  /* We use the same section offsets as from last time.  I'm not
 	     sure whether that is always correct for shared libraries.  */
 	  objfile->section_offsets = (struct section_offsets *)
@@ -2459,6 +2468,8 @@ reread_symbols (void)
 	      (*objfile->sf->sym_new_init) (objfile);
 	    }
 
+	  objfile->flags &= ~OBJF_SYMTABS_READ;
+
 	  (*objfile->sf->sym_init) (objfile);
 	  clear_complaints (&symfile_complaints, 1, 1);
 	  /* Do not set flags as this is safe and we don't want to be
diff --git a/gdb/symfile.h b/gdb/symfile.h
index d53c465..f1024dc 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -32,37 +32,6 @@ struct obj_section;
 struct obstack;
 struct block;
 
-/* Partial symbols are stored in the psymbol_cache and pointers to
-   them are kept in a dynamically grown array that is obtained from
-   malloc and grown as necessary via realloc.  Each objfile typically
-   has two of these, one for global symbols and one for static
-   symbols.  Although this adds a level of indirection for storing or
-   accessing the partial symbols, it allows us to throw away duplicate
-   psymbols and set all pointers to the single saved instance.  */
-
-struct psymbol_allocation_list
-{
-
-  /* Pointer to beginning of dynamically allocated array of pointers
-     to partial symbols.  The array is dynamically expanded as
-     necessary to accommodate more pointers.  */
-
-  struct partial_symbol **list;
-
-  /* Pointer to next available slot in which to store a pointer to a
-     partial symbol.  */
-
-  struct partial_symbol **next;
-
-  /* Number of allocated pointer slots in current dynamic array (not
-     the number of bytes of storage).  The "next" pointer will always
-     point somewhere between list[0] and list[size], and when at
-     list[size] the array will be expanded on the next attempt to
-     store a pointer.  */
-
-  int size;
-};
-
 /* Define an array of addresses to accommodate non-contiguous dynamic
    loading of modules.  This is for use when entering commands, so we
    can keep track of the section names until we read the file and can
@@ -131,9 +100,11 @@ struct symfile_segment_data
 
 struct quick_symbol_functions
 {
-  /* Return true if this objfile has any "partial" symbols
-     available.  */
-  int (*has_symbols) (struct objfile *objfile);
+  /* Return true if this objfile has any "partial" symbols available.
+     If TRY_READ is zero, do not do any extra work, just return the
+     answer.  If TRY_READ is nonzero, try to read partial symbols
+     first, if appropriate.  */
+  int (*has_symbols) (struct objfile *objfile, int try_read);
 
   /* Return the symbol table for the "last" file appearing in
      OBJFILE.  */
@@ -300,6 +271,12 @@ struct sym_fns
 
   void (*sym_read) (struct objfile *, int);
 
+  /* Read the partial symbols for an objfile.  This may be NULL, in
+     which case gdb assumes that sym_read already read the partial
+     symbols.  */
+
+  void (*sym_read_psymbols) (struct objfile *);
+
   /* Called when we are finished with an objfile.  Should do all
      cleanup that is specific to the object file format for the
      particular objfile.  */
@@ -373,22 +350,6 @@ extern struct symfile_segment_data *default_symfile_segments (bfd *abfd);
 extern bfd_byte *default_symfile_relocate (struct objfile *objfile,
                                            asection *sectp, bfd_byte *buf);
 
-extern void extend_psymbol_list (struct psymbol_allocation_list *,
-				 struct objfile *);
-
-/* Add any kind of symbol to a psymbol_allocation_list.  */
-
-/* #include "demangle.h" */
-
-extern const
-struct partial_symbol *add_psymbol_to_list (char *, int, int, domain_enum,
-					    enum address_class,
-					    struct psymbol_allocation_list *,
-					    long, CORE_ADDR,
-					    enum language, struct objfile *);
-
-extern void init_psymbol_list (struct objfile *, int);
-
 extern struct symtab *allocate_symtab (char *, struct objfile *);
 
 extern void add_symtab_fns (struct sym_fns *);
@@ -446,12 +407,6 @@ extern struct section_addr_info
 extern void free_section_addr_info (struct section_addr_info *);
 
 
-extern struct partial_symtab *start_psymtab_common (struct objfile *,
-						    struct section_offsets *,
-						    const char *, CORE_ADDR,
-						    struct partial_symbol **,
-						    struct partial_symbol **);
-
 /* Make a copy of the string at PTR with SIZE characters in the symbol
    obstack (and add a null character at the end in the copy).  Returns
    the address of the copy.  */
@@ -491,11 +446,6 @@ extern int auto_solib_limit;
 
 extern void set_initial_language (void);
 
-extern struct partial_symtab *allocate_psymtab (const char *,
-						struct objfile *);
-
-extern void discard_psymtab (struct partial_symtab *);
-
 extern void find_lowest_section (bfd *, asection *, void *);
 
 extern bfd *symfile_bfd_open (char *);
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 62e6b97..a469ddd 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -40,6 +40,7 @@
 #include "readline/readline.h"
 
 #include "psymtab.h"
+#include "psympriv.h"		/* FIXME */
 
 #ifndef DEV_TTY
 #define DEV_TTY "/dev/tty"
@@ -130,7 +131,9 @@ print_symbol_bcache_statistics (void)
     ALL_PSPACE_OBJFILES (pspace, objfile)
   {
     printf_filtered (_("Byte cache statistics for '%s':\n"), objfile->name);
-    print_bcache_statistics (objfile->psymbol_cache, "partial symbol cache");
+    if (objfile->psyms)
+      print_bcache_statistics (objfile->psyms->psymbol_cache,
+			       "partial symbol cache");
     print_bcache_statistics (objfile->macro_cache, "preprocessor macro cache");
     print_bcache_statistics (objfile->filename_cache, "file name cache");
   }
@@ -187,8 +190,9 @@ print_objfile_statistics (void)
 		       OBJSTAT (objfile, sz_strtab));
     printf_filtered (_("  Total memory used for objfile obstack: %d\n"),
 		     obstack_memory_used (&objfile->objfile_obstack));
-    printf_filtered (_("  Total memory used for psymbol cache: %d\n"),
-		     bcache_memory_used (objfile->psymbol_cache));
+    if (objfile->psyms)
+      printf_filtered (_("  Total memory used for psymbol cache: %d\n"),
+		       bcache_memory_used (objfile->psyms->psymbol_cache));
     printf_filtered (_("  Total memory used for macro cache: %d\n"),
 		     bcache_memory_used (objfile->macro_cache));
     printf_filtered (_("  Total memory used for file name cache: %d\n"),
diff --git a/gdb/symtab.c b/gdb/symtab.c
index cada00e..6405fb0 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -507,7 +507,7 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 void
 symbol_set_names (struct general_symbol_info *gsymbol,
 		  const char *linkage_name, int len, int copy_name,
-		  struct objfile *objfile)
+		  struct objfile *objfile, struct obstack *obstack)
 {
   struct demangled_name_entry **slot;
   /* A 0-terminated copy of the linkage name.  */
@@ -533,7 +533,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
 	gsymbol->name = (char *) linkage_name;
       else
 	{
-	  gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
+	  gsymbol->name = obstack_alloc (obstack, len + 1);
 	  memcpy (gsymbol->name, linkage_name, len);
 	  gsymbol->name[len] = '\0';
 	}
@@ -603,7 +603,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
 	 us better bcache hit rates for partial symbols.  */
       if (!copy_name && lookup_name == linkage_name)
 	{
-	  *slot = obstack_alloc (&objfile->objfile_obstack,
+	  *slot = obstack_alloc (obstack,
 				 offsetof (struct demangled_name_entry,
 					   demangled)
 				 + demangled_len + 1);
@@ -614,7 +614,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
 	  /* If we must copy the mangled name, put it directly after
 	     the demangled name so we can have a single
 	     allocation.  */
-	  *slot = obstack_alloc (&objfile->objfile_obstack,
+	  *slot = obstack_alloc (obstack,
 				 offsetof (struct demangled_name_entry,
 					   demangled)
 				 + lookup_len + demangled_len + 2);
@@ -1593,16 +1593,24 @@ char *
 find_main_filename (void)
 {
   struct objfile *objfile;
-  char *result, *name = main_name ();
+  char *result = NULL, *name = main_name ();
 
   ALL_OBJFILES (objfile)
   {
-    if (!objfile->sf)
+    if ((objfile->flags & OBJF_MAIN) == 0 || !objfile->sf)
       continue;
     result = objfile->sf->qf->find_symbol_file (objfile, name);
     if (result)
       return result;
   }
+
+  ALL_OBJFILES (objfile)
+  {
+    if (objfile->sf)
+      result = objfile->sf->qf->find_symbol_file (objfile, name);
+    if (result)
+      return result;
+  }
   return (NULL);
 }
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 5b109ce..3c175e9 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -190,10 +190,14 @@ extern void symbol_init_language_specific (struct general_symbol_info *symbol,
 /* Set the linkage and natural names of a symbol, by demangling
    the linkage name.  */
 #define SYMBOL_SET_NAMES(symbol,linkage_name,len,copy_name,objfile)	\
-  symbol_set_names (&(symbol)->ginfo, linkage_name, len, copy_name, objfile)
+  symbol_set_names (&(symbol)->ginfo, linkage_name, len, copy_name, objfile, \
+		    &objfile->objfile_obstack)
+#define SYMBOL_SET_NAMES_FULL(symbol,linkage_name,len,copy_name,objfile,obstack) \
+  symbol_set_names (&(symbol)->ginfo, linkage_name, len, copy_name, objfile, obstack)
 extern void symbol_set_names (struct general_symbol_info *symbol,
 			      const char *linkage_name, int len, int copy_name,
-			      struct objfile *objfile);
+			      struct objfile *objfile,
+			      struct obstack *obstack);
 
 /* Now come lots of name accessor macros.  Short version as to when to
    use which: Use SYMBOL_NATURAL_NAME to refer to the name of the
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index aa6d27e..b07170e 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -1943,10 +1943,6 @@ init_stringtab (bfd *abfd, file_ptr offset, struct objfile *objfile)
    for the psymtab.  */
 static unsigned int first_fun_line_offset;
 
-static struct partial_symtab *xcoff_start_psymtab
-  (struct objfile *, char *, int,
-   struct partial_symbol **, struct partial_symbol **);
-
 /* Allocate and partially fill a partial symtab.  It will be
    completely filled at the end of the symbol list.
 
@@ -1955,16 +1951,13 @@ static struct partial_symtab *xcoff_start_psymtab
    (normal). */
 
 static struct partial_symtab *
-xcoff_start_psymtab (struct objfile *objfile, char *filename, int first_symnum,
-		     struct partial_symbol **global_syms,
-		     struct partial_symbol **static_syms)
+xcoff_start_psymtab (struct objfile *objfile, char *filename, int first_symnum)
 {
   struct partial_symtab *result =
     start_psymtab_common (objfile, objfile->section_offsets,
 			  filename,
 			  /* We fill in textlow later.  */
-			  0,
-			  global_syms, static_syms);
+			  0);
 
   result->read_symtab_private = obstack_alloc (&objfile->objfile_obstack,
 					       sizeof (struct symloc));
@@ -2005,10 +1998,7 @@ xcoff_end_psymtab (struct partial_symtab *pst, char **include_list,
   ((struct symloc *) pst->read_symtab_private)->lineno_off =
     first_fun_line_offset;
   first_fun_line_offset = 0;
-  pst->n_global_syms =
-    objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset);
-  pst->n_static_syms =
-    objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset);
+  finalize_psymtab (objfile->psyms, pst);
 
   pst->number_of_dependencies = number_dependencies;
   if (number_dependencies)
@@ -2053,7 +2043,7 @@ xcoff_end_psymtab (struct partial_symtab *pst, char **include_list,
       subpst->read_symtab = pst->read_symtab;
     }
 
-  sort_pst_symbols (pst);
+  sort_pst_symbols (objfile->psyms, pst);
 
   if (num_includes == 0
       && number_dependencies == 0
@@ -2065,7 +2055,7 @@ xcoff_end_psymtab (struct partial_symtab *pst, char **include_list,
       /* Empty psymtabs happen as a result of header files which don't have
          any symbols in them.  There can be a lot of them.  */
 
-      discard_psymtab (pst);
+      discard_psymtab (pst->objfile->psyms, pst);
 
       /* Indicate that psymtab was thrown away.  */
       pst = (struct partial_symtab *) NULL;
@@ -2270,9 +2260,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 			    pst = xcoff_start_psymtab
 			      (objfile,
 			       filestring,
-			       symnum_before,
-			       objfile->global_psymbols.next,
-			       objfile->static_psymbols.next);
+			       symnum_before);
 			  }
 		      }
 		    /* Activate the misc_func_recorded mechanism for
@@ -2455,9 +2443,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 
 	    pst = xcoff_start_psymtab (objfile,
 				       filestring,
-				       symnum_before,
-				       objfile->global_psymbols.next,
-				       objfile->static_psymbols.next);
+				       symnum_before);
 	    last_csect_name = NULL;
 	  }
 	  break;
@@ -2616,7 +2602,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 
 		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_STATIC,
-				     &objfile->static_psymbols,
+				     0,
 				     0, symbol.n_value,
 				     psymtab_language, objfile);
 		continue;
@@ -2627,7 +2613,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		   wrong.  See the code that reads 'G's for symtabs. */
 		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_STATIC,
-				     &objfile->global_psymbols,
+				     1,
 				     0, symbol.n_value,
 				     psymtab_language, objfile);
 		continue;
@@ -2645,7 +2631,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		  {
 		    add_psymbol_to_list (namestring, p - namestring, 1,
 					 STRUCT_DOMAIN, LOC_TYPEDEF,
-					 &objfile->static_psymbols,
+					 0,
 					 symbol.n_value, 0,
 					 psymtab_language, objfile);
 		    if (p[2] == 't')
@@ -2653,7 +2639,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 			/* Also a typedef with the same name.  */
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_TYPEDEF,
-					     &objfile->static_psymbols,
+					     0,
 					     symbol.n_value, 0,
 					     psymtab_language, objfile);
 			p += 1;
@@ -2666,7 +2652,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		  {
 		    add_psymbol_to_list (namestring, p - namestring, 1,
 					 VAR_DOMAIN, LOC_TYPEDEF,
-					 &objfile->static_psymbols,
+					 0,
 					 symbol.n_value, 0,
 					 psymtab_language, objfile);
 		  }
@@ -2728,7 +2714,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 			   enum constants in psymtabs, just in symtabs.  */
 			add_psymbol_to_list (p, q - p, 1,
 					     VAR_DOMAIN, LOC_CONST,
-					     &objfile->static_psymbols, 0,
+					     0, 0,
 					     0, psymtab_language, objfile);
 			/* Point past the name.  */
 			p = q;
@@ -2746,7 +2732,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		/* Constant, e.g. from "const" in Pascal.  */
 		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_CONST,
-				     &objfile->static_psymbols, symbol.n_value,
+				     0, symbol.n_value,
 				     0, psymtab_language, objfile);
 		continue;
 
@@ -2764,7 +2750,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_BLOCK,
-				     &objfile->static_psymbols,
+				     0,
 				     0, symbol.n_value,
 				     psymtab_language, objfile);
 		continue;
@@ -2794,7 +2780,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_BLOCK,
-				     &objfile->global_psymbols,
+				     1,
 				     0, symbol.n_value,
 				     psymtab_language, objfile);
 		continue;
@@ -2956,14 +2942,6 @@ xcoff_initial_scan (struct objfile *objfile, int symfile_flags)
   if (val != size)
     perror_with_name (_("reading symbol table"));
 
-  /* If we are reinitializing, or if we have never loaded syms yet, init */
-  if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)
-    /* I'm not sure how how good num_symbols is; the rule of thumb in
-       init_psymbol_list was developed for a.out.  On the one hand,
-       num_symbols includes auxents.  On the other hand, it doesn't
-       include N_SLINE.  */
-    init_psymbol_list (objfile, num_symbols);
-
   free_pending_blocks ();
   back_to = make_cleanup (really_free_pendings, 0);
 
@@ -3045,6 +3023,7 @@ static struct sym_fns xcoff_sym_fns =
   xcoff_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   xcoff_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   xcoff_initial_scan,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   xcoff_symfile_finish,		/* sym_finish: finished with file, cleanup */
   xcoff_symfile_offsets,	/* sym_offsets: xlate offsets ext->int form */
   default_symfile_segments,	/* sym_segments: Get segment information from
-- 
1.6.2.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]