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]

[1/4] RFC: refactor partial symbol tables


This patch does the bulk of the work.

I went through gdb and looked at all uses of partial symbol tables.  I
moved all the psymtab code into a new file, and changed all the code in
gdb to call via a new struct of function pointers.

Mostly this was straightforward.  The only surprise that I can remember
was that Ada walks the psymtabs directly.

Now, symbol readers are allowed to include psympriv.h and access partial
symbol tables.  However, generic code should not do this.  This ensures
that partial symbol tables don't leak out into the main part of gdb.

The new "quick" function API is entirely ad hoc, based on existing gdb
code.  I consolidated functions in a few places, but perhaps more could
be done here.

Tom

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

	* xcoffread.c: Include psymtab.h.
	(xcoff_sym_fns): Update.
	* symtab.h (struct partial_symbol): Remove.
	(PSYMBOL_DOMAIN, PSYMBOL_CLASS): Remove.
	(struct partial_symtab): Remove.
	(PSYMTAB_TO_SYMTAB): Remove.
	(lookup_partial_symbol, lookup_partial_symtab, find_pc_psymtab)
	(find_pc_sect_psymtab): Remove.
	(find_pc_sect_symtab_via_partial): Declare.
	(find_pc_psymtab, find_pc_sect_psymbol, psymtab_to_symtab)
	(find_main_psymtab): Remove.
	(find_main_filename): Declare.
	(fixup_psymbol_section): Remove.
	(fixup_section): Declare.
	* symtab.c: Include psymtab.h.
	(lookup_symtab): Use lookup_symtab method.
	(lookup_partial_symtab): Remove.
	(find_pc_sect_psymtab_closer): Remove.
	(find_pc_sect_psymtab): Remove.
	(find_pc_sect_symtab_via_partial): New function.
	(find_pc_psymtab, find_pc_sect_psymbol, find_pc_psymbol): Remove.
	(fixup_section): No longer static.
	(fixup_psymbol_section): Remove.
	(lookup_symbol_aux): Use lookup_symbol_aux_quick.
	(lookup_global_symbol_from_objfile): Likewise.
	(lookup_symbol_aux_psymtabs): Remove.
	(lookup_symbol_aux_quick): New function.
	(lookup_symbol_global): Use lookup_symbol_aux_quick.
	(lookup_partial_symbol): Remove.
	(basic_lookup_transparent_type_quick): New function.
	(basic_lookup_transparent_type): Use it.
	(find_main_psymtab): Remove.
	(find_main_filename): New function.
	(find_pc_sect_symtab): Use find_pc_sect_symtab method.
	(find_line_symtab): Use expand_symtabs_with_filename method.
	(output_partial_symbol_filename): New function.
	(sources_info): Use map_partial_symbol_filenames.
	(struct search_symbols_data): New type.
	(search_symbols_file_matches): New function.
	(search_symbols_name_matches): Likewise.
	(search_symbols): Use expand_symtabs_matching method.
	(struct add_name_data): Rename from add_macro_name_data.
	(add_macro_name): Update.
	(add_partial_symbol_name): New function.
	(default_make_symbol_completion_list): Use
	map_partial_symbol_names.
	(struct add_partial_symbol_name): New type.
	(maybe_add_partial_symtab_filename): New function.
	(make_source_files_completion_list): Use
	map_partial_symbol_filenames.
	(expand_line_sal): Use expand_symtabs_with_filename method.
	* symmisc.c: Include psymtab.h.
	(print_objfile_statistics): Use print_stats method.
	(dump_objfile): Use dump method.
	(dump_psymtab, maintenance_print_psymbols)
	(maintenance_info_psymtabs, maintenance_check_symtabs)
	(extend_psymbol_list): Remove.
	* symfile.h (struct quick_symbol_functions): New struct.
	(struct sym_fns) <qf>: New field.
	(sort_pst_symbols): Remove.
	(increment_reading_symtab): Declare.
	* symfile.c: Include psymtab.h.
	(compare_psymbols, sort_pst_symbols): Remove.
	(psymtab_to_symtab): Remove.
	(increment_reading_symtab): New function.
	(symbol_file_add_with_addrs_or_offsets): Use expand_all_symtabs
	method.
	(set_initial_language): Use find_main_filename.
	(allocate_psymtab, discard_psymtab, cashier_psymtab): Remove.
	(free_named_symtabs): Remove unused code.
	(start_psymtab_common, add_psymbol_to_bcache)
	(append_psymbol_to_list, add_psymbol_to_list, init_psymbol_list):
	Remove.
	* stack.c: Include psymtab.h, symfile.h.
	(backtrace_command_1): Use find_pc_sect_symtab_via_partial.
	* source.h (psymtab_to_fullname): Don't declare.
	* source.c: Include psymtab.h.
	(select_source_symtab): Use find_last_source_symtab method.
	(forget_cached_source_info): Use forget_cached_source_info
	method.
	(find_and_open_source): No longer static.
	(psymtab_to_fullname): Remove.
	* somread.c: Include psymtab.h.
	(som_sym_fns): Update.
	* psympriv.h: New file.
	* psymtab.h: New file.
	* psymtab.c: New file.
	* objfiles.h: (ALL_OBJFILE_PSYMTABS): Remove.
	(ALL_PSYMTABS, ALL_PSPACE_PSYMTABS): Likewise.
	* objfiles.c: Include psymtab.h.
	(objfile_relocate1): Use relocate method.
	(objfile_has_partial_symbols): Use has_symbols method.
	* mipsread.c: Include psymtab.h.
	(ecoff_sym_fns): Update.
	* mi/mi-cmd-file.c: Include psymtab.h.
	(print_partial_file_name): New function.
	(mi_cmd_file_list_exec_source_files): Use
	map_partial_symbol_filenames.
	* mdebugread.c: Include psympriv.h.
	* machoread.c: Include psympriv.h.
	(macho_sym_fns): Update.
	* m2-exp.y (yylex): Use lookup_symtab.
	* elfread.c: Include psympriv.h.
	(elf_sym_fns): Update.
	* dwarf2read.c: Include psympriv.h.
	* dbxread.c: Include psympriv.h.
	(aout_sym_fns): Update.
	* cp-support.c: Include psymtab.h.
	(read_in_psymtabs): Remove.
	(make_symbol_overload_list_qualified): Use
	expand_symtabs_for_function method.
	* coffread.c: Include psympriv.h.
	(coff_sym_fns): Update.
	* blockframe.c: Include psymtab.h.
	(find_pc_partial_function): Use find_pc_sect_symtab method.
	* ada-lang.h (ada_update_initial_language): Update.
	* ada-lang.c: Include psymtab.h.
	(ada_update_initial_language): Remove 'main_pst' argument.
	(ada_lookup_partial_symbol): Remove.
	(struct ada_psym_data): New type.
	(ada_add_psyms): New function.
	(ada_add_non_local_symbols): Use map_ada_symtabs method.
	(struct add_partial_datum): New type.
	(ada_add_partial_symbol_completions): New function.
	(ada_make_symbol_completion_list): Use map_partial_symbol_names.
	(ada_exception_support_info_sniffer): Update.
	* Makefile.in (SFILES): Add psymtab.c.
	(COMMON_OBS): Add psymtab.o.
	(HFILES_NO_SRCDIR): Add psymtab.h, psympriv.h.

>From 17126e2a21134f7286f9233f9a8955e8ecc4c1a2 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Thu, 14 Jan 2010 11:14:57 -0700
Subject: [PATCH 1/4] move psymtab code to new file

---
 gdb/ChangeLog        |  133 ++++
 gdb/Makefile.in      |    7 +-
 gdb/ada-lang.c       |  263 +++------
 gdb/ada-lang.h       |    4 +-
 gdb/blockframe.c     |   74 +--
 gdb/coffread.c       |    3 +
 gdb/cp-support.c     |   32 +-
 gdb/dbxread.c        |    4 +-
 gdb/dwarf2read.c     |    1 +
 gdb/elfread.c        |    2 +
 gdb/m2-exp.y         |    2 +-
 gdb/machoread.c      |    3 +
 gdb/mdebugread.c     |    1 +
 gdb/mi/mi-cmd-file.c |   35 +-
 gdb/mipsread.c       |    3 +
 gdb/objfiles.c       |   37 +-
 gdb/objfiles.h       |   16 -
 gdb/psympriv.h       |  166 +++++
 gdb/psymtab.c        | 1766 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/psymtab.h        |   31 +
 gdb/somread.c        |    2 +
 gdb/source.c         |   77 +--
 gdb/source.h         |    1 -
 gdb/stack.c          |    9 +-
 gdb/symfile.c        |  459 +-------------
 gdb/symfile.h        |  170 +++++-
 gdb/symmisc.c        |  464 +-------------
 gdb/symtab.c         | 1065 +++++++++---------------------
 gdb/symtab.h         |  177 +-----
 gdb/xcoffread.c      |    2 +
 30 files changed, 2790 insertions(+), 2219 deletions(-)
 create mode 100644 gdb/psympriv.h
 create mode 100644 gdb/psymtab.c
 create mode 100644 gdb/psymtab.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 31a0f76..d83466b 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -664,7 +664,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	objfiles.c osabi.c observer.c osdata.c \
 	p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
 	progspace.c \
-	prologue-value.c \
+	prologue-value.c psymtab.c \
 	regcache.c reggroups.c remote.c remote-fileio.c reverse.c \
 	scm-exp.c scm-lang.c scm-valprint.c \
 	sentinel-frame.c \
@@ -754,7 +754,8 @@ config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \
 annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h	\
 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
 sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \
-gdb_usleep.h jit.h xml-syscall.h ada-operator.inc microblaze-tdep.h
+gdb_usleep.h jit.h xml-syscall.h ada-operator.inc microblaze-tdep.h \
+psymtab.h psympriv.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -791,7 +792,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	blockframe.o breakpoint.o findvar.o regcache.o \
 	charset.o disasm.o dummy-frame.o dfp.o \
 	source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
-	block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o \
+	block.o symtab.o psymtab.o symfile.o symmisc.o linespec.o dictionary.o \
 	infcall.o \
 	infcmd.o infrun.o \
 	expprint.o environ.o stack.o thread.o \
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 24def95..905b495 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -57,6 +57,8 @@
 #include "observer.h"
 #include "vec.h"
 
+#include "psymtab.h"
+
 /* Define whether or not the C operator '/' truncates towards zero for
    differently signed operands (truncation direction is undefined in C). 
    Copied from valarith.c.  */
@@ -637,13 +639,10 @@ base_type (struct type *type)
                                 /* Language Selection */
 
 /* If the main program is in Ada, return language_ada, otherwise return LANG
-   (the main program is in Ada iif the adainit symbol is found).
-
-   MAIN_PST is not used.  */
+   (the main program is in Ada iif the adainit symbol is found).  */
 
 enum language
-ada_update_initial_language (enum language lang,
-                             struct partial_symtab *main_pst)
+ada_update_initial_language (enum language lang)
 {
   if (lookup_minimal_symbol ("adainit", (const char *) NULL,
                              (struct objfile *) NULL) != NULL)
@@ -4095,143 +4094,6 @@ defns_collected (struct obstack *obstackp, int finish)
     return (struct ada_symbol_info *) obstack_base (obstackp);
 }
 
-/* Look, in partial_symtab PST, for symbol NAME in given namespace.
-   Check the global symbols if GLOBAL, the static symbols if not.
-   Do wild-card match if WILD.  */
-
-static struct partial_symbol *
-ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name,
-                           int global, domain_enum namespace, int wild)
-{
-  struct partial_symbol **start;
-  int name_len = strlen (name);
-  int length = (global ? pst->n_global_syms : pst->n_static_syms);
-  int i;
-
-  if (length == 0)
-    {
-      return (NULL);
-    }
-
-  start = (global ?
-           pst->objfile->global_psymbols.list + pst->globals_offset :
-           pst->objfile->static_psymbols.list + pst->statics_offset);
-
-  if (wild)
-    {
-      for (i = 0; i < length; i += 1)
-        {
-          struct partial_symbol *psym = start[i];
-
-          if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
-                                     SYMBOL_DOMAIN (psym), namespace)
-              && wild_match (name, name_len, SYMBOL_LINKAGE_NAME (psym)))
-            return psym;
-        }
-      return NULL;
-    }
-  else
-    {
-      if (global)
-        {
-          int U;
-          i = 0;
-          U = length - 1;
-          while (U - i > 4)
-            {
-              int M = (U + i) >> 1;
-              struct partial_symbol *psym = start[M];
-              if (SYMBOL_LINKAGE_NAME (psym)[0] < name[0])
-                i = M + 1;
-              else if (SYMBOL_LINKAGE_NAME (psym)[0] > name[0])
-                U = M - 1;
-              else if (strcmp (SYMBOL_LINKAGE_NAME (psym), name) < 0)
-                i = M + 1;
-              else
-                U = M;
-            }
-        }
-      else
-        i = 0;
-
-      while (i < length)
-        {
-          struct partial_symbol *psym = start[i];
-
-          if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
-                                     SYMBOL_DOMAIN (psym), namespace))
-            {
-              int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym), name_len);
-
-              if (cmp < 0)
-                {
-                  if (global)
-                    break;
-                }
-              else if (cmp == 0
-                       && is_name_suffix (SYMBOL_LINKAGE_NAME (psym)
-                                          + name_len))
-                return psym;
-            }
-          i += 1;
-        }
-
-      if (global)
-        {
-          int U;
-          i = 0;
-          U = length - 1;
-          while (U - i > 4)
-            {
-              int M = (U + i) >> 1;
-              struct partial_symbol *psym = start[M];
-              if (SYMBOL_LINKAGE_NAME (psym)[0] < '_')
-                i = M + 1;
-              else if (SYMBOL_LINKAGE_NAME (psym)[0] > '_')
-                U = M - 1;
-              else if (strcmp (SYMBOL_LINKAGE_NAME (psym), "_ada_") < 0)
-                i = M + 1;
-              else
-                U = M;
-            }
-        }
-      else
-        i = 0;
-
-      while (i < length)
-        {
-          struct partial_symbol *psym = start[i];
-
-          if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
-                                     SYMBOL_DOMAIN (psym), namespace))
-            {
-              int cmp;
-
-              cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (psym)[0];
-              if (cmp == 0)
-                {
-                  cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (psym), 5);
-                  if (cmp == 0)
-                    cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym) + 5,
-                                   name_len);
-                }
-
-              if (cmp < 0)
-                {
-                  if (global)
-                    break;
-                }
-              else if (cmp == 0
-                       && is_name_suffix (SYMBOL_LINKAGE_NAME (psym)
-                                          + name_len + 5))
-                return psym;
-            }
-          i += 1;
-        }
-    }
-  return NULL;
-}
-
 /* Return a minimal symbol matching NAME according to Ada decoding
    rules.  Returns NULL if there is no such minimal symbol.  Names 
    prefixed with "standard__" are handled specially: "standard__" is 
@@ -4610,6 +4472,30 @@ ada_add_local_symbols (struct obstack *obstackp, const char *name,
     add_symbols_from_enclosing_procs (obstackp, name, domain, wild_match);
 }
 
+/* An object of this type is used as the user_data argument when
+   calling the map_ada_symtabs method.  */
+
+struct ada_psym_data
+{
+  struct obstack *obstackp;
+  const char *name;
+  domain_enum domain;
+  int global;
+  int wild_match;
+};
+
+/* Callback function for map_ada_symtabs.  */
+
+static void
+ada_add_psyms (struct objfile *objfile, struct symtab *s, void *user_data)
+{
+  struct ada_psym_data *data = user_data;
+  const int block_kind = data->global ? GLOBAL_BLOCK : STATIC_BLOCK;
+  ada_add_block_symbols (data->obstackp,
+			 BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), block_kind),
+			 data->name, data->domain, objfile, data->wild_match);
+}
+
 /* Add to OBSTACKP all non-local symbols whose name and domain match
    NAME and DOMAIN respectively.  The search is performed on GLOBAL_BLOCK
    symbols if GLOBAL is non-zero, or on STATIC_BLOCK symbols otherwise.  */
@@ -4617,26 +4503,24 @@ ada_add_local_symbols (struct obstack *obstackp, const char *name,
 static void
 ada_add_non_local_symbols (struct obstack *obstackp, const char *name,
                            domain_enum domain, int global,
-                           int wild_match)
+                           int is_wild_match)
 {
   struct objfile *objfile;
-  struct partial_symtab *ps;
+  struct ada_psym_data data;
 
-  ALL_PSYMTABS (objfile, ps)
-  {
-    QUIT;
-    if (ps->readin
-        || ada_lookup_partial_symbol (ps, name, global, domain, wild_match))
-      {
-        struct symtab *s = PSYMTAB_TO_SYMTAB (ps);
-        const int block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
+  data.obstackp = obstackp;
+  data.name = name;
+  data.domain = domain;
+  data.global = global;
+  data.wild_match = is_wild_match;
 
-        if (s == NULL || !s->primary)
-          continue;
-        ada_add_block_symbols (obstackp,
-                               BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), block_kind),
-                               name, domain, objfile, wild_match);
-      }
+  ALL_OBJFILES (objfile)
+  {
+    if (objfile->sf)
+      objfile->sf->qf->map_ada_symtabs (objfile, wild_match, is_name_suffix,
+					ada_add_psyms, name,
+					global, domain,
+					is_wild_match, &data);
   }
 }
 
@@ -5257,6 +5141,29 @@ symbol_completion_add (VEC(char_ptr) **sv,
   VEC_safe_push (char_ptr, *sv, completion);
 }
 
+/* An object of this type is passed as the user_data argument to the
+   map_partial_symbol_names method.  */
+struct add_partial_datum
+{
+  VEC(char_ptr) **completions;
+  char *text;
+  int text_len;
+  char *text0;
+  char *word;
+  int wild_match;
+  int encoded;
+};
+
+/* A callback for map_partial_symbol_names.  */
+static void
+ada_add_partial_symbol_completions (const char *name, void *user_data)
+{
+  struct add_partial_datum *data = user_data;
+  symbol_completion_add (data->completions, name,
+			 data->text, data->text_len, data->text0, data->word,
+			 data->wild_match, data->encoded);
+}
+
 /* Return a list of possible symbol names completing TEXT0.  The list
    is NULL terminated.  WORD is the entire command on which completion
    is made.  */
@@ -5271,7 +5178,6 @@ ada_make_symbol_completion_list (char *text0, char *word)
   VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
   struct symbol *sym;
   struct symtab *s;
-  struct partial_symtab *ps;
   struct minimal_symbol *msymbol;
   struct objfile *objfile;
   struct block *b, *surrounding_static_block = 0;
@@ -5303,34 +5209,17 @@ ada_make_symbol_completion_list (char *text0, char *word)
     }
 
   /* First, look at the partial symtab symbols.  */
-  ALL_PSYMTABS (objfile, ps)
   {
-    struct partial_symbol **psym;
-
-    /* If the psymtab's been read in we'll get it when we search
-       through the blockvector.  */
-    if (ps->readin)
-      continue;
-
-    for (psym = objfile->global_psymbols.list + ps->globals_offset;
-         psym < (objfile->global_psymbols.list + ps->globals_offset
-                 + ps->n_global_syms); psym++)
-      {
-        QUIT;
-        symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (*psym),
-                               text, text_len, text0, word,
-                               wild_match, encoded);
-      }
-
-    for (psym = objfile->static_psymbols.list + ps->statics_offset;
-         psym < (objfile->static_psymbols.list + ps->statics_offset
-                 + ps->n_static_syms); psym++)
-      {
-        QUIT;
-        symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (*psym),
-                               text, text_len, text0, word,
-                               wild_match, encoded);
-      }
+    struct add_partial_datum data;
+
+    data.completions = &completions;
+    data.text = text;
+    data.text_len = text_len;
+    data.text0 = text0;
+    data.word = word;
+    data.wild_match = wild_match;
+    data.encoded = encoded;
+    map_partial_symbol_names (ada_add_partial_symbol_completions, &data);
   }
 
   /* At this point scan through the misc symbol vectors and add each
@@ -10111,7 +10000,7 @@ ada_exception_support_info_sniffer (void)
      started yet.  Inform the user of these two possible causes if
      applicable.  */
 
-  if (ada_update_initial_language (language_unknown, NULL) != language_ada)
+  if (ada_update_initial_language (language_unknown) != language_ada)
     error (_("Unable to insert catchpoint.  Is this an Ada main program?"));
 
   /* If the symbol does not exist, then check that the program is
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index 5568ed0..f8e0180 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -21,7 +21,6 @@
 #if !defined (ADA_LANG_H)
 #define ADA_LANG_H 1
 
-struct partial_symbol;
 struct frame_info;
 
 #include "value.h"
@@ -207,8 +206,7 @@ extern char *ada_decode_symbol (const struct general_symbol_info*);
 
 extern const char *ada_decode (const char*);
 
-extern enum language ada_update_initial_language (enum language, 
-						  struct partial_symtab*);
+extern enum language ada_update_initial_language (enum language);
 
 extern void clear_ada_sym_cache (void);
 
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
index d8efa7b..30f2a32 100644
--- a/gdb/blockframe.c
+++ b/gdb/blockframe.c
@@ -37,6 +37,7 @@
 #include "gdbcmd.h"
 #include "block.h"
 #include "inline-frame.h"
+#include "psymtab.h"
 
 /* Return the innermost lexical block in execution
    in a specified stack frame.  The frame address is assumed valid.
@@ -188,10 +189,10 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
 			  CORE_ADDR *endaddr)
 {
   struct obj_section *section;
-  struct partial_symtab *pst;
   struct symbol *f;
   struct minimal_symbol *msymbol;
-  struct partial_symbol *psb;
+  struct symtab *symtab = NULL;
+  struct objfile *objfile;
   int i;
   CORE_ADDR mapped_pc;
 
@@ -212,55 +213,30 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
     goto return_cached_value;
 
   msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section);
-  pst = find_pc_sect_psymtab (mapped_pc, section);
-  if (pst)
+  ALL_OBJFILES (objfile)
+  {
+    if (objfile->sf)
+      symtab = objfile->sf->qf->find_pc_sect_symtab (objfile, msymbol,
+						     mapped_pc, section, 0);
+    if (symtab)
+      break;
+  }
+
+  if (symtab)
     {
-      /* Need to read the symbols to get a good value for the end address.  */
-      if (endaddr != NULL && !pst->readin)
+      /* Checking whether the msymbol has a larger value is for the
+	 "pathological" case mentioned in print_frame_info.  */
+      f = find_pc_sect_function (mapped_pc, section);
+      if (f != NULL
+	  && (msymbol == NULL
+	      || (BLOCK_START (SYMBOL_BLOCK_VALUE (f))
+		  >= SYMBOL_VALUE_ADDRESS (msymbol))))
 	{
-	  /* Need to get the terminal in case symbol-reading produces
-	     output.  */
-	  target_terminal_ours_for_output ();
-	  PSYMTAB_TO_SYMTAB (pst);
-	}
-
-      if (pst->readin)
-	{
-	  /* Checking whether the msymbol has a larger value is for the
-	     "pathological" case mentioned in print_frame_info.  */
-	  f = find_pc_sect_function (mapped_pc, section);
-	  if (f != NULL
-	      && (msymbol == NULL
-		  || (BLOCK_START (SYMBOL_BLOCK_VALUE (f))
-		      >= SYMBOL_VALUE_ADDRESS (msymbol))))
-	    {
-	      cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
-	      cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
-	      cache_pc_function_name = SYMBOL_LINKAGE_NAME (f);
-	      cache_pc_function_section = section;
-	      goto return_cached_value;
-	    }
-	}
-      else
-	{
-	  /* Now that static symbols go in the minimal symbol table, perhaps
-	     we could just ignore the partial symbols.  But at least for now
-	     we use the partial or minimal symbol, whichever is larger.  */
-	  psb = find_pc_sect_psymbol (pst, mapped_pc, section);
-
-	  if (psb
-	      && (msymbol == NULL
-		  || (SYMBOL_VALUE_ADDRESS (psb)
-		      >= SYMBOL_VALUE_ADDRESS (msymbol))))
-	    {
-	      /* This case isn't being cached currently. */
-	      if (address)
-		*address = SYMBOL_VALUE_ADDRESS (psb);
-	      if (name)
-		*name = SYMBOL_LINKAGE_NAME (psb);
-	      /* endaddr non-NULL can't happen here.  */
-	      return 1;
-	    }
+	  cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
+	  cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
+	  cache_pc_function_name = SYMBOL_LINKAGE_NAME (f);
+	  cache_pc_function_section = section;
+	  goto return_cached_value;
 	}
     }
 
diff --git a/gdb/coffread.c b/gdb/coffread.c
index eca6618..a394fc7 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -45,6 +45,8 @@
 
 #include "coff-pe-read.h"
 
+#include "psymtab.h"
+
 extern void _initialize_coffread (void);
 
 struct coff_symfile_info
@@ -2131,6 +2133,7 @@ static struct sym_fns coff_sym_fns =
   default_symfile_segments,	/* sym_segments: Get segment information from
 				   a file.  */
   NULL,                         /* sym_read_linetable  */
+  &psym_functions,
   NULL				/* next: pointer to next struct sym_fns */
 };
 
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index c31fcff..d43d25f 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -38,6 +38,8 @@
 
 #include "safe-ctype.h"
 
+#include "psymtab.h"
+
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
 
@@ -62,8 +64,6 @@ static void make_symbol_overload_list_using (const char *func_name,
 
 static void make_symbol_overload_list_qualified (const char *func_name);
 
-static void read_in_psymtabs (const char *oload_name);
-
 /* The list of "maint cplus" commands.  */
 
 struct cmd_list_element *maint_cplus_cmd_list = NULL;
@@ -772,7 +772,11 @@ make_symbol_overload_list_qualified (const char *func_name)
   /* Look through the partial symtabs for all symbols which begin
      by matching FUNC_NAME.  Make sure we read that symbol table in. */
 
-  read_in_psymtabs (func_name);
+  ALL_OBJFILES (objfile)
+  {
+    if (objfile->sf)
+      objfile->sf->qf->expand_symtabs_for_function (objfile, func_name);
+  }
 
   /* Search upwards from currently selected frame (so that we can
      complete on local vars.  */
@@ -826,28 +830,6 @@ make_symbol_overload_list_qualified (const char *func_name)
   }
 }
 
-/* Look through the partial symtabs for all symbols which begin
-   by matching FUNC_NAME.  Make sure we read that symbol table in. */
-
-static void
-read_in_psymtabs (const char *func_name)
-{
-  struct partial_symtab *ps;
-  struct objfile *objfile;
-
-  ALL_PSYMTABS (objfile, ps)
-  {
-    if (ps->readin)
-      continue;
-
-    if ((lookup_partial_symbol (ps, func_name, NULL, 1, VAR_DOMAIN)
-	 != NULL)
-	|| (lookup_partial_symbol (ps, func_name, NULL, 0, VAR_DOMAIN)
-	    != NULL))
-      psymtab_to_symtab (ps);
-  }
-}
-
 /* Lookup the rtti type for a class name. */
 
 struct type *
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 816a355..b197294 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -1,6 +1,6 @@
 /* Read dbx symbol tables and convert to internal format, for GDB.
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009.
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010.
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -55,6 +55,7 @@
 #include "complaints.h"
 #include "cp-abi.h"
 #include "cp-support.h"
+#include "psympriv.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
@@ -3576,6 +3577,7 @@ static struct sym_fns aout_sym_fns =
   default_symfile_segments,	/* sym_segments: Get segment information from
 				   a file.  */
   NULL,                         /* sym_read_linetable */
+  &psym_functions,
   NULL				/* next: pointer to next struct sym_fns */
 };
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 243859c..4559b75 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -48,6 +48,7 @@
 #include "gdbcmd.h"
 #include "block.h"
 #include "addrmap.h"
+#include "psympriv.h"
 
 #include <fcntl.h>
 #include "gdb_string.h"
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 78e9163..e21d5c9 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -36,6 +36,7 @@
 #include "gdb-stabs.h"
 #include "complaints.h"
 #include "demangle.h"
+#include "psympriv.h"
 
 extern void _initialize_elfread (void);
 
@@ -1057,6 +1058,7 @@ static struct sym_fns elf_sym_fns =
   elf_symfile_segments,		/* sym_segments: Get segment information from
 				   a file.  */
   NULL,                         /* sym_read_linetable */
+  &psym_functions,
   NULL				/* next: pointer to next struct sym_fns */
 };
 
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
index f93bd5f..38bc7cc 100644
--- a/gdb/m2-exp.y
+++ b/gdb/m2-exp.y
@@ -1022,7 +1022,7 @@ yylex ()
     char *tmp = copy_name (yylval.sval);
     struct symbol *sym;
 
-    if (lookup_partial_symtab (tmp))
+    if (lookup_symtab (tmp))
       return BLOCKNAME;
     sym = lookup_symbol (tmp, expression_context_block, VAR_DOMAIN, 0);
     if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 81f60ec..e1bc9a2 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -32,6 +32,7 @@
 #include "gdb_assert.h"
 #include "aout/stab_gnu.h"
 #include "vec.h"
+#include "psympriv.h"
 
 #include <string.h>
 
@@ -745,6 +746,8 @@ static struct sym_fns macho_sym_fns = {
   macho_symfile_offsets,        /* sym_offsets:  xlate external to internal form */
   default_symfile_segments,	/* sym_segments: Get segment information from
 				   a file.  */
+  NULL,
+  &psym_functions,
   NULL                          /* next: pointer to next struct sym_fns */
 };
 
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 28d52a4..7452d9d 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -57,6 +57,7 @@
 #include "mdebugread.h"
 #include "gdb_stat.h"
 #include "gdb_string.h"
+#include "psympriv.h"
 
 #include "bfd.h"
 
diff --git a/gdb/mi/mi-cmd-file.c b/gdb/mi/mi-cmd-file.c
index 11a9f78..c8f1a3b 100644
--- a/gdb/mi/mi-cmd-file.c
+++ b/gdb/mi/mi-cmd-file.c
@@ -25,6 +25,7 @@
 #include "symtab.h"
 #include "source.h"
 #include "objfiles.h"
+#include "psymtab.h"
 
 /* Return to the client the absolute path and line number of the 
    current file being executed. */
@@ -63,6 +64,21 @@ mi_cmd_file_list_exec_source_file (char *command, char **argv, int argc)
   ui_out_field_int (uiout, "macro-info", st.symtab->macro_table ? 1 : 0);
 }
 
+/* A callback for map_partial_symbol_filenames.  */
+static void
+print_partial_file_name (const char *filename, const char *fullname,
+			 void *ignore)
+{
+  ui_out_begin (uiout, ui_out_type_tuple, NULL);
+
+  ui_out_field_string (uiout, "file", filename);
+
+  if (fullname)
+    ui_out_field_string (uiout, "fullname", fullname);
+
+  ui_out_end (uiout, ui_out_type_tuple);
+}
+
 void
 mi_cmd_file_list_exec_source_files (char *command, char **argv, int argc)
 {
@@ -92,24 +108,7 @@ mi_cmd_file_list_exec_source_files (char *command, char **argv, int argc)
     ui_out_end (uiout, ui_out_type_tuple);
   }
 
-  /* Look at all of the psymtabs */
-  ALL_PSYMTABS (objfile, ps)
-  {
-    if (!ps->readin)
-      {
-	ui_out_begin (uiout, ui_out_type_tuple, NULL);
-
-	ui_out_field_string (uiout, "file", ps->filename);
-
-	/* Extract the fullname if it is not known yet */
-	psymtab_to_fullname (ps);
-
-	if (ps->fullname)
-	  ui_out_field_string (uiout, "fullname", ps->fullname);
-
-	ui_out_end (uiout, ui_out_type_tuple);
-      }
-  }
+  map_partial_symbol_filenames (print_partial_file_name, NULL);
 
   ui_out_end (uiout, ui_out_type_list);
 }
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index 4ef817e..d84fe55 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -42,6 +42,8 @@
 #include "elf/internal.h"
 #include "elf/mips.h"
 
+#include "psymtab.h"
+
 static void
 read_alphacoff_dynamic_symtab (struct section_offsets *,
 			       struct objfile *objfile);
@@ -399,6 +401,7 @@ static struct sym_fns ecoff_sym_fns =
   default_symfile_segments,	/* sym_segments: Get segment information from
 				   a file.  */
   NULL,                         /* sym_read_linetable */
+  &psym_functions,
   NULL				/* next: pointer to next struct sym_fns */
 };
 
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 0b07e37..e06bf05 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -52,6 +52,7 @@
 #include "exec.h"
 #include "observer.h"
 #include "complaints.h"
+#include "psymtab.h"
 
 /* Prototypes for local functions */
 
@@ -779,38 +780,8 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
     addrmap_relocate (objfile->psymtabs_addrmap,
 		      ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
 
-  {
-    struct partial_symtab *p;
-
-    ALL_OBJFILE_PSYMTABS (objfile, p)
-    {
-      p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
-      p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
-    }
-  }
-
-  {
-    struct partial_symbol **psym;
-
-    for (psym = objfile->global_psymbols.list;
-	 psym < objfile->global_psymbols.next;
-	 psym++)
-      {
-	fixup_psymbol_section (*psym, objfile);
-	if (SYMBOL_SECTION (*psym) >= 0)
-	  SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
-						    SYMBOL_SECTION (*psym));
-      }
-    for (psym = objfile->static_psymbols.list;
-	 psym < objfile->static_psymbols.next;
-	 psym++)
-      {
-	fixup_psymbol_section (*psym, objfile);
-	if (SYMBOL_SECTION (*psym) >= 0)
-	  SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
-						    SYMBOL_SECTION (*psym));
-      }
-  }
+  if (objfile->sf)
+    objfile->sf->qf->relocate (objfile, new_offsets, delta);
 
   {
     struct minimal_symbol *msym;
@@ -914,7 +885,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
 int
 objfile_has_partial_symbols (struct objfile *objfile)
 {
-  return objfile->psymtabs != NULL;
+  return objfile->sf ? objfile->sf->qf->has_symbols (objfile) : 0;
 }
 
 /* Return non-zero if OBJFILE has full symbols.  */
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index c689622..df78c6d 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -564,11 +564,6 @@ extern void gdb_bfd_unref (struct bfd *abfd);
 #define	ALL_OBJFILE_SYMTABS(objfile, s) \
     for ((s) = (objfile) -> symtabs; (s) != NULL; (s) = (s) -> next)
 
-/* Traverse all psymtabs in one objfile.  */
-
-#define	ALL_OBJFILE_PSYMTABS(objfile, p) \
-    for ((p) = (objfile) -> psymtabs; (p) != NULL; (p) = (p) -> next)
-
 /* Traverse all minimal symbols in one objfile.  */
 
 #define	ALL_OBJFILE_MSYMBOLS(objfile, m) \
@@ -599,17 +594,6 @@ extern void gdb_bfd_unref (struct bfd *abfd);
     ALL_OBJFILE_SYMTABS (objfile, s)			\
       if ((s)->primary)
 
-/* Traverse all psymtabs in all objfiles in the current symbol
-   space.  */
-
-#define	ALL_PSYMTABS(objfile, p) \
-  ALL_OBJFILES (objfile)	 \
-    ALL_OBJFILE_PSYMTABS (objfile, p)
-
-#define ALL_PSPACE_PSYMTABS(ss, objfile, p)		\
-  ALL_PSPACE_OBJFILES (ss, objfile)			\
-    ALL_OBJFILE_PSYMTABS (objfile, p)
-
 /* Traverse all minimal symbols in all objfiles in the current symbol
    space.  */
 
diff --git a/gdb/psympriv.h b/gdb/psympriv.h
new file mode 100644
index 0000000..42fa427
--- /dev/null
+++ b/gdb/psympriv.h
@@ -0,0 +1,166 @@
+/* Private partial symbol table definitions.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef PSYMPRIV_H
+#define PSYMPRIV_H
+
+#include "psymtab.h"
+
+/* A partial_symbol records the name, domain, and address class of
+   symbols whose types we have not parsed yet.  For functions, it also
+   contains their memory address, so we can find them from a PC value.
+   Each partial_symbol sits in a partial_symtab, all of which are chained
+   on a  partial symtab list and which points to the corresponding 
+   normal symtab once the partial_symtab has been referenced.  */
+
+/* This structure is space critical.  See space comments at the top of
+   symtab.h. */
+
+struct partial_symbol
+{
+
+  /* The general symbol info required for all types of symbols. */
+
+  struct general_symbol_info ginfo;
+
+  /* Name space code.  */
+
+  ENUM_BITFIELD(domain_enum_tag) domain : 6;
+
+  /* Address class (for info_symbols) */
+
+  ENUM_BITFIELD(address_class) aclass : 6;
+
+};
+
+#define PSYMBOL_DOMAIN(psymbol)	(psymbol)->domain
+#define PSYMBOL_CLASS(psymbol)		(psymbol)->aclass
+
+/* Each source file that has not been fully read in is represented by
+   a partial_symtab.  This contains the information on where in the
+   executable the debugging symbols for a specific file are, and a
+   list of names of global symbols which are located in this file.
+   They are all chained on partial symtab lists.
+
+   Even after the source file has been read into a symtab, the
+   partial_symtab remains around.  They are allocated on an obstack,
+   objfile_obstack.  */
+
+struct partial_symtab
+{
+
+  /* Chain of all existing partial symtabs.  */
+
+  struct partial_symtab *next;
+
+  /* Name of the source file which this partial_symtab defines */
+
+  char *filename;
+
+  /* Full path of the source file.  NULL if not known.  */
+
+  char *fullname;
+
+  /* Directory in which it was compiled, or NULL if we don't know.  */
+
+  char *dirname;
+
+  /* Information about the object file from which symbols should be read.  */
+
+  struct objfile *objfile;
+
+  /* Set of relocation offsets to apply to each section.  */
+
+  struct section_offsets *section_offsets;
+
+  /* Range of text addresses covered by this file; texthigh is the
+     beginning of the next section. */
+
+  CORE_ADDR textlow;
+  CORE_ADDR texthigh;
+
+  /* Array of pointers to all of the partial_symtab's which this one
+     depends on.  Since this array can only be set to previous or
+     the current (?) psymtab, this dependency tree is guaranteed not
+     to have any loops.  "depends on" means that symbols must be read
+     for the dependencies before being read for this psymtab; this is
+     for type references in stabs, where if foo.c includes foo.h, declarations
+     in foo.h may use type numbers defined in foo.c.  For other debugging
+     formats there may be no need to use dependencies.  */
+
+  struct partial_symtab **dependencies;
+
+  int number_of_dependencies;
+
+  /* Global symbol list.  This list will be sorted after readin to
+     improve access.  Binary search will be the usual method of
+     finding a symbol within it. globals_offset is an integer offset
+     within global_psymbols[].  */
+
+  int globals_offset;
+  int n_global_syms;
+
+  /* Static symbol list.  This list will *not* be sorted after readin;
+     to find a symbol in it, exhaustive search must be used.  This is
+     reasonable because searches through this list will eventually
+     lead to either the read in of a files symbols for real (assumed
+     to take a *lot* of time; check) or an error (and we don't care
+     how long errors take).  This is an offset and size within
+     static_psymbols[].  */
+
+  int statics_offset;
+  int n_static_syms;
+
+  /* Pointer to symtab eventually allocated for this source file, 0 if
+     !readin or if we haven't looked for the symtab after it was readin.  */
+
+  struct symtab *symtab;
+
+  /* Pointer to function which will read in the symtab corresponding to
+     this psymtab.  */
+
+  void (*read_symtab) (struct partial_symtab *);
+
+  /* Information that lets read_symtab() locate the part of the symbol table
+     that this psymtab corresponds to.  This information is private to the
+     format-dependent symbol reading routines.  For further detail examine
+     the various symbol reading modules.  Should really be (void *) but is
+     (char *) as with other such gdb variables.  (FIXME) */
+
+  char *read_symtab_private;
+
+  /* Non-zero if the symtab corresponding to this psymtab has been readin */
+
+  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)
+
+/* Traverse all psymtabs in all objfiles.  */
+
+#define	ALL_PSYMTABS(objfile, p) \
+  ALL_OBJFILES (objfile)	 \
+    ALL_OBJFILE_PSYMTABS (objfile, p)
+
+#endif /* PSYMPRIV_H */
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
new file mode 100644
index 0000000..7cf888b
--- /dev/null
+++ b/gdb/psymtab.c
@@ -0,0 +1,1766 @@
+/* Partial symbol tables.
+   
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "symtab.h"
+#include "psympriv.h"
+#include "objfiles.h"
+#include "gdb_assert.h"
+#include "block.h"
+#include "filenames.h"
+#include "source.h"
+#include "addrmap.h"
+#include "gdbtypes.h"
+#include "bcache.h"
+#include "ui-out.h"
+#include "command.h"
+#include "readline/readline.h"
+#include "gdb_regex.h"
+
+#ifndef DEV_TTY
+#define DEV_TTY "/dev/tty"
+#endif
+
+/* A fast way to get from a psymtab to its symtab (after the first time).  */
+#define PSYMTAB_TO_SYMTAB(pst)  \
+    ((pst) -> symtab != NULL ? (pst) -> symtab : psymtab_to_symtab (pst))
+
+/* Lookup a partial symbol.  */
+static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
+						     const char *,
+						     const char *, int,
+						     domain_enum);
+
+static char *psymtab_to_fullname (struct partial_symtab *ps);
+
+static struct partial_symbol *find_pc_sect_psymbol (struct partial_symtab *,
+						    CORE_ADDR,
+						    struct obj_section *);
+
+static struct partial_symbol *fixup_psymbol_section (struct partial_symbol
+						     *psym,
+						     struct objfile *objfile);
+
+static struct symtab *psymtab_to_symtab (struct partial_symtab *pst);
+
+/* 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.  */
+
+static struct partial_symtab *
+lookup_partial_symtab (struct objfile *objfile, const char *name,
+		       const char *full_path, const char *real_path)
+{
+  struct partial_symtab *pst;
+
+  ALL_OBJFILE_PSYMTABS (objfile, pst)
+  {
+    if (FILENAME_CMP (name, pst->filename) == 0)
+      {
+	return (pst);
+      }
+
+    /* If the user gave us an absolute path, try to find the file in
+       this symtab and use its absolute path.  */
+    if (full_path != NULL)
+      {
+	psymtab_to_fullname (pst);
+	if (pst->fullname != NULL
+	    && FILENAME_CMP (full_path, pst->fullname) == 0)
+	  {
+	    return pst;
+	  }
+      }
+
+    if (real_path != NULL)
+      {
+        char *rp = NULL;
+	psymtab_to_fullname (pst);
+        if (pst->fullname != NULL)
+          {
+            rp = gdb_realpath (pst->fullname);
+            make_cleanup (xfree, rp);
+          }
+	if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
+	  {
+	    return pst;
+	  }
+      }
+  }
+
+  /* Now, search for a matching tail (only if name doesn't have any dirs) */
+
+  if (lbasename (name) == name)
+    ALL_OBJFILE_PSYMTABS (objfile, pst)
+    {
+      if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
+	return (pst);
+    }
+
+  return (NULL);
+}
+
+static int
+lookup_symtab_via_partial_symtab (struct objfile *objfile, const char *name,
+				  const char *full_path, const char *real_path,
+				  struct symtab **result)
+{
+  struct partial_symtab *ps;
+
+  ps = lookup_partial_symtab (objfile, name, full_path, real_path);
+  if (!ps)
+    return 0;
+
+  if (ps->readin)
+    error (_("Internal: readin %s pst for `%s' found when no symtab found."),
+	   ps->filename, name);
+
+  *result = PSYMTAB_TO_SYMTAB (ps);
+  return 1;
+}
+
+/* Find which partial symtab contains PC and SECTION starting at psymtab PST.
+   We may find a different psymtab than PST.  See FIND_PC_SECT_PSYMTAB.  */
+
+static struct partial_symtab *
+find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section,
+			     struct partial_symtab *pst,
+			     struct minimal_symbol *msymbol)
+{
+  struct objfile *objfile = pst->objfile;
+  struct partial_symtab *tpst;
+  struct partial_symtab *best_pst = pst;
+  CORE_ADDR best_addr = pst->textlow;
+
+  /* An objfile that has its functions reordered might have
+     many partial symbol tables containing the PC, but
+     we want the partial symbol table that contains the
+     function containing the PC.  */
+  if (!(objfile->flags & OBJF_REORDERED) &&
+      section == 0)	/* can't validate section this way */
+    return pst;
+
+  if (msymbol == NULL)
+    return (pst);
+
+  /* The code range of partial symtabs sometimes overlap, so, in
+     the loop below, we need to check all partial symtabs and
+     find the one that fits better for the given PC address. We
+     select the partial symtab that contains a symbol whose
+     address is closest to the PC address.  By closest we mean
+     that find_pc_sect_symbol returns the symbol with address
+     that is closest and still less than the given PC.  */
+  for (tpst = pst; tpst != NULL; tpst = tpst->next)
+    {
+      if (pc >= tpst->textlow && pc < tpst->texthigh)
+	{
+	  struct partial_symbol *p;
+	  CORE_ADDR this_addr;
+
+	  /* NOTE: This assumes that every psymbol has a
+	     corresponding msymbol, which is not necessarily
+	     true; the debug info might be much richer than the
+	     object's symbol table.  */
+	  p = find_pc_sect_psymbol (tpst, pc, section);
+	  if (p != NULL
+	      && SYMBOL_VALUE_ADDRESS (p)
+	      == SYMBOL_VALUE_ADDRESS (msymbol))
+	    return tpst;
+
+	  /* Also accept the textlow value of a psymtab as a
+	     "symbol", to provide some support for partial
+	     symbol tables with line information but no debug
+	     symbols (e.g. those produced by an assembler).  */
+	  if (p != NULL)
+	    this_addr = SYMBOL_VALUE_ADDRESS (p);
+	  else
+	    this_addr = tpst->textlow;
+
+	  /* Check whether it is closer than our current
+	     BEST_ADDR.  Since this symbol address is
+	     necessarily lower or equal to PC, the symbol closer
+	     to PC is the symbol which address is the highest.
+	     This way we return the psymtab which contains such
+	     best match symbol. This can help in cases where the
+	     symbol information/debuginfo is not complete, like
+	     for instance on IRIX6 with gcc, where no debug info
+	     is emitted for statics. (See also the nodebug.exp
+	     testcase.) */
+	  if (this_addr > best_addr)
+	    {
+	      best_addr = this_addr;
+	      best_pst = tpst;
+	    }
+	}
+    }
+  return best_pst;
+}
+
+/* Find which partial symtab contains PC and SECTION.  Return 0 if
+   none.  We return the psymtab that contains a symbol whose address
+   exactly matches PC, or, if we cannot find an exact match, the
+   psymtab that contains a symbol whose address is closest to PC.  */
+static struct partial_symtab *
+find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc,
+		      struct obj_section *section,
+		      struct minimal_symbol *msymbol)
+{
+  struct partial_symtab *pst;
+
+  /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
+     than the later used TEXTLOW/TEXTHIGH one.  */
+
+  if (objfile->psymtabs_addrmap != NULL)
+    {
+      pst = addrmap_find (objfile->psymtabs_addrmap, pc);
+      if (pst != NULL)
+	{
+	  /* FIXME: addrmaps currently do not handle overlayed sections,
+	     so fall back to the non-addrmap case if we're debugging
+	     overlays and the addrmap returned the wrong section.  */
+	  if (overlay_debugging && msymbol && section)
+	    {
+	      struct partial_symbol *p;
+	      /* NOTE: This assumes that every psymbol has a
+		 corresponding msymbol, which is not necessarily
+		 true; the debug info might be much richer than the
+		 object's symbol table.  */
+	      p = find_pc_sect_psymbol (pst, pc, section);
+	      if (!p
+		  || SYMBOL_VALUE_ADDRESS (p)
+		  != SYMBOL_VALUE_ADDRESS (msymbol))
+		goto next;
+	    }
+
+	  /* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as
+	     PSYMTABS_ADDRMAP we used has already the best 1-byte
+	     granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into
+	     a worse chosen section due to the TEXTLOW/TEXTHIGH ranges
+	     overlap.  */
+
+	  return pst;
+	}
+    }
+
+ next:
+
+  /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
+     which still have no corresponding full SYMTABs read.  But it is not
+     present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
+     so far.  */
+
+  /* Check even OBJFILE with non-zero PSYMTABS_ADDRMAP as only several of
+     its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying
+     debug info type in single OBJFILE.  */
+
+  ALL_OBJFILE_PSYMTABS (objfile, pst)
+    if (pc >= pst->textlow && pc < pst->texthigh)
+      {
+	struct partial_symtab *best_pst;
+
+	best_pst = find_pc_sect_psymtab_closer (pc, section, pst, msymbol);
+	if (best_pst != NULL)
+	  return best_pst;
+      }
+
+  return NULL;
+}
+
+static struct symtab *
+find_pc_sect_symtab_from_partial (struct objfile *objfile,
+				  struct minimal_symbol *msymbol,
+				  CORE_ADDR pc, struct obj_section *section,
+				  int warn_if_readin)
+{
+  struct partial_symtab *ps = find_pc_sect_psymtab (objfile, pc, section,
+						    msymbol);
+  if (ps)
+    {
+      if (warn_if_readin && ps->readin)
+	/* Might want to error() here (in case symtab is corrupt and
+	   will cause a core dump), but maybe we can successfully
+	   continue, so let's not.  */
+	warning (_("\
+(Internal error: pc %s in read in psymtab, but not in symtab.)\n"),
+		 paddress (get_objfile_arch (ps->objfile), pc));
+      return PSYMTAB_TO_SYMTAB (ps);
+    }
+  return NULL;
+}
+
+/* Find which partial symbol within a psymtab matches PC and SECTION.
+   Return 0 if none.  */
+
+static struct partial_symbol *
+find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
+		      struct obj_section *section)
+{
+  struct partial_symbol *best = NULL, *p, **pp;
+  CORE_ADDR best_pc;
+
+  gdb_assert (psymtab != NULL);
+
+  /* Cope with programs that start at address 0 */
+  best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0;
+
+  /* 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)
+     < psymtab->n_global_syms);
+       pp++)
+    {
+      p = *pp;
+      if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
+	  && SYMBOL_CLASS (p) == LOC_BLOCK
+	  && pc >= SYMBOL_VALUE_ADDRESS (p)
+	  && (SYMBOL_VALUE_ADDRESS (p) > best_pc
+	      || (psymtab->textlow == 0
+		  && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
+	{
+	  if (section)		/* match on a specific section */
+	    {
+	      fixup_psymbol_section (p, psymtab->objfile);
+	      if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
+		continue;
+	    }
+	  best_pc = SYMBOL_VALUE_ADDRESS (p);
+	  best = p;
+	}
+    }
+
+  for (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
+    (pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
+     < psymtab->n_static_syms);
+       pp++)
+    {
+      p = *pp;
+      if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
+	  && SYMBOL_CLASS (p) == LOC_BLOCK
+	  && pc >= SYMBOL_VALUE_ADDRESS (p)
+	  && (SYMBOL_VALUE_ADDRESS (p) > best_pc
+	      || (psymtab->textlow == 0
+		  && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
+	{
+	  if (section)		/* match on a specific section */
+	    {
+	      fixup_psymbol_section (p, psymtab->objfile);
+	      if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
+		continue;
+	    }
+	  best_pc = SYMBOL_VALUE_ADDRESS (p);
+	  best = p;
+	}
+    }
+
+  return best;
+}
+
+static struct partial_symbol *
+fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
+{
+  CORE_ADDR addr;
+
+  if (!psym)
+    return NULL;
+
+  if (SYMBOL_OBJ_SECTION (psym))
+    return psym;
+
+  gdb_assert (objfile);
+
+  switch (SYMBOL_CLASS (psym))
+    {
+    case LOC_STATIC:
+    case LOC_LABEL:
+    case LOC_BLOCK:
+      addr = SYMBOL_VALUE_ADDRESS (psym);
+      break;
+    default:
+      /* Nothing else will be listed in the minsyms -- no use looking
+	 it up.  */
+      return psym;
+    }
+
+  fixup_section (&psym->ginfo, addr, objfile);
+
+  return psym;
+}
+
+static struct symtab *
+lookup_symbol_aux_psymtabs (struct objfile *objfile,
+			    int block_index, const char *name,
+			    const char *linkage_name,
+			    const domain_enum domain)
+{
+  struct partial_symtab *ps;
+  const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
+
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+  {
+    if (!ps->readin && lookup_partial_symbol (ps, name, linkage_name,
+					      psymtab_index, domain))
+      return PSYMTAB_TO_SYMTAB (ps);
+  }
+
+  return NULL;
+}
+
+/* Look, in partial_symtab PST, for symbol whose natural name is NAME.
+   If LINKAGE_NAME is non-NULL, check in addition that the symbol's
+   linkage name matches it.  Check the global symbols if GLOBAL, the
+   static symbols if not */
+
+static struct partial_symbol *
+lookup_partial_symbol (struct partial_symtab *pst, const char *name,
+		       const char *linkage_name, int global,
+		       domain_enum domain)
+{
+  struct partial_symbol *temp;
+  struct partial_symbol **start, **psym;
+  struct partial_symbol **top, **real_top, **bottom, **center;
+  int length = (global ? pst->n_global_syms : pst->n_static_syms);
+  int do_linear_search = 1;
+
+  if (length == 0)
+    {
+      return (NULL);
+    }
+  start = (global ?
+	   pst->objfile->global_psymbols.list + pst->globals_offset :
+	   pst->objfile->static_psymbols.list + pst->statics_offset);
+
+  if (global)			/* This means we can use a binary search. */
+    {
+      do_linear_search = 0;
+
+      /* Binary search.  This search is guaranteed to end with center
+         pointing at the earliest partial symbol whose name might be
+         correct.  At that point *all* partial symbols with an
+         appropriate name will be checked against the correct
+         domain.  */
+
+      bottom = start;
+      top = start + length - 1;
+      real_top = top;
+      while (top > bottom)
+	{
+	  center = bottom + (top - bottom) / 2;
+	  if (!(center < top))
+	    internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+	  if (!do_linear_search
+	      && (SYMBOL_LANGUAGE (*center) == language_java))
+	    {
+	      do_linear_search = 1;
+	    }
+	  if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0)
+	    {
+	      top = center;
+	    }
+	  else
+	    {
+	      bottom = center + 1;
+	    }
+	}
+      if (!(top == bottom))
+	internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+
+      while (top <= real_top
+	     && (linkage_name != NULL
+		 ? strcmp (SYMBOL_LINKAGE_NAME (*top), linkage_name) == 0
+		 : SYMBOL_MATCHES_SEARCH_NAME (*top,name)))
+	{
+	  if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
+				     SYMBOL_DOMAIN (*top), domain))
+	    return (*top);
+	  top++;
+	}
+    }
+
+  /* Can't use a binary search or else we found during the binary search that
+     we should also do a linear search. */
+
+  if (do_linear_search)
+    {
+      for (psym = start; psym < start + length; psym++)
+	{
+	  if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
+				     SYMBOL_DOMAIN (*psym), domain))
+	    {
+	      if (linkage_name != NULL
+		  ? strcmp (SYMBOL_LINKAGE_NAME (*psym), linkage_name) == 0
+		  : SYMBOL_MATCHES_SEARCH_NAME (*psym, name))
+		{
+		  return (*psym);
+		}
+	    }
+	}
+    }
+
+  return (NULL);
+}
+
+/* Get the symbol table that corresponds to a partial_symtab.
+   This is fast after the first time you do it.  In fact, there
+   is an even faster macro PSYMTAB_TO_SYMTAB that does the fast
+   case inline.  */
+
+static struct symtab *
+psymtab_to_symtab (struct partial_symtab *pst)
+{
+  /* If it's been looked up before, return it. */
+  if (pst->symtab)
+    return pst->symtab;
+
+  /* If it has not yet been read in, read it.  */
+  if (!pst->readin)
+    {
+      struct cleanup *back_to = increment_reading_symtab ();
+      (*pst->read_symtab) (pst);
+      do_cleanups (back_to);
+    }
+
+  return pst->symtab;
+}
+
+static void
+relocate_psymtabs (struct objfile *objfile,
+		   struct section_offsets *new_offsets,
+		   struct section_offsets *delta)
+{
+  struct partial_symbol **psym;
+  struct partial_symtab *p;
+
+  ALL_OBJFILE_PSYMTABS (objfile, p)
+    {
+      p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
+      p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
+    }
+
+  for (psym = objfile->global_psymbols.list;
+       psym < objfile->global_psymbols.next;
+       psym++)
+    {
+      fixup_psymbol_section (*psym, objfile);
+      if (SYMBOL_SECTION (*psym) >= 0)
+	SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
+						  SYMBOL_SECTION (*psym));
+    }
+  for (psym = objfile->static_psymbols.list;
+       psym < objfile->static_psymbols.next;
+       psym++)
+    {
+      fixup_psymbol_section (*psym, objfile);
+      if (SYMBOL_SECTION (*psym) >= 0)
+	SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
+						  SYMBOL_SECTION (*psym));
+    }
+}
+
+static struct symtab *
+find_last_source_symtab_from_partial (struct objfile *ofp)
+{
+  struct symtab *result;
+  struct partial_symtab *ps;
+  struct partial_symtab *cs_pst = 0;
+
+  ALL_OBJFILE_PSYMTABS (ofp, ps)
+    {
+      const char *name = ps->filename;
+      int len = strlen (name);
+      if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
+			|| strcmp (name, "<<C++-namespaces>>") == 0)))
+	cs_pst = ps;
+    }
+
+  if (cs_pst)
+    {
+      if (cs_pst->readin)
+	{
+	  internal_error (__FILE__, __LINE__,
+			  _("select_source_symtab: "
+			  "readin pst found and no symtabs."));
+	}
+      else
+	return PSYMTAB_TO_SYMTAB (cs_pst);
+    }
+  return NULL;
+}
+
+static void
+forget_cached_source_info_partial (struct objfile *objfile)
+{
+  struct partial_symtab *pst;
+
+  ALL_OBJFILE_PSYMTABS (objfile, pst)
+    {
+      if (pst->fullname != NULL)
+	{
+	  xfree (pst->fullname);
+	  pst->fullname = NULL;
+	}
+    }
+}
+
+static void
+print_partial_symbols (struct gdbarch *gdbarch,
+		       struct partial_symbol **p, int count, char *what,
+		       struct ui_file *outfile)
+{
+  fprintf_filtered (outfile, "  %s partial symbols:\n", what);
+  while (count-- > 0)
+    {
+      fprintf_filtered (outfile, "    `%s'", SYMBOL_LINKAGE_NAME (*p));
+      if (SYMBOL_DEMANGLED_NAME (*p) != NULL)
+	{
+	  fprintf_filtered (outfile, "  `%s'", SYMBOL_DEMANGLED_NAME (*p));
+	}
+      fputs_filtered (", ", outfile);
+      switch (SYMBOL_DOMAIN (*p))
+	{
+	case UNDEF_DOMAIN:
+	  fputs_filtered ("undefined domain, ", outfile);
+	  break;
+	case VAR_DOMAIN:
+	  /* This is the usual thing -- don't print it */
+	  break;
+	case STRUCT_DOMAIN:
+	  fputs_filtered ("struct domain, ", outfile);
+	  break;
+	case LABEL_DOMAIN:
+	  fputs_filtered ("label domain, ", outfile);
+	  break;
+	default:
+	  fputs_filtered ("<invalid domain>, ", outfile);
+	  break;
+	}
+      switch (SYMBOL_CLASS (*p))
+	{
+	case LOC_UNDEF:
+	  fputs_filtered ("undefined", outfile);
+	  break;
+	case LOC_CONST:
+	  fputs_filtered ("constant int", outfile);
+	  break;
+	case LOC_STATIC:
+	  fputs_filtered ("static", outfile);
+	  break;
+	case LOC_REGISTER:
+	  fputs_filtered ("register", outfile);
+	  break;
+	case LOC_ARG:
+	  fputs_filtered ("pass by value", outfile);
+	  break;
+	case LOC_REF_ARG:
+	  fputs_filtered ("pass by reference", outfile);
+	  break;
+	case LOC_REGPARM_ADDR:
+	  fputs_filtered ("register address parameter", outfile);
+	  break;
+	case LOC_LOCAL:
+	  fputs_filtered ("stack parameter", outfile);
+	  break;
+	case LOC_TYPEDEF:
+	  fputs_filtered ("type", outfile);
+	  break;
+	case LOC_LABEL:
+	  fputs_filtered ("label", outfile);
+	  break;
+	case LOC_BLOCK:
+	  fputs_filtered ("function", outfile);
+	  break;
+	case LOC_CONST_BYTES:
+	  fputs_filtered ("constant bytes", outfile);
+	  break;
+	case LOC_UNRESOLVED:
+	  fputs_filtered ("unresolved", outfile);
+	  break;
+	case LOC_OPTIMIZED_OUT:
+	  fputs_filtered ("optimized out", outfile);
+	  break;
+	case LOC_COMPUTED:
+	  fputs_filtered ("computed at runtime", outfile);
+	  break;
+	default:
+	  fputs_filtered ("<invalid location>", outfile);
+	  break;
+	}
+      fputs_filtered (", ", outfile);
+      fputs_filtered (paddress (gdbarch, SYMBOL_VALUE_ADDRESS (*p)), outfile);
+      fprintf_filtered (outfile, "\n");
+      p++;
+    }
+}
+
+static void
+dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
+	      struct ui_file *outfile)
+{
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  int i;
+
+  fprintf_filtered (outfile, "\nPartial symtab for source file %s ",
+		    psymtab->filename);
+  fprintf_filtered (outfile, "(object ");
+  gdb_print_host_address (psymtab, outfile);
+  fprintf_filtered (outfile, ")\n\n");
+  fprintf_unfiltered (outfile, "  Read from object file %s (",
+		      objfile->name);
+  gdb_print_host_address (objfile, outfile);
+  fprintf_unfiltered (outfile, ")\n");
+
+  if (psymtab->readin)
+    {
+      fprintf_filtered (outfile,
+			"  Full symtab was read (at ");
+      gdb_print_host_address (psymtab->symtab, outfile);
+      fprintf_filtered (outfile, " by function at ");
+      gdb_print_host_address (psymtab->read_symtab, outfile);
+      fprintf_filtered (outfile, ")\n");
+    }
+
+  fprintf_filtered (outfile, "  Relocate symbols by ");
+  for (i = 0; i < psymtab->objfile->num_sections; ++i)
+    {
+      if (i != 0)
+	fprintf_filtered (outfile, ", ");
+      wrap_here ("    ");
+      fputs_filtered (paddress (gdbarch,
+				ANOFFSET (psymtab->section_offsets, i)),
+		      outfile);
+    }
+  fprintf_filtered (outfile, "\n");
+
+  fprintf_filtered (outfile, "  Symbols cover text addresses ");
+  fputs_filtered (paddress (gdbarch, psymtab->textlow), outfile);
+  fprintf_filtered (outfile, "-");
+  fputs_filtered (paddress (gdbarch, psymtab->texthigh), outfile);
+  fprintf_filtered (outfile, "\n");
+  fprintf_filtered (outfile, "  Depends on %d other partial symtabs.\n",
+		    psymtab->number_of_dependencies);
+  for (i = 0; i < psymtab->number_of_dependencies; i++)
+    {
+      fprintf_filtered (outfile, "    %d ", i);
+      gdb_print_host_address (psymtab->dependencies[i], outfile);
+      fprintf_filtered (outfile, " %s\n",
+			psymtab->dependencies[i]->filename);
+    }
+  if (psymtab->n_global_syms > 0)
+    {
+      print_partial_symbols (gdbarch,
+			     objfile->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
+			     + psymtab->statics_offset,
+			     psymtab->n_static_syms, "Static", outfile);
+    }
+  fprintf_filtered (outfile, "\n");
+}
+
+static void
+print_psymtab_stats_for_objfile (struct objfile *objfile)
+{
+  int i;
+  struct partial_symtab *ps;
+  i = 0;
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+    {
+      if (ps->readin == 0)
+	i++;
+    }
+  printf_filtered (_("  Number of psym tables (not yet expanded): %d\n"), i);
+}
+
+static void
+dump_psymtabs_for_objfile (struct objfile *objfile)
+{
+  struct partial_symtab *psymtab;
+
+  if (objfile->psymtabs)
+    {
+      printf_filtered ("Psymtabs:\n");
+      for (psymtab = objfile->psymtabs;
+	   psymtab != NULL;
+	   psymtab = psymtab->next)
+	{
+	  printf_filtered ("%s at ",
+			   psymtab->filename);
+	  gdb_print_host_address (psymtab, gdb_stdout);
+	  printf_filtered (", ");
+	  if (psymtab->objfile != objfile)
+	    {
+	      printf_filtered ("NOT ON CHAIN!  ");
+	    }
+	  wrap_here ("  ");
+	}
+      printf_filtered ("\n\n");
+    }
+}
+
+/* Look through the partial symtabs for all symbols which begin
+   by matching FUNC_NAME.  Make sure we read that symbol table in. */
+
+static void
+read_symtabs_for_function (struct objfile *objfile, const char *func_name)
+{
+  struct partial_symtab *ps;
+
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+  {
+    if (ps->readin)
+      continue;
+
+    if ((lookup_partial_symbol (ps, func_name, NULL, 1, VAR_DOMAIN)
+	 != NULL)
+	|| (lookup_partial_symbol (ps, func_name, NULL, 0, VAR_DOMAIN)
+	    != NULL))
+      psymtab_to_symtab (ps);
+  }
+}
+
+void
+maintenance_print_psymbols (char *args, int from_tty)
+{
+  char **argv;
+  struct ui_file *outfile;
+  struct cleanup *cleanups;
+  char *symname = NULL;
+  char *filename = DEV_TTY;
+  struct objfile *objfile;
+  struct partial_symtab *ps;
+
+  dont_repeat ();
+
+  if (args == NULL)
+    {
+      error (_("print-psymbols takes an output file name and optional symbol file name"));
+    }
+  argv = gdb_buildargv (args);
+  cleanups = make_cleanup_freeargv (argv);
+
+  if (argv[0] != NULL)
+    {
+      filename = argv[0];
+      /* If a second arg is supplied, it is a source file name to match on */
+      if (argv[1] != NULL)
+	{
+	  symname = argv[1];
+	}
+    }
+
+  filename = tilde_expand (filename);
+  make_cleanup (xfree, filename);
+
+  outfile = gdb_fopen (filename, FOPEN_WT);
+  if (outfile == 0)
+    perror_with_name (filename);
+  make_cleanup_ui_file_delete (outfile);
+
+  immediate_quit++;
+  ALL_PSYMTABS (objfile, ps)
+    if (symname == NULL || strcmp (symname, ps->filename) == 0)
+    dump_psymtab (objfile, ps, outfile);
+  immediate_quit--;
+  do_cleanups (cleanups);
+}
+
+static void
+expand_partial_symbol_tables (struct objfile *objfile)
+{
+  struct partial_symtab *psymtab;
+
+  for (psymtab = objfile->psymtabs;
+       psymtab != NULL;
+       psymtab = psymtab->next)
+    {
+      psymtab_to_symtab (psymtab);
+    }
+}
+
+static void
+read_psymtabs_with_filename (struct objfile *objfile, const char *filename)
+{
+  struct partial_symtab *p;
+
+  ALL_OBJFILE_PSYMTABS (objfile, p)
+    {
+      if (strcmp (filename, p->filename) == 0)
+	PSYMTAB_TO_SYMTAB (p);
+    }
+}
+
+static void
+map_symbol_names_psymtab (struct objfile *objfile,
+			  void (*fun) (const char *, void *), void *data)
+{
+  struct partial_symtab *ps;
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+    {
+      struct partial_symbol **psym;
+
+      /* If the psymtab's been read in we'll get it when we search
+	 through the blockvector.  */
+      if (ps->readin)
+	continue;
+
+      for (psym = objfile->global_psymbols.list + ps->globals_offset;
+	   psym < (objfile->global_psymbols.list + ps->globals_offset
+		   + ps->n_global_syms);
+	   psym++)
+	{
+	  /* If interrupted, then quit. */
+	  QUIT;
+	  (*fun) (SYMBOL_NATURAL_NAME (*psym), data);
+	}
+
+      for (psym = objfile->static_psymbols.list + ps->statics_offset;
+	   psym < (objfile->static_psymbols.list + ps->statics_offset
+		   + ps->n_static_syms);
+	   psym++)
+	{
+	  QUIT;
+	  (*fun) (SYMBOL_NATURAL_NAME (*psym), data);
+	}
+    }
+}
+
+static void
+map_symbol_filenames_psymtab (struct objfile *objfile,
+			      void (*fun) (const char *, const char *,
+					   void *),
+			      void *data)
+{
+  struct partial_symtab *ps;
+
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+    {
+      const char *fullname;
+
+      if (ps->readin)
+	continue;
+
+      fullname = psymtab_to_fullname (ps);
+      (*fun) (fullname, ps->filename, data);
+    }
+}
+
+/* FIXME */
+int find_and_open_source (const char *filename,
+			  const char *dirname,
+			  char **fullname);
+
+/* Finds the fullname that a partial_symtab represents.
+
+   If this functions finds the fullname, it will save it in ps->fullname
+   and it will also return the value.
+
+   If this function fails to find the file that this partial_symtab represents,
+   NULL will be returned and ps->fullname will be set to NULL.  */
+static char *
+psymtab_to_fullname (struct partial_symtab *ps)
+{
+  int r;
+
+  if (!ps)
+    return NULL;
+
+  /* Don't check ps->fullname here, the file could have been
+     deleted/moved/..., look for it again */
+  r = find_and_open_source (ps->filename, ps->dirname, &ps->fullname);
+
+  if (r >= 0)
+    {
+      close (r);
+      return ps->fullname;
+    }
+
+  return NULL;
+}
+
+static char *
+find_symbol_file_from_partial (struct objfile *objfile, const char *name)
+{
+  struct partial_symtab *pst;
+
+  ALL_OBJFILE_PSYMTABS (objfile, pst)
+    {
+      if (lookup_partial_symbol (pst, name, NULL, 1, VAR_DOMAIN))
+	return pst->filename;
+    }
+  return NULL;
+}
+
+/* Look, in partial_symtab PST, for symbol NAME in given namespace.
+   Check the global symbols if GLOBAL, the static symbols if not.
+   Do wild-card match if WILD.  */
+
+static struct partial_symbol *
+ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name,
+                           int global, domain_enum namespace, int wild,
+			   int (*wild_match) (const char *, int, const char *),
+			   int (*is_name_suffix) (const char *))
+{
+  struct partial_symbol **start;
+  int name_len = strlen (name);
+  int length = (global ? pst->n_global_syms : pst->n_static_syms);
+  int i;
+
+  if (length == 0)
+    {
+      return (NULL);
+    }
+
+  start = (global ?
+           pst->objfile->global_psymbols.list + pst->globals_offset :
+           pst->objfile->static_psymbols.list + pst->statics_offset);
+
+  if (wild)
+    {
+      for (i = 0; i < length; i += 1)
+        {
+          struct partial_symbol *psym = start[i];
+
+          if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
+                                     SYMBOL_DOMAIN (psym), namespace)
+              && (*wild_match) (name, name_len, SYMBOL_LINKAGE_NAME (psym)))
+            return psym;
+        }
+      return NULL;
+    }
+  else
+    {
+      if (global)
+        {
+          int U;
+          i = 0;
+          U = length - 1;
+          while (U - i > 4)
+            {
+              int M = (U + i) >> 1;
+              struct partial_symbol *psym = start[M];
+              if (SYMBOL_LINKAGE_NAME (psym)[0] < name[0])
+                i = M + 1;
+              else if (SYMBOL_LINKAGE_NAME (psym)[0] > name[0])
+                U = M - 1;
+              else if (strcmp (SYMBOL_LINKAGE_NAME (psym), name) < 0)
+                i = M + 1;
+              else
+                U = M;
+            }
+        }
+      else
+        i = 0;
+
+      while (i < length)
+        {
+          struct partial_symbol *psym = start[i];
+
+          if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
+                                     SYMBOL_DOMAIN (psym), namespace))
+            {
+              int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym), name_len);
+
+              if (cmp < 0)
+                {
+                  if (global)
+                    break;
+                }
+              else if (cmp == 0
+                       && (*is_name_suffix) (SYMBOL_LINKAGE_NAME (psym)
+					     + name_len))
+                return psym;
+            }
+          i += 1;
+        }
+
+      if (global)
+        {
+          int U;
+          i = 0;
+          U = length - 1;
+          while (U - i > 4)
+            {
+              int M = (U + i) >> 1;
+              struct partial_symbol *psym = start[M];
+              if (SYMBOL_LINKAGE_NAME (psym)[0] < '_')
+                i = M + 1;
+              else if (SYMBOL_LINKAGE_NAME (psym)[0] > '_')
+                U = M - 1;
+              else if (strcmp (SYMBOL_LINKAGE_NAME (psym), "_ada_") < 0)
+                i = M + 1;
+              else
+                U = M;
+            }
+        }
+      else
+        i = 0;
+
+      while (i < length)
+        {
+          struct partial_symbol *psym = start[i];
+
+          if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
+                                     SYMBOL_DOMAIN (psym), namespace))
+            {
+              int cmp;
+
+              cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (psym)[0];
+              if (cmp == 0)
+                {
+                  cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (psym), 5);
+                  if (cmp == 0)
+                    cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym) + 5,
+                                   name_len);
+                }
+
+              if (cmp < 0)
+                {
+                  if (global)
+                    break;
+                }
+              else if (cmp == 0
+                       && (*is_name_suffix) (SYMBOL_LINKAGE_NAME (psym)
+					     + name_len + 5))
+                return psym;
+            }
+          i += 1;
+        }
+    }
+  return NULL;
+}
+
+static void
+map_ada_symtabs (struct objfile *objfile,
+		 int (*wild_match) (const char *, int, const char *),
+		 int (*is_name_suffix) (const char *),
+		 void (*callback) (struct objfile *, struct symtab *, void *),
+		 const char *name, int global, domain_enum namespace, int wild,
+		 void *data)
+{
+  struct partial_symtab *ps;
+
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+    {
+      QUIT;
+      if (ps->readin
+	  || ada_lookup_partial_symbol (ps, name, global, namespace, wild,
+					wild_match, is_name_suffix))
+	{
+	  struct symtab *s = PSYMTAB_TO_SYMTAB (ps);
+	  if (s == NULL || !s->primary)
+	    continue;
+	  (*callback) (objfile, s, data);
+	}
+    }
+}
+
+static void
+expand_symtabs_matching_via_partial (struct objfile *objfile,
+				     int (*file_matcher) (const char *, void *),
+				     int (*name_matcher) (const char *, void *),
+				     domain_enum kind,
+				     void *data)
+{
+  struct partial_symtab *ps;
+
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+    {
+      struct partial_symbol **psym;
+      struct partial_symbol **bound, **gbound, **sbound;
+      int keep_going = 1;
+
+      if (ps->readin)
+	continue;
+
+      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;
+      bound = gbound;
+
+      /* Go through all of the symbols stored in a partial
+	 symtab in one loop. */
+      psym = objfile->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;
+		  bound = sbound;
+		}
+	      else
+		keep_going = 0;
+	      continue;
+	    }
+	  else
+	    {
+	      QUIT;
+
+	      if ((*name_matcher) (SYMBOL_NATURAL_NAME (*psym), data)
+		  && ((kind == VARIABLES_DOMAIN
+		       && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
+		       && SYMBOL_CLASS (*psym) != LOC_BLOCK)
+		      || (kind == FUNCTIONS_DOMAIN
+			  && SYMBOL_CLASS (*psym) == LOC_BLOCK)
+		      || (kind == TYPES_DOMAIN
+			  && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)))
+		{
+		  PSYMTAB_TO_SYMTAB (ps);
+		  keep_going = 0;
+		}
+	    }
+	  psym++;
+	}
+    }
+}
+
+static int
+objfile_has_psyms (struct objfile *objfile)
+{
+  return objfile->psymtabs != NULL;
+}
+
+const struct quick_symbol_functions psym_functions =
+{
+  objfile_has_psyms,
+  find_last_source_symtab_from_partial,
+  forget_cached_source_info_partial,
+  lookup_symtab_via_partial_symtab,
+  lookup_symbol_aux_psymtabs,
+  print_psymtab_stats_for_objfile,
+  dump_psymtabs_for_objfile,
+  relocate_psymtabs,
+  read_symtabs_for_function,
+  expand_partial_symbol_tables,
+  read_psymtabs_with_filename,
+  find_symbol_file_from_partial,
+  map_ada_symtabs,
+  expand_symtabs_matching_via_partial,
+  find_pc_sect_symtab_from_partial,
+  map_symbol_names_psymtab,
+  map_symbol_filenames_psymtab
+};
+
+
+
+/* This compares two partial symbols by names, using strcmp_iw_ordered
+   for the comparison.  */
+
+static int
+compare_psymbols (const void *s1p, const void *s2p)
+{
+  struct partial_symbol *const *s1 = s1p;
+  struct partial_symbol *const *s2 = s2p;
+
+  return strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*s1),
+			    SYMBOL_SEARCH_NAME (*s2));
+}
+
+void
+sort_pst_symbols (struct partial_symtab *pst)
+{
+  /* Sort the global list; don't sort the static list */
+
+  qsort (pst->objfile->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)
+{
+  struct partial_symtab *psymtab;
+
+  psymtab = allocate_psymtab (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;
+  return (psymtab);
+}
+
+/* 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
+   structure.  In other words, having two symbols with the same name but
+   different domain (or address) is possible and correct.  */
+
+static const struct partial_symbol *
+add_psymbol_to_bcache (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 *added)
+{
+  /* psymbol is static so that there will be no uninitialized gaps in the
+     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.  */
+  memset (&psymbol.ginfo.value, 0, sizeof (psymbol.ginfo.value));
+  /* val and coreaddr are mutually exclusive, one of them *will* be zero */
+  if (val != 0)
+    {
+      SYMBOL_VALUE (&psymbol) = val;
+    }
+  else
+    {
+      SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
+    }
+  SYMBOL_SECTION (&psymbol) = 0;
+  SYMBOL_LANGUAGE (&psymbol) = language;
+  PSYMBOL_DOMAIN (&psymbol) = domain;
+  PSYMBOL_CLASS (&psymbol) = class;
+
+  SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
+
+  /* Stash the partial symbol away in the cache */
+  return bcache_full (&psymbol, sizeof (struct partial_symbol),
+		      objfile->psymbol_cache, added);
+}
+
+/* Helper function, adds partial symbol to the given partial symbol
+   list.  */
+
+static void
+append_psymbol_to_list (struct psymbol_allocation_list *list,
+			const struct partial_symbol *psym,
+			struct objfile *objfile)
+{
+  if (list->next >= list->list + list->size)
+    extend_psymbol_list (list, objfile);
+  *list->next++ = (struct partial_symbol *) psym;
+  OBJSTAT (objfile, n_psyms++);
+}
+
+/* Add a symbol with a long value to a psymtab.
+   Since one arg is a struct, we pass in a ptr and deref it (sigh).
+   Return the partial symbol that has been added.  */
+
+/* NOTE: carlton/2003-09-11: The reason why we return the partial
+   symbol is so that callers can get access to the symbol's demangled
+   name, which they don't have any cheap way to determine otherwise.
+   (Currenly, dwarf2read.c is the only file who uses that information,
+   though it's possible that other readers might in the future.)
+   Elena wasn't thrilled about that, and I don't blame her, but we
+   couldn't come up with a better way to get that information.  If
+   it's needed in other situations, we could consider breaking up
+   SYMBOL_SET_NAMES to provide access to the demangled name lookup
+   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)
+{
+  const struct partial_symbol *psym;
+
+  int added;
+
+  /* Stash the partial symbol away in the cache */
+  psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
+				val, coreaddr, language, objfile, &added);
+
+  /* Do not duplicate global partial symbols.  */
+  if (list == &objfile->global_psymbols
+      && !added)
+    return psym;
+
+  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+  append_psymbol_to_list (list, psym, objfile);
+  return psym;
+}
+
+/* Initialize storage for partial symbols.  */
+
+void
+init_psymbol_list (struct objfile *objfile, int total_symbols)
+{
+  /* 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 *)));
+    }
+}
+
+struct partial_symtab *
+allocate_psymtab (const char *filename, struct objfile *objfile)
+{
+  struct partial_symtab *psymtab;
+
+  if (objfile->free_psymtabs)
+    {
+      psymtab = objfile->free_psymtabs;
+      objfile->free_psymtabs = psymtab->next;
+    }
+  else
+    psymtab = (struct partial_symtab *)
+      obstack_alloc (&objfile->objfile_obstack,
+		     sizeof (struct partial_symtab));
+
+  memset (psymtab, 0, sizeof (struct partial_symtab));
+  psymtab->filename = obsavestring (filename, strlen (filename),
+				    &objfile->objfile_obstack);
+  psymtab->symtab = NULL;
+
+  /* Prepend it to the psymtab list for the objfile it belongs to.
+     Psymtabs are searched in most recent inserted -> least recent
+     inserted order. */
+
+  psymtab->objfile = objfile;
+  psymtab->next = objfile->psymtabs;
+  objfile->psymtabs = psymtab;
+#if 0
+  {
+    struct partial_symtab **prev_pst;
+    psymtab->objfile = objfile;
+    psymtab->next = NULL;
+    prev_pst = &(objfile->psymtabs);
+    while ((*prev_pst) != NULL)
+      prev_pst = &((*prev_pst)->next);
+    (*prev_pst) = psymtab;
+  }
+#endif
+
+  return (psymtab);
+}
+
+void
+discard_psymtab (struct partial_symtab *pst)
+{
+  struct partial_symtab **prev_pst;
+
+  /* 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
+     check is wrong, in that a psymtab with N_SLINE entries but
+     nothing else is not empty, but we don't realize that.  Fixing
+     that without slowing things down might be tricky.  */
+
+  /* First, snip it out of the psymtab chain */
+
+  prev_pst = &(pst->objfile->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;
+}
+
+/* Increase the space allocated for LISTP, which is probably
+   global_psymbols or static_psymbols. This space will eventually
+   be freed in free_objfile().  */
+
+void
+extend_psymbol_list (struct psymbol_allocation_list *listp,
+		     struct objfile *objfile)
+{
+  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;
+}
+
+
+
+/* List all the partial symbol tables whose names match REGEXP (optional).  */
+void
+maintenance_info_psymtabs (char *regexp, int from_tty)
+{
+  struct program_space *pspace;
+  struct objfile *objfile;
+
+  if (regexp)
+    re_comp (regexp);
+
+  ALL_PSPACES (pspace)
+    ALL_PSPACE_OBJFILES (pspace, objfile)
+    {
+      struct gdbarch *gdbarch = get_objfile_arch (objfile);
+      struct partial_symtab *psymtab;
+
+      /* We don't want to print anything for this objfile until we
+         actually find a symtab whose name matches.  */
+      int printed_objfile_start = 0;
+
+      ALL_OBJFILE_PSYMTABS (objfile, psymtab)
+	{
+	  QUIT;
+
+	  if (! regexp
+	      || re_exec (psymtab->filename))
+	    {
+	      if (! printed_objfile_start)
+		{
+		  printf_filtered ("{ objfile %s ", objfile->name);
+		  wrap_here ("  ");
+		  printf_filtered ("((struct objfile *) %s)\n", 
+				   host_address_to_string (objfile));
+		  printed_objfile_start = 1;
+		}
+
+	      printf_filtered ("  { psymtab %s ", psymtab->filename);
+	      wrap_here ("    ");
+	      printf_filtered ("((struct partial_symtab *) %s)\n", 
+			       host_address_to_string (psymtab));
+
+	      printf_filtered ("    readin %s\n",
+			       psymtab->readin ? "yes" : "no");
+	      printf_filtered ("    fullname %s\n",
+			       psymtab->fullname ? psymtab->fullname : "(null)");
+	      printf_filtered ("    text addresses ");
+	      fputs_filtered (paddress (gdbarch, psymtab->textlow),
+			      gdb_stdout);
+	      printf_filtered (" -- ");
+	      fputs_filtered (paddress (gdbarch, psymtab->texthigh),
+			      gdb_stdout);
+	      printf_filtered ("\n");
+	      printf_filtered ("    globals ");
+	      if (psymtab->n_global_syms)
+		{
+		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
+				   host_address_to_string (psymtab->objfile->global_psymbols.list
+				    + psymtab->globals_offset),
+				   psymtab->n_global_syms);
+		}
+	      else
+		printf_filtered ("(none)\n");
+	      printf_filtered ("    statics ");
+	      if (psymtab->n_static_syms)
+		{
+		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
+				   host_address_to_string (psymtab->objfile->static_psymbols.list
+				    + psymtab->statics_offset),
+				   psymtab->n_static_syms);
+		}
+	      else
+		printf_filtered ("(none)\n");
+	      printf_filtered ("    dependencies ");
+	      if (psymtab->number_of_dependencies)
+		{
+		  int i;
+
+		  printf_filtered ("{\n");
+		  for (i = 0; i < psymtab->number_of_dependencies; i++)
+		    {
+		      struct partial_symtab *dep = psymtab->dependencies[i];
+
+		      /* Note the string concatenation there --- no comma.  */
+		      printf_filtered ("      psymtab %s "
+				       "((struct partial_symtab *) %s)\n",
+				       dep->filename, 
+				       host_address_to_string (dep));
+		    }
+		  printf_filtered ("    }\n");
+		}
+	      else
+		printf_filtered ("(none)\n");
+	      printf_filtered ("  }\n");
+	    }
+	}
+
+      if (printed_objfile_start)
+        printf_filtered ("}\n");
+    }
+}
+
+/* Check consistency of psymtabs and symtabs.  */
+
+void
+maintenance_check_symtabs (char *ignore, int from_tty)
+{
+  struct symbol *sym;
+  struct partial_symbol **psym;
+  struct symtab *s = NULL;
+  struct partial_symtab *ps;
+  struct blockvector *bv;
+  struct objfile *objfile;
+  struct block *b;
+  int length;
+
+  ALL_PSYMTABS (objfile, ps)
+  {
+    struct gdbarch *gdbarch = get_objfile_arch (objfile);
+    s = PSYMTAB_TO_SYMTAB (ps);
+    if (s == NULL)
+      continue;
+    bv = BLOCKVECTOR (s);
+    b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+    psym = ps->objfile->static_psymbols.list + ps->statics_offset;
+    length = ps->n_static_syms;
+    while (length--)
+      {
+	sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
+				   NULL, SYMBOL_DOMAIN (*psym));
+	if (!sym)
+	  {
+	    printf_filtered ("Static symbol `");
+	    puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
+	    printf_filtered ("' only found in ");
+	    puts_filtered (ps->filename);
+	    printf_filtered (" psymtab\n");
+	  }
+	psym++;
+      }
+    b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+    psym = ps->objfile->global_psymbols.list + ps->globals_offset;
+    length = ps->n_global_syms;
+    while (length--)
+      {
+	sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
+				   NULL, SYMBOL_DOMAIN (*psym));
+	if (!sym)
+	  {
+	    printf_filtered ("Global symbol `");
+	    puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
+	    printf_filtered ("' only found in ");
+	    puts_filtered (ps->filename);
+	    printf_filtered (" psymtab\n");
+	  }
+	psym++;
+      }
+    if (ps->texthigh < ps->textlow)
+      {
+	printf_filtered ("Psymtab ");
+	puts_filtered (ps->filename);
+	printf_filtered (" covers bad range ");
+	fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
+	printf_filtered (" - ");
+	fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
+	printf_filtered ("\n");
+	continue;
+      }
+    if (ps->texthigh == 0)
+      continue;
+    if (ps->textlow < BLOCK_START (b) || ps->texthigh > BLOCK_END (b))
+      {
+	printf_filtered ("Psymtab ");
+	puts_filtered (ps->filename);
+	printf_filtered (" covers ");
+	fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
+	printf_filtered (" - ");
+	fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
+	printf_filtered (" but symtab covers only ");
+	fputs_filtered (paddress (gdbarch, BLOCK_START (b)), gdb_stdout);
+	printf_filtered (" - ");
+	fputs_filtered (paddress (gdbarch, BLOCK_END (b)), gdb_stdout);
+	printf_filtered ("\n");
+      }
+  }
+}
+
+
+
+void
+map_partial_symbol_names (void (*fun) (const char *, void *), void *data)
+{
+  struct objfile *objfile;
+
+  ALL_OBJFILES (objfile)
+  {
+    if (objfile->sf)
+      objfile->sf->qf->map_symbol_names (objfile, fun, data);
+  }
+}
+
+void
+map_partial_symbol_filenames (void (*fun) (const char *, const char *,
+					   void *),
+			      void *data)
+{
+  struct objfile *objfile;
+
+  ALL_OBJFILES (objfile)
+  {
+    if (objfile->sf)
+      objfile->sf->qf->map_symbol_filenames (objfile, fun, data);
+  }
+}
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
new file mode 100644
index 0000000..9b8c8df
--- /dev/null
+++ b/gdb/psymtab.h
@@ -0,0 +1,31 @@
+/* Public partial symbol table definitions.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef PSYMTAB_H
+#define PSYMTAB_H
+
+void map_partial_symbol_names (void (*) (const char *, void *), void *);
+
+void map_partial_symbol_filenames (void (*) (const char *, const char *,
+					     void *),
+				   void *);
+
+extern const struct quick_symbol_functions psym_functions;
+
+#endif /* PSYMTAB_H */
diff --git a/gdb/somread.c b/gdb/somread.c
index c7beaba..a790473 100644
--- a/gdb/somread.c
+++ b/gdb/somread.c
@@ -32,6 +32,7 @@
 #include "demangle.h"
 #include "som.h"
 #include "libhppa.h"
+#include "psymtab.h"
 
 #include "solib-som.h"
 
@@ -437,6 +438,7 @@ static struct sym_fns som_sym_fns =
   default_symfile_segments,	/* sym_segments: Get segment information from
 				   a file.  */
   NULL,                         /* sym_read_linetable */
+  &psym_functions,
   NULL				/* next: pointer to next struct sym_fns */
 };
 
diff --git a/gdb/source.c b/gdb/source.c
index 2090326..dda5d1b 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -46,6 +46,8 @@
 #include "ui-out.h"
 #include "readline/readline.h"
 
+#include "psymtab.h"
+
 
 #define OPEN_MODE (O_RDONLY | O_BINARY)
 #define FDOPEN_MODE FOPEN_RB
@@ -229,8 +231,6 @@ select_source_symtab (struct symtab *s)
 {
   struct symtabs_and_lines sals;
   struct symtab_and_line sal;
-  struct partial_symtab *ps;
-  struct partial_symtab *cs_pst = 0;
   struct objfile *ofp;
 
   if (s)
@@ -281,33 +281,13 @@ select_source_symtab (struct symtab *s)
   if (current_source_symtab)
     return;
 
-  /* How about the partial symbol tables?  */
-
   ALL_OBJFILES (ofp)
-    {
-      for (ps = ofp->psymtabs; ps != NULL; ps = ps->next)
-	{
-	  const char *name = ps->filename;
-	  int len = strlen (name);
-	  if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
-	      || strcmp (name, "<<C++-namespaces>>") == 0)))
-	    cs_pst = ps;
-	}
-    }
-  if (cs_pst)
-    {
-      if (cs_pst->readin)
-	{
-	  internal_error (__FILE__, __LINE__,
-			  _("select_source_symtab: "
-			  "readin pst found and no symtabs."));
-	}
-      else
-	{
-	  current_source_pspace = current_program_space;
-	  current_source_symtab = PSYMTAB_TO_SYMTAB (cs_pst);
-	}
-    }
+  {
+    if (ofp->sf)
+      s = ofp->sf->qf->find_last_source_symtab (ofp);
+    if (s)
+      current_source_symtab = s;
+  }
   if (current_source_symtab)
     return;
 
@@ -332,7 +312,6 @@ forget_cached_source_info (void)
   struct program_space *pspace;
   struct symtab *s;
   struct objfile *objfile;
-  struct partial_symtab *pst;
 
   ALL_PSPACES (pspace)
     ALL_PSPACE_OBJFILES (pspace, objfile)
@@ -351,14 +330,8 @@ forget_cached_source_info (void)
 	    }
 	}
 
-      ALL_OBJFILE_PSYMTABS (objfile, pst)
-      {
-	if (pst->fullname != NULL)
-	  {
-	    xfree (pst->fullname);
-	    pst->fullname = NULL;
-	  }
-      }
+      if (objfile->sf)
+	objfile->sf->qf->forget_cached_source_info (objfile);
     }
 
   last_source_visited = NULL;
@@ -964,7 +937,7 @@ rewrite_source_path (const char *path)
      An invalid file descriptor is returned. ( the return value is negative ) 
      FULLNAME is set to NULL.  */
 
-static int
+int
 find_and_open_source (const char *filename,
 		      const char *dirname,
 		      char **fullname)
@@ -1094,34 +1067,6 @@ symtab_to_fullname (struct symtab *s)
 
   return NULL;
 }
-
-/* Finds the fullname that a partial_symtab represents.
-
-   If this functions finds the fullname, it will save it in ps->fullname
-   and it will also return the value.
-
-   If this function fails to find the file that this partial_symtab represents,
-   NULL will be returned and ps->fullname will be set to NULL.  */
-char *
-psymtab_to_fullname (struct partial_symtab *ps)
-{
-  int r;
-
-  if (!ps)
-    return NULL;
-
-  /* Don't check ps->fullname here, the file could have been
-     deleted/moved/..., look for it again */
-  r = find_and_open_source (ps->filename, ps->dirname, &ps->fullname);
-
-  if (r >= 0)
-    {
-      close (r);
-      return ps->fullname;
-    }
-
-  return NULL;
-}
 
 /* Create and initialize the table S->line_charpos that records
    the positions of the lines in the source file, which is assumed
diff --git a/gdb/source.h b/gdb/source.h
index ae23c83..7b755c6 100644
--- a/gdb/source.h
+++ b/gdb/source.h
@@ -25,7 +25,6 @@ struct symtab;
    negative number for error.  */
 extern int open_source_file (struct symtab *s);
 
-extern char* psymtab_to_fullname (struct partial_symtab *ps);
 extern char* symtab_to_fullname (struct symtab *s);
 
 /* Create and initialize the table S->line_charpos that records the
diff --git a/gdb/stack.c b/gdb/stack.c
index 6e198e0..3a909f7 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -52,6 +52,9 @@
 #include <ctype.h>
 #include "gdb_string.h"
 
+#include "psymtab.h"
+#include "symfile.h"
+
 void (*deprecated_selected_frame_level_changed_hook) (int);
 
 /* The possible choices of "set print frame-arguments, and the value
@@ -1321,10 +1324,10 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
       i = count;
       for (fi = trailing; fi != NULL && i--; fi = get_prev_frame (fi))
 	{
+	  CORE_ADDR pc;
 	  QUIT;
-	  ps = find_pc_psymtab (get_frame_address_in_block (fi));
-	  if (ps)
-	    PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in.  */
+	  pc = get_frame_address_in_block (fi);
+	  find_pc_sect_symtab_via_partial (pc, find_pc_mapped_section (pc));
 	}
     }
 
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 89cc07c..4b264be 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -65,6 +65,7 @@
 #include <time.h>
 #include <sys/time.h>
 
+#include "psymtab.h"
 
 int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num);
 void (*deprecated_show_load_progress) (const char *section,
@@ -97,8 +98,6 @@ static void symbol_file_add_main_1 (char *args, int from_tty, int flags);
 
 static void add_symbol_file_command (char *, int);
 
-static void cashier_psymtab (struct partial_symtab *);
-
 bfd *symfile_bfd_open (char *);
 
 int get_section_index (struct objfile *, char *);
@@ -190,29 +189,6 @@ int auto_solib_add = 1;
 int auto_solib_limit;
 
 
-/* This compares two partial symbols by names, using strcmp_iw_ordered
-   for the comparison.  */
-
-static int
-compare_psymbols (const void *s1p, const void *s2p)
-{
-  struct partial_symbol *const *s1 = s1p;
-  struct partial_symbol *const *s2 = s2p;
-
-  return strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*s1),
-			    SYMBOL_SEARCH_NAME (*s2));
-}
-
-void
-sort_pst_symbols (struct partial_symtab *pst)
-{
-  /* Sort the global list; don't sort the static list */
-
-  qsort (pst->objfile->global_psymbols.list + pst->globals_offset,
-	 pst->n_global_syms, sizeof (struct partial_symbol *),
-	 compare_psymbols);
-}
-
 /* Make a null terminated copy of the string at PTR with SIZE characters in
    the obstack pointed to by OBSTACKP .  Returns the address of the copy.
    Note that the string at PTR does not have to be null terminated, I.E. it
@@ -251,7 +227,7 @@ obconcat (struct obstack *obstackp, const char *s1, const char *s2,
   return val;
 }
 
-/* True if we are nested inside psymtab_to_symtab. */
+/* True if we are reading a symbol table. */
 
 int currently_reading_symtab = 0;
 
@@ -261,28 +237,13 @@ decrement_reading_symtab (void *dummy)
   currently_reading_symtab--;
 }
 
-/* Get the symbol table that corresponds to a partial_symtab.
-   This is fast after the first time you do it.  In fact, there
-   is an even faster macro PSYMTAB_TO_SYMTAB that does the fast
-   case inline.  */
-
-struct symtab *
-psymtab_to_symtab (struct partial_symtab *pst)
+/* Increment currently_reading_symtab and return a cleanup that can be
+   used to decrement it.  */
+struct cleanup *
+increment_reading_symtab (void)
 {
-  /* If it's been looked up before, return it. */
-  if (pst->symtab)
-    return pst->symtab;
-
-  /* If it has not yet been read in, read it.  */
-  if (!pst->readin)
-    {
-      struct cleanup *back_to = make_cleanup (decrement_reading_symtab, NULL);
-      currently_reading_symtab++;
-      (*pst->read_symtab) (pst);
-      do_cleanups (back_to);
-    }
-
-  return pst->symtab;
+  ++currently_reading_symtab;
+  return make_cleanup (decrement_reading_symtab, NULL);
 }
 
 /* Remember the lowest-addressed loadable section we've seen.
@@ -958,7 +919,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
                                        int flags)
 {
   struct objfile *objfile;
-  struct partial_symtab *psymtab;
   struct cleanup *my_cleanups;
   const char *name = bfd_get_filename (abfd);
   const int from_tty = add_flags & SYMFILE_VERBOSE;
@@ -1008,12 +968,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
 	  gdb_flush (gdb_stdout);
 	}
 
-      for (psymtab = objfile->psymtabs;
-	   psymtab != NULL;
-	   psymtab = psymtab->next)
-	{
-	  psymtab_to_symtab (psymtab);
-	}
+      if (objfile->sf)
+	objfile->sf->qf->expand_all_symtabs (objfile);
     }
 
   if ((from_tty || info_verbose)
@@ -1447,24 +1403,21 @@ symbol_file_command (char *args, int from_tty)
 void
 set_initial_language (void)
 {
-  struct partial_symtab *pst;
+  char *filename;
   enum language lang = language_unknown;
 
-  pst = find_main_psymtab ();
-  if (pst != NULL)
-    {
-      if (pst->filename != NULL)
-	lang = deduce_language_from_filename (pst->filename);
-
-      if (lang == language_unknown)
-	{
-	  /* Make C the default language */
-	  lang = language_c;
-	}
+  filename = find_main_filename ();
+  if (filename != NULL)
+    lang = deduce_language_from_filename (filename);
 
-      set_language (lang);
-      expected_language = current_language; /* Don't warn the user.  */
+  if (lang == language_unknown)
+    {
+      /* Make C the default language */
+      lang = language_c;
     }
+
+  set_language (lang);
+  expected_language = current_language; /* Don't warn the user.  */
 }
 
 /* If NAME is a remote name open the file using remote protocol, otherwise
@@ -2602,73 +2555,6 @@ allocate_symtab (char *filename, struct objfile *objfile)
 
   return (symtab);
 }
-
-struct partial_symtab *
-allocate_psymtab (const char *filename, struct objfile *objfile)
-{
-  struct partial_symtab *psymtab;
-
-  if (objfile->free_psymtabs)
-    {
-      psymtab = objfile->free_psymtabs;
-      objfile->free_psymtabs = psymtab->next;
-    }
-  else
-    psymtab = (struct partial_symtab *)
-      obstack_alloc (&objfile->objfile_obstack,
-		     sizeof (struct partial_symtab));
-
-  memset (psymtab, 0, sizeof (struct partial_symtab));
-  psymtab->filename = (char *) bcache (filename, strlen (filename) + 1,
-				       objfile->filename_cache);
-  psymtab->symtab = NULL;
-
-  /* Prepend it to the psymtab list for the objfile it belongs to.
-     Psymtabs are searched in most recent inserted -> least recent
-     inserted order. */
-
-  psymtab->objfile = objfile;
-  psymtab->next = objfile->psymtabs;
-  objfile->psymtabs = psymtab;
-#if 0
-  {
-    struct partial_symtab **prev_pst;
-    psymtab->objfile = objfile;
-    psymtab->next = NULL;
-    prev_pst = &(objfile->psymtabs);
-    while ((*prev_pst) != NULL)
-      prev_pst = &((*prev_pst)->next);
-    (*prev_pst) = psymtab;
-  }
-#endif
-
-  return (psymtab);
-}
-
-void
-discard_psymtab (struct partial_symtab *pst)
-{
-  struct partial_symtab **prev_pst;
-
-  /* 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
-     check is wrong, in that a psymtab with N_SLINE entries but
-     nothing else is not empty, but we don't realize that.  Fixing
-     that without slowing things down might be tricky.  */
-
-  /* First, snip it out of the psymtab chain */
-
-  prev_pst = &(pst->objfile->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;
-}
 
 
 /* Reset all data structures in gdb which may contain references to symbol
@@ -2752,52 +2638,6 @@ clear_symtab_users_once (void)
 }
 #endif
 
-/* Delete the specified psymtab, and any others that reference it.  */
-
-static void
-cashier_psymtab (struct partial_symtab *pst)
-{
-  struct partial_symtab *ps, *pprev = NULL;
-  int i;
-
-  /* Find its previous psymtab in the chain */
-  for (ps = pst->objfile->psymtabs; ps; ps = ps->next)
-    {
-      if (ps == pst)
-	break;
-      pprev = ps;
-    }
-
-  if (ps)
-    {
-      /* Unhook it from the chain.  */
-      if (ps == pst->objfile->psymtabs)
-	pst->objfile->psymtabs = ps->next;
-      else
-	pprev->next = ps->next;
-
-      /* FIXME, we can't conveniently deallocate the entries in the
-         partial_symbol lists (global_psymbols/static_psymbols) that
-         this psymtab points to.  These just take up space until all
-         the psymtabs are reclaimed.  Ditto the dependencies list and
-         filename, which are all in the objfile_obstack.  */
-
-      /* We need to cashier any psymtab that has this one as a dependency... */
-    again:
-      for (ps = pst->objfile->psymtabs; ps; ps = ps->next)
-	{
-	  for (i = 0; i < ps->number_of_dependencies; i++)
-	    {
-	      if (ps->dependencies[i] == pst)
-		{
-		  cashier_psymtab (ps);
-		  goto again;	/* Must restart, chain has been munged. */
-		}
-	    }
-	}
-    }
-}
-
 /* If a symtab or psymtab for filename NAME is found, free it along
    with any dependent breakpoints, displays, etc.
    Used when loading new versions of object modules with the "add-file"
@@ -2814,266 +2654,9 @@ cashier_psymtab (struct partial_symtab *pst)
 int
 free_named_symtabs (char *name)
 {
-#if 0
-  /* FIXME:  With the new method of each objfile having it's own
-     psymtab list, this function needs serious rethinking.  In particular,
-     why was it ever necessary to toss psymtabs with specific compilation
-     unit filenames, as opposed to all psymtabs from a particular symbol
-     file?  -- fnf
-     Well, the answer is that some systems permit reloading of particular
-     compilation units.  We want to blow away any old info about these
-     compilation units, regardless of which objfiles they arrived in. --gnu.  */
-
-  struct symtab *s;
-  struct symtab *prev;
-  struct partial_symtab *ps;
-  struct blockvector *bv;
-  int blewit = 0;
-
-  /* We only wack things if the symbol-reload switch is set.  */
-  if (!symbol_reloading)
-    return 0;
-
-  /* Some symbol formats have trouble providing file names... */
-  if (name == 0 || *name == '\0')
-    return 0;
-
-  /* Look for a psymtab with the specified name.  */
-
-again2:
-  for (ps = partial_symtab_list; ps; ps = ps->next)
-    {
-      if (strcmp (name, ps->filename) == 0)
-	{
-	  cashier_psymtab (ps);	/* Blow it away...and its little dog, too.  */
-	  goto again2;		/* Must restart, chain has been munged */
-	}
-    }
-
-  /* Look for a symtab with the specified name.  */
-
-  for (s = symtab_list; s; s = s->next)
-    {
-      if (strcmp (name, s->filename) == 0)
-	break;
-      prev = s;
-    }
-
-  if (s)
-    {
-      if (s == symtab_list)
-	symtab_list = s->next;
-      else
-	prev->next = s->next;
-
-      /* For now, queue a delete for all breakpoints, displays, etc., whether
-         or not they depend on the symtab being freed.  This should be
-         changed so that only those data structures affected are deleted.  */
-
-      /* But don't delete anything if the symtab is empty.
-         This test is necessary due to a bug in "dbxread.c" that
-         causes empty symtabs to be created for N_SO symbols that
-         contain the pathname of the object file.  (This problem
-         has been fixed in GDB 3.9x).  */
-
-      bv = BLOCKVECTOR (s);
-      if (BLOCKVECTOR_NBLOCKS (bv) > 2
-	  || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK))
-	  || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)))
-	{
-	  complaint (&symfile_complaints, _("Replacing old symbols for `%s'"),
-		     name);
-	  clear_symtab_users_queued++;
-	  make_cleanup (clear_symtab_users_once, 0);
-	  blewit = 1;
-	}
-      else
-	complaint (&symfile_complaints, _("Empty symbol table found for `%s'"),
-		   name);
-
-      free_symtab (s);
-    }
-  else
-    {
-      /* It is still possible that some breakpoints will be affected
-         even though no symtab was found, since the file might have
-         been compiled without debugging, and hence not be associated
-         with a symtab.  In order to handle this correctly, we would need
-         to keep a list of text address ranges for undebuggable files.
-         For now, we do nothing, since this is a fairly obscure case.  */
-      ;
-    }
-
-  /* FIXME, what about the minimal symbol table? */
-  return blewit;
-#else
   return (0);
-#endif
-}
-
-/* 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)
-{
-  struct partial_symtab *psymtab;
-
-  psymtab = allocate_psymtab (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;
-  return (psymtab);
 }
 
-/* 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
-   structure.  In other words, having two symbols with the same name but
-   different domain (or address) is possible and correct.  */
-
-static const struct partial_symbol *
-add_psymbol_to_bcache (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 *added)
-{
-  /* psymbol is static so that there will be no uninitialized gaps in the
-     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.  */
-  memset (&psymbol.ginfo.value, 0, sizeof (psymbol.ginfo.value));
-  /* val and coreaddr are mutually exclusive, one of them *will* be zero */
-  if (val != 0)
-    {
-      SYMBOL_VALUE (&psymbol) = val;
-    }
-  else
-    {
-      SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
-    }
-  SYMBOL_SECTION (&psymbol) = 0;
-  SYMBOL_LANGUAGE (&psymbol) = language;
-  PSYMBOL_DOMAIN (&psymbol) = domain;
-  PSYMBOL_CLASS (&psymbol) = class;
-
-  SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
-
-  /* Stash the partial symbol away in the cache */
-  return bcache_full (&psymbol, sizeof (struct partial_symbol),
-		      objfile->psymbol_cache, added);
-}
-
-/* Helper function, adds partial symbol to the given partial symbol
-   list.  */
-
-static void
-append_psymbol_to_list (struct psymbol_allocation_list *list,
-			const struct partial_symbol *psym,
-			struct objfile *objfile)
-{
-  if (list->next >= list->list + list->size)
-    extend_psymbol_list (list, objfile);
-  *list->next++ = (struct partial_symbol *) psym;
-  OBJSTAT (objfile, n_psyms++);
-}
-
-/* Add a symbol with a long value to a psymtab.
-   Since one arg is a struct, we pass in a ptr and deref it (sigh).
-   Return the partial symbol that has been added.  */
-
-/* NOTE: carlton/2003-09-11: The reason why we return the partial
-   symbol is so that callers can get access to the symbol's demangled
-   name, which they don't have any cheap way to determine otherwise.
-   (Currenly, dwarf2read.c is the only file who uses that information,
-   though it's possible that other readers might in the future.)
-   Elena wasn't thrilled about that, and I don't blame her, but we
-   couldn't come up with a better way to get that information.  If
-   it's needed in other situations, we could consider breaking up
-   SYMBOL_SET_NAMES to provide access to the demangled name lookup
-   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)
-{
-  const struct partial_symbol *psym;
-
-  int added;
-
-  /* Stash the partial symbol away in the cache */
-  psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
-				val, coreaddr, language, objfile, &added);
-
-  /* Do not duplicate global partial symbols.  */
-  if (list == &objfile->global_psymbols
-      && !added)
-    return psym;
-
-  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
-  append_psymbol_to_list (list, psym, objfile);
-  return psym;
-}
-
-/* Initialize storage for partial symbols.  */
-
-void
-init_psymbol_list (struct objfile *objfile, int total_symbols)
-{
-  /* 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 *)));
-    }
-}
-
 /* OVERLAYS:
    The following code implements an abstraction for debugging overlay sections.
 
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 7ae819c..8982dbf 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -109,6 +109,168 @@ struct symfile_segment_data
   int *segment_info;
 };
 
+/* The "quick" symbol functions exist so that symbol readers can
+   avoiding an initial read of all the symbols.  For example, symbol
+   readers might choose to use the "partial symbol table" utilities,
+   which is one implementation of the quick symbol functions.
+
+   The quick symbol functions are generally opaque: the underlying
+   representation is hidden from the caller.
+
+   In general, these functions should only look at whatever special
+   index the symbol reader creates -- looking through the symbol
+   tables themselves is handled by generic code.  If a function is
+   defined as returning a "symbol table", this means that the function
+   should only return a newly-created symbol table; it should not
+   examine pre-existing ones.
+
+   The exact list of functions here was determined in an ad hoc way
+   based on gdb's history.  */
+
+struct quick_symbol_functions
+{
+  /* Return true if this objfile has any "partial" symbols
+     available.  */
+  int (*has_symbols) (struct objfile *objfile);
+
+  /* Return the symbol table for the "last" file appearing in
+     OBJFILE.  */
+  struct symtab *(*find_last_source_symtab) (struct objfile *objfile);
+
+  /* Forget all cached full file names for OBJFILE.  */
+  void (*forget_cached_source_info) (struct objfile *objfile);
+
+  /* Look up the symbol table, in OBJFILE, of a source file named
+     NAME.  If there is no '/' in the name, a match after a '/' in the
+     symbol table's file name will also work.  FULL_PATH is the
+     absolute file name, and REAL_PATH is the same, run through
+     gdb_realpath.
+     
+     If no such symbol table can be found, returns 0.
+     
+     Otherwise, sets *RESULT to the symbol table and returns 1.  This
+     might return 1 and set *RESULT to NULL if the requested file is
+     an include file that does not have a symtab of its own.  */
+  int (*lookup_symtab) (struct objfile *objfile,
+			const char *name,
+			const char *full_path,
+			const char *real_path,
+			struct symtab **result);
+
+  /* Check to see if the symbol is defined in a "partial" symbol table
+     of OBJFILE.  KIND should be either GLOBAL_BLOCK or STATIC_BLOCK,
+     depending on whether we want to search global symbols or static
+     symbols.  NAME is the name of the symbol to look for, and
+     LINKAGE_NAME is the linkage name (or NULL).  DOMAIN indicates
+     what sort of symbol to search for.  If DOMAIN is STRUCT_DOMAIN,
+     then LINKAGE_NAME is ignored.
+     
+     Returns the newly-expanded symbol table in which the symbol is
+     defined, or NULL if no such symbol table exists.  */
+  struct symtab *(*lookup_symbol) (struct objfile *objfile,
+				   int kind, const char *name,
+				   const char *linkage_name,
+				   domain_enum domain);
+
+  /* Print statistics about any indices loaded for OBJFILE.  The
+     statistics should be printed to gdb_stdout.  This is used for
+     "maint print statistics".  */
+  void (*print_stats) (struct objfile *objfile);
+
+  /* Dump any indices loaded for OBJFILE.  The dump should go to
+     gdb_stdout.  This is used for "maint print objfiles".  */
+  void (*dump) (struct objfile *objfile);
+
+  /* This is called by objfile_relocate to relocate any indices loaded
+     for OBJFILE.  */
+  void (*relocate) (struct objfile *objfile,
+		    struct section_offsets *new_offsets,
+		    struct section_offsets *delta);
+
+  /* Find all the symbols in OBJFILE named FUNC_NAME, and ensure that
+     the corresponding symbol tables are loaded.  */
+  void (*expand_symtabs_for_function) (struct objfile *objfile,
+				       const char *func_name);
+
+  /* Read all symbol tables associated with OBJFILE.  */
+  void (*expand_all_symtabs) (struct objfile *objfile);
+
+  /* Read all symbol tables associated with OBJFILE which have the
+     file name FILENAME.  */
+  void (*expand_symtabs_with_filename) (struct objfile *objfile,
+					const char *filename);
+
+  /* Return the file name of the file holding the symbol in OBJFILE
+     named NAME.  If no such symbol exists in OBJFILE, return NULL.  */
+  char *(*find_symbol_file) (struct objfile *objfile, const char *name);
+
+  /* This method is specific to Ada.  It walks the partial symbol
+     tables of OBJFILE looking for a name match.  WILD_MATCH and
+     IS_NAME_SUFFIX are predicate functions that the implementation
+     may call to check for a match.
+     
+     This function is completely ad hoc and new implementations should
+     refer to the psymtab implementation to see what to do.  */
+  void (*map_ada_symtabs) (struct objfile *objfile,
+			   int (*wild_match) (const char *, int, const char *),
+			   int (*is_name_suffix) (const char *),
+			   void (*callback) (struct objfile *,
+					     struct symtab *, void *),
+			   const char *name, int global,
+			   domain_enum namespace, int wild,
+			   void *data);
+
+  /* Expand all symbol tables in OBJFILE matching some criteria.
+     
+     FILE_MATCHER is called for each file in OBJFILE.  The file name
+     and the DATA argument are passed to it.  If it returns zero, this
+     file is skipped.
+     
+     Otherwise, if the file is not skipped, then NAME_MATCHER is
+     called for each symbol defined in the file.  The symbol's
+     "natural" name and DATA are passed to NAME_MATCHER.
+     
+     If NAME_MATCHER returns zero, then this symbol is skipped.
+     
+     Otherwise, if this symbol is not skipped, and it matches KIND,
+     then this symbol's symbol table is expanded.
+     
+     DATA is user data that is passed unmodified to the callback
+     functions.  */
+  void (*expand_symtabs_matching) (struct objfile *objfile,
+				   int (*file_matcher) (const char *, void *),
+				   int (*name_matcher) (const char *, void *),
+				   domain_enum kind,
+				   void *data);
+
+  /* Return the symbol table from OBJFILE that contains PC and
+     SECTION.  Return NULL if there is no such symbol table.  This
+     should return the symbol table that contains a symbol whose
+     address exactly matches PC, or, if there is no exact match, the
+     symbol table that contains a symbol whose address is closest to
+     PC.  */
+  struct symtab *(*find_pc_sect_symtab) (struct objfile *objfile,
+					 struct minimal_symbol *msymbol,
+					 CORE_ADDR pc,
+					 struct obj_section *section,
+					 int warn_if_readin);
+
+  /* Call a callback for every symbol defined in OBJFILE.  FUN is the
+     callback.  It is passed the symbol's natural name, and the DATA
+     passed to this function.  */
+  void (*map_symbol_names) (struct objfile *objfile,
+			    void (*fun) (const char *, void *),
+			    void *data);
+
+  /* Call a callback for every file defined in OBJFILE.  FUN is the
+     callback.  It is passed the file's name, the file's full name,
+     and the DATA passed to this function.  */
+  void (*map_symbol_filenames) (struct objfile *objfile,
+				void (*fun) (const char *, const char *,
+					     void *),
+				void *data);
+};
+
 /* Structure to keep track of symbol reading functions for various
    object file types.  */
 
@@ -165,6 +327,10 @@ struct sym_fns
      information.  */
   void (*sym_read_linetable) (void);
 
+  /* The "quick" (aka partial) symbol functions for this symbol
+     reader.  */
+  const struct quick_symbol_functions *qf;
+
   /* Finds the next struct sym_fns.  They are allocated and
      initialized in whatever module implements the functions pointed
      to; an initializer calls add_symtab_fns to add them to the global
@@ -211,8 +377,6 @@ struct partial_symbol *add_psymbol_to_list (char *, int, int, domain_enum,
 
 extern void init_psymbol_list (struct objfile *, int);
 
-extern void sort_pst_symbols (struct partial_symtab *);
-
 extern struct symtab *allocate_symtab (char *, struct objfile *);
 
 extern int free_named_symtabs (char *);
@@ -386,6 +550,8 @@ extern int symfile_map_offsets_to_segments (bfd *,
 struct symfile_segment_data *get_symfile_segment_data (bfd *abfd);
 void free_symfile_segment_data (struct symfile_segment_data *data);
 
+extern struct cleanup *increment_reading_symtab (void);
+
 /* From dwarf2read.c */
 
 extern int dwarf2_has_info (struct objfile *);
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 1f3eb9e..8d3e1a6 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -39,6 +39,8 @@
 #include "gdb_string.h"
 #include "readline/readline.h"
 
+#include "psymtab.h"
+
 #ifndef DEV_TTY
 #define DEV_TTY "/dev/tty"
 #endif
@@ -58,19 +60,12 @@ FILE *std_err;
 static void dump_symtab (struct objfile *, struct symtab *,
 			 struct ui_file *);
 
-static void dump_psymtab (struct objfile *, struct partial_symtab *,
-			  struct ui_file *);
-
 static void dump_msymbols (struct objfile *, struct ui_file *);
 
 static void dump_objfile (struct objfile *);
 
 static int block_depth (struct block *);
 
-static void print_partial_symbols (struct gdbarch *,
-				   struct partial_symbol **, int,
-				   char *, struct ui_file *);
-
 void _initialize_symmisc (void);
 
 struct print_symbol_args
@@ -151,7 +146,6 @@ print_objfile_statistics (void)
   struct program_space *pspace;
   struct objfile *objfile;
   struct symtab *s;
-  struct partial_symtab *ps;
   int i, linetables, blockvectors;
 
   immediate_quit++;
@@ -174,13 +168,8 @@ print_objfile_statistics (void)
     if (OBJSTAT (objfile, n_types) > 0)
       printf_filtered (_("  Number of \"types\" defined: %d\n"),
 		       OBJSTAT (objfile, n_types));
-    i = 0;
-    ALL_OBJFILE_PSYMTABS (objfile, ps)
-      {
-        if (ps->readin == 0)
-          i++;
-      }
-    printf_filtered (_("  Number of psym tables (not yet expanded): %d\n"), i);
+    if (objfile->sf)
+      objfile->sf->qf->print_stats (objfile);
     i = linetables = blockvectors = 0;
     ALL_OBJFILE_SYMTABS (objfile, s)
       {
@@ -215,7 +204,6 @@ static void
 dump_objfile (struct objfile *objfile)
 {
   struct symtab *symtab;
-  struct partial_symtab *psymtab;
 
   printf_filtered ("\nObject file %s:  ", objfile->name);
   printf_filtered ("Objfile at ");
@@ -225,25 +213,8 @@ dump_objfile (struct objfile *objfile)
   printf_filtered (", %d minsyms\n\n",
 		   objfile->minimal_symbol_count);
 
-  if (objfile->psymtabs)
-    {
-      printf_filtered ("Psymtabs:\n");
-      for (psymtab = objfile->psymtabs;
-	   psymtab != NULL;
-	   psymtab = psymtab->next)
-	{
-	  printf_filtered ("%s at ",
-			   psymtab->filename);
-	  gdb_print_host_address (psymtab, gdb_stdout);
-	  printf_filtered (", ");
-	  if (psymtab->objfile != objfile)
-	    {
-	      printf_filtered ("NOT ON CHAIN!  ");
-	    }
-	  wrap_here ("  ");
-	}
-      printf_filtered ("\n\n");
-    }
+  if (objfile->sf)
+    objfile->sf->qf->dump (objfile);
 
   if (objfile->symtabs)
     {
@@ -345,76 +316,6 @@ dump_msymbols (struct objfile *objfile, struct ui_file *outfile)
 }
 
 static void
-dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
-	      struct ui_file *outfile)
-{
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  int i;
-
-  fprintf_filtered (outfile, "\nPartial symtab for source file %s ",
-		    psymtab->filename);
-  fprintf_filtered (outfile, "(object ");
-  gdb_print_host_address (psymtab, outfile);
-  fprintf_filtered (outfile, ")\n\n");
-  fprintf_unfiltered (outfile, "  Read from object file %s (",
-		      objfile->name);
-  gdb_print_host_address (objfile, outfile);
-  fprintf_unfiltered (outfile, ")\n");
-
-  if (psymtab->readin)
-    {
-      fprintf_filtered (outfile,
-			"  Full symtab was read (at ");
-      gdb_print_host_address (psymtab->symtab, outfile);
-      fprintf_filtered (outfile, " by function at ");
-      gdb_print_host_address (psymtab->read_symtab, outfile);
-      fprintf_filtered (outfile, ")\n");
-    }
-
-  fprintf_filtered (outfile, "  Relocate symbols by ");
-  for (i = 0; i < psymtab->objfile->num_sections; ++i)
-    {
-      if (i != 0)
-	fprintf_filtered (outfile, ", ");
-      wrap_here ("    ");
-      fputs_filtered (paddress (gdbarch,
-				ANOFFSET (psymtab->section_offsets, i)),
-		      outfile);
-    }
-  fprintf_filtered (outfile, "\n");
-
-  fprintf_filtered (outfile, "  Symbols cover text addresses ");
-  fputs_filtered (paddress (gdbarch, psymtab->textlow), outfile);
-  fprintf_filtered (outfile, "-");
-  fputs_filtered (paddress (gdbarch, psymtab->texthigh), outfile);
-  fprintf_filtered (outfile, "\n");
-  fprintf_filtered (outfile, "  Depends on %d other partial symtabs.\n",
-		    psymtab->number_of_dependencies);
-  for (i = 0; i < psymtab->number_of_dependencies; i++)
-    {
-      fprintf_filtered (outfile, "    %d ", i);
-      gdb_print_host_address (psymtab->dependencies[i], outfile);
-      fprintf_filtered (outfile, " %s\n",
-			psymtab->dependencies[i]->filename);
-    }
-  if (psymtab->n_global_syms > 0)
-    {
-      print_partial_symbols (gdbarch,
-			     objfile->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
-			     + psymtab->statics_offset,
-			     psymtab->n_static_syms, "Static", outfile);
-    }
-  fprintf_filtered (outfile, "\n");
-}
-
-static void
 dump_symtab_1 (struct objfile *objfile, struct symtab *symtab,
 	       struct ui_file *outfile)
 {
@@ -750,142 +651,6 @@ print_symbol (void *args)
 }
 
 void
-maintenance_print_psymbols (char *args, int from_tty)
-{
-  char **argv;
-  struct ui_file *outfile;
-  struct cleanup *cleanups;
-  char *symname = NULL;
-  char *filename = DEV_TTY;
-  struct objfile *objfile;
-  struct partial_symtab *ps;
-
-  dont_repeat ();
-
-  if (args == NULL)
-    {
-      error (_("print-psymbols takes an output file name and optional symbol file name"));
-    }
-  argv = gdb_buildargv (args);
-  cleanups = make_cleanup_freeargv (argv);
-
-  if (argv[0] != NULL)
-    {
-      filename = argv[0];
-      /* If a second arg is supplied, it is a source file name to match on */
-      if (argv[1] != NULL)
-	{
-	  symname = argv[1];
-	}
-    }
-
-  filename = tilde_expand (filename);
-  make_cleanup (xfree, filename);
-
-  outfile = gdb_fopen (filename, FOPEN_WT);
-  if (outfile == 0)
-    perror_with_name (filename);
-  make_cleanup_ui_file_delete (outfile);
-
-  immediate_quit++;
-  ALL_PSYMTABS (objfile, ps)
-    if (symname == NULL || strcmp (symname, ps->filename) == 0)
-    dump_psymtab (objfile, ps, outfile);
-  immediate_quit--;
-  do_cleanups (cleanups);
-}
-
-static void
-print_partial_symbols (struct gdbarch *gdbarch,
-		       struct partial_symbol **p, int count, char *what,
-		       struct ui_file *outfile)
-{
-  fprintf_filtered (outfile, "  %s partial symbols:\n", what);
-  while (count-- > 0)
-    {
-      fprintf_filtered (outfile, "    `%s'", SYMBOL_LINKAGE_NAME (*p));
-      if (SYMBOL_DEMANGLED_NAME (*p) != NULL)
-	{
-	  fprintf_filtered (outfile, "  `%s'", SYMBOL_DEMANGLED_NAME (*p));
-	}
-      fputs_filtered (", ", outfile);
-      switch (SYMBOL_DOMAIN (*p))
-	{
-	case UNDEF_DOMAIN:
-	  fputs_filtered ("undefined domain, ", outfile);
-	  break;
-	case VAR_DOMAIN:
-	  /* This is the usual thing -- don't print it */
-	  break;
-	case STRUCT_DOMAIN:
-	  fputs_filtered ("struct domain, ", outfile);
-	  break;
-	case LABEL_DOMAIN:
-	  fputs_filtered ("label domain, ", outfile);
-	  break;
-	default:
-	  fputs_filtered ("<invalid domain>, ", outfile);
-	  break;
-	}
-      switch (SYMBOL_CLASS (*p))
-	{
-	case LOC_UNDEF:
-	  fputs_filtered ("undefined", outfile);
-	  break;
-	case LOC_CONST:
-	  fputs_filtered ("constant int", outfile);
-	  break;
-	case LOC_STATIC:
-	  fputs_filtered ("static", outfile);
-	  break;
-	case LOC_REGISTER:
-	  fputs_filtered ("register", outfile);
-	  break;
-	case LOC_ARG:
-	  fputs_filtered ("pass by value", outfile);
-	  break;
-	case LOC_REF_ARG:
-	  fputs_filtered ("pass by reference", outfile);
-	  break;
-	case LOC_REGPARM_ADDR:
-	  fputs_filtered ("register address parameter", outfile);
-	  break;
-	case LOC_LOCAL:
-	  fputs_filtered ("stack parameter", outfile);
-	  break;
-	case LOC_TYPEDEF:
-	  fputs_filtered ("type", outfile);
-	  break;
-	case LOC_LABEL:
-	  fputs_filtered ("label", outfile);
-	  break;
-	case LOC_BLOCK:
-	  fputs_filtered ("function", outfile);
-	  break;
-	case LOC_CONST_BYTES:
-	  fputs_filtered ("constant bytes", outfile);
-	  break;
-	case LOC_UNRESOLVED:
-	  fputs_filtered ("unresolved", outfile);
-	  break;
-	case LOC_OPTIMIZED_OUT:
-	  fputs_filtered ("optimized out", outfile);
-	  break;
-	case LOC_COMPUTED:
-	  fputs_filtered ("computed at runtime", outfile);
-	  break;
-	default:
-	  fputs_filtered ("<invalid location>", outfile);
-	  break;
-	}
-      fputs_filtered (", ", outfile);
-      fputs_filtered (paddress (gdbarch, SYMBOL_VALUE_ADDRESS (*p)), outfile);
-      fprintf_filtered (outfile, "\n");
-      p++;
-    }
-}
-
-void
 maintenance_print_msymbols (char *args, int from_tty)
 {
   char **argv;
@@ -1012,194 +777,6 @@ maintenance_info_symtabs (char *regexp, int from_tty)
         printf_filtered ("}\n");
     }
 }
-
-
-/* List all the partial symbol tables whose names match REGEXP (optional).  */
-void
-maintenance_info_psymtabs (char *regexp, int from_tty)
-{
-  struct program_space *pspace;
-  struct objfile *objfile;
-
-  if (regexp)
-    re_comp (regexp);
-
-  ALL_PSPACES (pspace)
-    ALL_PSPACE_OBJFILES (pspace, objfile)
-    {
-      struct gdbarch *gdbarch = get_objfile_arch (objfile);
-      struct partial_symtab *psymtab;
-
-      /* We don't want to print anything for this objfile until we
-         actually find a symtab whose name matches.  */
-      int printed_objfile_start = 0;
-
-      ALL_OBJFILE_PSYMTABS (objfile, psymtab)
-	{
-	  QUIT;
-
-	  if (! regexp
-	      || re_exec (psymtab->filename))
-	    {
-	      if (! printed_objfile_start)
-		{
-		  printf_filtered ("{ objfile %s ", objfile->name);
-		  wrap_here ("  ");
-		  printf_filtered ("((struct objfile *) %s)\n", 
-				   host_address_to_string (objfile));
-		  printed_objfile_start = 1;
-		}
-
-	      printf_filtered ("  { psymtab %s ", psymtab->filename);
-	      wrap_here ("    ");
-	      printf_filtered ("((struct partial_symtab *) %s)\n", 
-			       host_address_to_string (psymtab));
-
-	      printf_filtered ("    readin %s\n",
-			       psymtab->readin ? "yes" : "no");
-	      printf_filtered ("    fullname %s\n",
-			       psymtab->fullname ? psymtab->fullname : "(null)");
-	      printf_filtered ("    text addresses ");
-	      fputs_filtered (paddress (gdbarch, psymtab->textlow),
-			      gdb_stdout);
-	      printf_filtered (" -- ");
-	      fputs_filtered (paddress (gdbarch, psymtab->texthigh),
-			      gdb_stdout);
-	      printf_filtered ("\n");
-	      printf_filtered ("    globals ");
-	      if (psymtab->n_global_syms)
-		{
-		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
-				   host_address_to_string (psymtab->objfile->global_psymbols.list
-				    + psymtab->globals_offset),
-				   psymtab->n_global_syms);
-		}
-	      else
-		printf_filtered ("(none)\n");
-	      printf_filtered ("    statics ");
-	      if (psymtab->n_static_syms)
-		{
-		  printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
-				   host_address_to_string (psymtab->objfile->static_psymbols.list
-				    + psymtab->statics_offset),
-				   psymtab->n_static_syms);
-		}
-	      else
-		printf_filtered ("(none)\n");
-	      printf_filtered ("    dependencies ");
-	      if (psymtab->number_of_dependencies)
-		{
-		  int i;
-
-		  printf_filtered ("{\n");
-		  for (i = 0; i < psymtab->number_of_dependencies; i++)
-		    {
-		      struct partial_symtab *dep = psymtab->dependencies[i];
-
-		      /* Note the string concatenation there --- no comma.  */
-		      printf_filtered ("      psymtab %s "
-				       "((struct partial_symtab *) %s)\n",
-				       dep->filename, 
-				       host_address_to_string (dep));
-		    }
-		  printf_filtered ("    }\n");
-		}
-	      else
-		printf_filtered ("(none)\n");
-	      printf_filtered ("  }\n");
-	    }
-	}
-
-      if (printed_objfile_start)
-        printf_filtered ("}\n");
-    }
-}
-
-
-/* Check consistency of psymtabs and symtabs.  */
-
-void
-maintenance_check_symtabs (char *ignore, int from_tty)
-{
-  struct symbol *sym;
-  struct partial_symbol **psym;
-  struct symtab *s = NULL;
-  struct partial_symtab *ps;
-  struct blockvector *bv;
-  struct objfile *objfile;
-  struct block *b;
-  int length;
-
-  ALL_PSYMTABS (objfile, ps)
-  {
-    struct gdbarch *gdbarch = get_objfile_arch (objfile);
-    s = PSYMTAB_TO_SYMTAB (ps);
-    if (s == NULL)
-      continue;
-    bv = BLOCKVECTOR (s);
-    b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-    psym = ps->objfile->static_psymbols.list + ps->statics_offset;
-    length = ps->n_static_syms;
-    while (length--)
-      {
-	sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
-				   NULL, SYMBOL_DOMAIN (*psym));
-	if (!sym)
-	  {
-	    printf_filtered ("Static symbol `");
-	    puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
-	    printf_filtered ("' only found in ");
-	    puts_filtered (ps->filename);
-	    printf_filtered (" psymtab\n");
-	  }
-	psym++;
-      }
-    b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-    psym = ps->objfile->global_psymbols.list + ps->globals_offset;
-    length = ps->n_global_syms;
-    while (length--)
-      {
-	sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
-				   NULL, SYMBOL_DOMAIN (*psym));
-	if (!sym)
-	  {
-	    printf_filtered ("Global symbol `");
-	    puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
-	    printf_filtered ("' only found in ");
-	    puts_filtered (ps->filename);
-	    printf_filtered (" psymtab\n");
-	  }
-	psym++;
-      }
-    if (ps->texthigh < ps->textlow)
-      {
-	printf_filtered ("Psymtab ");
-	puts_filtered (ps->filename);
-	printf_filtered (" covers bad range ");
-	fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
-	printf_filtered (" - ");
-	fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
-	printf_filtered ("\n");
-	continue;
-      }
-    if (ps->texthigh == 0)
-      continue;
-    if (ps->textlow < BLOCK_START (b) || ps->texthigh > BLOCK_END (b))
-      {
-	printf_filtered ("Psymtab ");
-	puts_filtered (ps->filename);
-	printf_filtered (" covers ");
-	fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
-	printf_filtered (" - ");
-	fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
-	printf_filtered (" but symtab covers only ");
-	fputs_filtered (paddress (gdbarch, BLOCK_START (b)), gdb_stdout);
-	printf_filtered (" - ");
-	fputs_filtered (paddress (gdbarch, BLOCK_END (b)), gdb_stdout);
-	printf_filtered ("\n");
-      }
-  }
-}
 
 
 /* Return the nexting depth of a block within other blocks in its symtab.  */
@@ -1216,35 +793,6 @@ block_depth (struct block *block)
 }
 
 
-/* Increase the space allocated for LISTP, which is probably
-   global_psymbols or static_psymbols. This space will eventually
-   be freed in free_objfile().  */
-
-void
-extend_psymbol_list (struct psymbol_allocation_list *listp,
-		     struct objfile *objfile)
-{
-  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;
-}
-
-
 /* Do early runtime initializations. */
 void
 _initialize_symmisc (void)
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 7f5dabd..b16d1f0 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -62,6 +62,8 @@
 #include "macrotab.h"
 #include "macroscope.h"
 
+#include "psymtab.h"
+
 /* Prototypes for local functions */
 
 static void completion_list_add_name (char *, char *, int, char *, char *);
@@ -104,12 +106,11 @@ struct symbol *lookup_symbol_aux_symtabs (int block_index,
 					  const domain_enum domain);
 
 static
-struct symbol *lookup_symbol_aux_psymtabs (int block_index,
-					   const char *name,
-					   const char *linkage_name,
-					   const domain_enum domain);
-
-static int file_matches (char *, char **, int);
+struct symbol *lookup_symbol_aux_quick (struct objfile *objfile,
+					int block_index,
+					const char *name,
+					const char *linkage_name,
+					const domain_enum domain);
 
 static void print_symbol_info (domain_enum,
 			       struct symtab *, struct symbol *, int, char *);
@@ -159,8 +160,8 @@ const struct block *block_found;
 struct symtab *
 lookup_symtab (const char *name)
 {
-  struct symtab *s;
-  struct partial_symtab *ps;
+  int found;
+  struct symtab *s = NULL;
   struct objfile *objfile;
   char *real_path = NULL;
   char *full_path = NULL;
@@ -225,18 +226,22 @@ got_symtab:
   /* Same search rules as above apply here, but now we look thru the
      psymtabs.  */
 
-  ps = lookup_partial_symtab (name);
-  if (!ps)
-    return (NULL);
-
-  if (ps->readin)
-    error (_("Internal: readin %s pst for `%s' found when no symtab found."),
-	   ps->filename, name);
-
-  s = PSYMTAB_TO_SYMTAB (ps);
+  found = 0;
+  ALL_OBJFILES (objfile)
+  {
+    if (objfile->sf
+	&& objfile->sf->qf->lookup_symtab (objfile, name, full_path, real_path,
+					   &s))
+      {
+	found = 1;
+	break;
+      }
+  }
 
-  if (s)
+  if (s != NULL)
     return s;
+  if (!found)
+    return NULL;
 
   /* At this point, we have located the psymtab for this file, but
      the conversion to a symtab has failed.  This usually happens
@@ -248,75 +253,6 @@ got_symtab:
      symbol parsing routines. */
   goto got_symtab;
 }
-
-/* 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.  */
-
-struct partial_symtab *
-lookup_partial_symtab (const char *name)
-{
-  struct partial_symtab *pst;
-  struct objfile *objfile;
-  char *full_path = NULL;
-  char *real_path = NULL;
-
-  /* Here we are interested in canonicalizing an absolute path, not
-     absolutizing a relative path.  */
-  if (IS_ABSOLUTE_PATH (name))
-    {
-      full_path = xfullpath (name);
-      make_cleanup (xfree, full_path);
-      real_path = gdb_realpath (name);
-      make_cleanup (xfree, real_path);
-    }
-
-  ALL_PSYMTABS (objfile, pst)
-  {
-    if (FILENAME_CMP (name, pst->filename) == 0)
-      {
-	return (pst);
-      }
-
-    /* If the user gave us an absolute path, try to find the file in
-       this symtab and use its absolute path.  */
-    if (full_path != NULL)
-      {
-	psymtab_to_fullname (pst);
-	if (pst->fullname != NULL
-	    && FILENAME_CMP (full_path, pst->fullname) == 0)
-	  {
-	    return pst;
-	  }
-      }
-
-    if (real_path != NULL)
-      {
-        char *rp = NULL;
-	psymtab_to_fullname (pst);
-        if (pst->fullname != NULL)
-          {
-            rp = gdb_realpath (pst->fullname);
-            make_cleanup (xfree, rp);
-          }
-	if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
-	  {
-	    return pst;
-	  }
-      }
-  }
-
-  /* Now, search for a matching tail (only if name doesn't have any dirs) */
-
-  if (lbasename (name) == name)
-    ALL_PSYMTABS (objfile, pst)
-    {
-      if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
-	return (pst);
-    }
-
-  return (NULL);
-}
 
 /* Mangle a GDB method stub type.  This actually reassembles the pieces of the
    full method name, which consist of the class name (from T), the unadorned
@@ -828,89 +764,8 @@ matching_obj_sections (struct obj_section *obj_first,
   return 0;
 }
 
-/* Find which partial symtab contains PC and SECTION starting at psymtab PST.
-   We may find a different psymtab than PST.  See FIND_PC_SECT_PSYMTAB.  */
-
-static struct partial_symtab *
-find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section,
-			     struct partial_symtab *pst,
-			     struct minimal_symbol *msymbol)
-{
-  struct objfile *objfile = pst->objfile;
-  struct partial_symtab *tpst;
-  struct partial_symtab *best_pst = pst;
-  CORE_ADDR best_addr = pst->textlow;
-
-  /* An objfile that has its functions reordered might have
-     many partial symbol tables containing the PC, but
-     we want the partial symbol table that contains the
-     function containing the PC.  */
-  if (!(objfile->flags & OBJF_REORDERED) &&
-      section == 0)	/* can't validate section this way */
-    return pst;
-
-  if (msymbol == NULL)
-    return (pst);
-
-  /* The code range of partial symtabs sometimes overlap, so, in
-     the loop below, we need to check all partial symtabs and
-     find the one that fits better for the given PC address. We
-     select the partial symtab that contains a symbol whose
-     address is closest to the PC address.  By closest we mean
-     that find_pc_sect_symbol returns the symbol with address
-     that is closest and still less than the given PC.  */
-  for (tpst = pst; tpst != NULL; tpst = tpst->next)
-    {
-      if (pc >= tpst->textlow && pc < tpst->texthigh)
-	{
-	  struct partial_symbol *p;
-	  CORE_ADDR this_addr;
-
-	  /* NOTE: This assumes that every psymbol has a
-	     corresponding msymbol, which is not necessarily
-	     true; the debug info might be much richer than the
-	     object's symbol table.  */
-	  p = find_pc_sect_psymbol (tpst, pc, section);
-	  if (p != NULL
-	      && SYMBOL_VALUE_ADDRESS (p)
-	      == SYMBOL_VALUE_ADDRESS (msymbol))
-	    return tpst;
-
-	  /* Also accept the textlow value of a psymtab as a
-	     "symbol", to provide some support for partial
-	     symbol tables with line information but no debug
-	     symbols (e.g. those produced by an assembler).  */
-	  if (p != NULL)
-	    this_addr = SYMBOL_VALUE_ADDRESS (p);
-	  else
-	    this_addr = tpst->textlow;
-
-	  /* Check whether it is closer than our current
-	     BEST_ADDR.  Since this symbol address is
-	     necessarily lower or equal to PC, the symbol closer
-	     to PC is the symbol which address is the highest.
-	     This way we return the psymtab which contains such
-	     best match symbol. This can help in cases where the
-	     symbol information/debuginfo is not complete, like
-	     for instance on IRIX6 with gcc, where no debug info
-	     is emitted for statics. (See also the nodebug.exp
-	     testcase.) */
-	  if (this_addr > best_addr)
-	    {
-	      best_addr = this_addr;
-	      best_pst = tpst;
-	    }
-	}
-    }
-  return best_pst;
-}
-
-/* Find which partial symtab contains PC and SECTION.  Return 0 if
-   none.  We return the psymtab that contains a symbol whose address
-   exactly matches PC, or, if we cannot find an exact match, the
-   psymtab that contains a symbol whose address is closest to PC.  */
-struct partial_symtab *
-find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
+struct symtab *
+find_pc_sect_symtab_via_partial (CORE_ADDR pc, struct obj_section *section)
 {
   struct objfile *objfile;
   struct minimal_symbol *msymbol;
@@ -927,166 +782,23 @@ find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
 	  || MSYMBOL_TYPE (msymbol) == mst_file_bss))
     return NULL;
 
-  /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
-     than the later used TEXTLOW/TEXTHIGH one.  */
-
-  ALL_OBJFILES (objfile)
-    if (objfile->psymtabs_addrmap != NULL)
-      {
-	struct partial_symtab *pst;
-
-	pst = addrmap_find (objfile->psymtabs_addrmap, pc);
-	if (pst != NULL)
-	  {
-	    /* FIXME: addrmaps currently do not handle overlayed sections,
-	       so fall back to the non-addrmap case if we're debugging
-	       overlays and the addrmap returned the wrong section.  */
-	    if (overlay_debugging && msymbol && section)
-	      {
-		struct partial_symbol *p;
-		/* NOTE: This assumes that every psymbol has a
-		   corresponding msymbol, which is not necessarily
-		   true; the debug info might be much richer than the
-		   object's symbol table.  */
-		p = find_pc_sect_psymbol (pst, pc, section);
-		if (!p
-		    || SYMBOL_VALUE_ADDRESS (p)
-		       != SYMBOL_VALUE_ADDRESS (msymbol))
-		  continue;
-	      }
-
-	    /* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as
-	       PSYMTABS_ADDRMAP we used has already the best 1-byte
-	       granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into
-	       a worse chosen section due to the TEXTLOW/TEXTHIGH ranges
-	       overlap.  */
-
-	    return pst;
-	  }
-      }
-
-  /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
-     which still have no corresponding full SYMTABs read.  But it is not
-     present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
-     so far.  */
-
   ALL_OBJFILES (objfile)
-    {
-      struct partial_symtab *pst;
-
-      /* Check even OBJFILE with non-zero PSYMTABS_ADDRMAP as only several of
-	 its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying
-	 debug info type in single OBJFILE.  */
-
-      ALL_OBJFILE_PSYMTABS (objfile, pst)
-	if (pc >= pst->textlow && pc < pst->texthigh)
-	  {
-	    struct partial_symtab *best_pst;
-
-	    best_pst = find_pc_sect_psymtab_closer (pc, section, pst,
-						    msymbol);
-	    if (best_pst != NULL)
-	      return best_pst;
-	  }
-    }
+  {
+    struct symtab *result = NULL;
+    if (objfile->sf)
+      result = objfile->sf->qf->find_pc_sect_symtab (objfile, msymbol,
+						     pc, section, 0);
+    if (result)
+      return result;
+  }
 
   return NULL;
 }
-
-/* Find which partial symtab contains PC.  Return 0 if none.
-   Backward compatibility, no section */
-
-struct partial_symtab *
-find_pc_psymtab (CORE_ADDR pc)
-{
-  return find_pc_sect_psymtab (pc, find_pc_mapped_section (pc));
-}
-
-/* Find which partial symbol within a psymtab matches PC and SECTION.
-   Return 0 if none.  Check all psymtabs if PSYMTAB is 0.  */
-
-struct partial_symbol *
-find_pc_sect_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc,
-		      struct obj_section *section)
-{
-  struct partial_symbol *best = NULL, *p, **pp;
-  CORE_ADDR best_pc;
-
-  if (!psymtab)
-    psymtab = find_pc_sect_psymtab (pc, section);
-  if (!psymtab)
-    return 0;
-
-  /* Cope with programs that start at address 0 */
-  best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0;
-
-  /* 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)
-     < psymtab->n_global_syms);
-       pp++)
-    {
-      p = *pp;
-      if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
-	  && SYMBOL_CLASS (p) == LOC_BLOCK
-	  && pc >= SYMBOL_VALUE_ADDRESS (p)
-	  && (SYMBOL_VALUE_ADDRESS (p) > best_pc
-	      || (psymtab->textlow == 0
-		  && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
-	{
-	  if (section)		/* match on a specific section */
-	    {
-	      fixup_psymbol_section (p, psymtab->objfile);
-	      if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
-		continue;
-	    }
-	  best_pc = SYMBOL_VALUE_ADDRESS (p);
-	  best = p;
-	}
-    }
-
-  for (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
-    (pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
-     < psymtab->n_static_syms);
-       pp++)
-    {
-      p = *pp;
-      if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
-	  && SYMBOL_CLASS (p) == LOC_BLOCK
-	  && pc >= SYMBOL_VALUE_ADDRESS (p)
-	  && (SYMBOL_VALUE_ADDRESS (p) > best_pc
-	      || (psymtab->textlow == 0
-		  && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
-	{
-	  if (section)		/* match on a specific section */
-	    {
-	      fixup_psymbol_section (p, psymtab->objfile);
-	      if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
-		continue;
-	    }
-	  best_pc = SYMBOL_VALUE_ADDRESS (p);
-	  best = p;
-	}
-    }
-
-  return best;
-}
-
-/* Find which partial symbol within a psymtab matches PC.  Return 0 if none.
-   Check all psymtabs if PSYMTAB is 0.  Backwards compatibility, no section. */
-
-struct partial_symbol *
-find_pc_psymbol (struct partial_symtab *psymtab, CORE_ADDR pc)
-{
-  return find_pc_sect_psymbol (psymtab, pc, find_pc_mapped_section (pc));
-}
 
 /* Debug symbols usually don't have section information.  We need to dig that
    out of the minimal symbols and stash that in the debug symbol.  */
 
-static void
+void
 fixup_section (struct general_symbol_info *ginfo,
 	       CORE_ADDR addr, struct objfile *objfile)
 {
@@ -1200,37 +912,6 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
   return sym;
 }
 
-struct partial_symbol *
-fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
-{
-  CORE_ADDR addr;
-
-  if (!psym)
-    return NULL;
-
-  if (SYMBOL_OBJ_SECTION (psym))
-    return psym;
-
-  gdb_assert (objfile);
-
-  switch (SYMBOL_CLASS (psym))
-    {
-    case LOC_STATIC:
-    case LOC_LABEL:
-    case LOC_BLOCK:
-      addr = SYMBOL_VALUE_ADDRESS (psym);
-      break;
-    default:
-      /* Nothing else will be listed in the minsyms -- no use looking
-	 it up.  */
-      return psym;
-    }
-
-  fixup_section (&psym->ginfo, addr, objfile);
-
-  return psym;
-}
-
 /* Find the definition for a specified symbol name NAME
    in domain DOMAIN, visible from lexical block BLOCK.
    Returns the struct symbol pointer, or zero if no symbol is found.
@@ -1342,6 +1023,7 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
 {
   struct symbol *sym;
   const struct language_defn *langdef;
+  struct objfile *objfile;
 
   /* Make sure we do something sensible with is_a_field_of_this, since
      the callers that set this parameter to some non-null value will
@@ -1416,9 +1098,13 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
   if (sym != NULL)
     return sym;
 
-  sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, linkage_name, domain);
-  if (sym != NULL)
-    return sym;
+  ALL_OBJFILES (objfile)
+  {
+    sym = lookup_symbol_aux_quick (objfile, STATIC_BLOCK, name,
+				   linkage_name, domain);
+    if (sym != NULL)
+      return sym;
+  }
 
   return NULL;
 }
@@ -1509,7 +1195,6 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
   struct blockvector *bv;
   const struct block *block;
   struct symtab *s;
-  struct partial_symtab *ps;
 
   for (objfile = main_objfile;
        objfile;
@@ -1528,20 +1213,10 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
             }
         }
 
-      /* Now go through psymtabs.  */
-      ALL_OBJFILE_PSYMTABS (objfile, ps)
-        {
-          if (!ps->readin
-              && lookup_partial_symbol (ps, name, linkage_name,
-                                        1, domain))
-            {
-              s = PSYMTAB_TO_SYMTAB (ps);
-              bv = BLOCKVECTOR (s);
-              block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-              sym = lookup_block_symbol (block, name, linkage_name, domain);
-              return fixup_symbol_section (sym, (struct objfile *)objfile);
-            }
-        }
+      sym = lookup_symbol_aux_quick ((struct objfile *) objfile, GLOBAL_BLOCK,
+				     name, linkage_name, domain);
+      if (sym)
+	return sym;
     }
 
   return NULL;
@@ -1578,61 +1253,53 @@ lookup_symbol_aux_symtabs (int block_index,
   return NULL;
 }
 
-/* Check to see if the symbol is defined in one of the partial
-   symtabs.  BLOCK_INDEX should be either GLOBAL_BLOCK or
-   STATIC_BLOCK, depending on whether or not we want to search global
-   symbols or static symbols.  */
+/* A helper function for lookup_symbol_aux that interfaces with the
+   "quick" symbol table functions.  */
 
 static struct symbol *
-lookup_symbol_aux_psymtabs (int block_index, const char *name,
-			    const char *linkage_name,
-			    const domain_enum domain)
+lookup_symbol_aux_quick (struct objfile *objfile, int kind,
+			 const char *name, const char *linkage_name,
+			 const domain_enum domain)
 {
-  struct symbol *sym;
-  struct objfile *objfile;
+  struct symtab *symtab;
   struct blockvector *bv;
   const struct block *block;
   struct partial_symtab *ps;
-  struct symtab *s;
-  const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
+  struct symbol *sym;
 
-  ALL_PSYMTABS (objfile, ps)
-  {
-    if (!ps->readin
-	&& lookup_partial_symbol (ps, name, linkage_name,
-				  psymtab_index, domain))
-      {
-	s = PSYMTAB_TO_SYMTAB (ps);
-	bv = BLOCKVECTOR (s);
-	block = BLOCKVECTOR_BLOCK (bv, block_index);
-	sym = lookup_block_symbol (block, name, linkage_name, domain);
-	if (!sym)
-	  {
-	    /* This shouldn't be necessary, but as a last resort try
-	       looking in the statics even though the psymtab claimed
-	       the symbol was global, or vice-versa. It's possible
-	       that the psymtab gets it wrong in some cases.  */
-
-	    /* FIXME: carlton/2002-09-30: Should we really do that?
-	       If that happens, isn't it likely to be a GDB error, in
-	       which case we should fix the GDB error rather than
-	       silently dealing with it here?  So I'd vote for
-	       removing the check for the symbol in the other
-	       block.  */
-	    block = BLOCKVECTOR_BLOCK (bv,
-				       block_index == GLOBAL_BLOCK ?
-				       STATIC_BLOCK : GLOBAL_BLOCK);
-	    sym = lookup_block_symbol (block, name, linkage_name, domain);
-	    if (!sym)
-	      error (_("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s<type>)."),
-		     block_index == GLOBAL_BLOCK ? "global" : "static",
-		     name, ps->filename, name, name);
-	  }
-	return fixup_symbol_section (sym, objfile);
-      }
-  }
+  if (!objfile->sf)
+    return NULL;
+  symtab = objfile->sf->qf->lookup_symbol (objfile, kind, name,
+					   linkage_name, domain);
+  if (!symtab)
+    return NULL;
 
-  return NULL;
+  bv = BLOCKVECTOR (symtab);
+  block = BLOCKVECTOR_BLOCK (bv, kind);
+  sym = lookup_block_symbol (block, name, linkage_name, domain);
+  if (!sym)
+    {
+      /* This shouldn't be necessary, but as a last resort try
+	 looking in the statics even though the psymtab claimed
+	 the symbol was global, or vice-versa. It's possible
+	 that the psymtab gets it wrong in some cases.  */
+
+      /* FIXME: carlton/2002-09-30: Should we really do that?
+	 If that happens, isn't it likely to be a GDB error, in
+	 which case we should fix the GDB error rather than
+	 silently dealing with it here?  So I'd vote for
+	 removing the check for the symbol in the other
+	 block.  */
+      block = BLOCKVECTOR_BLOCK (bv,
+				 kind == GLOBAL_BLOCK ?
+				 STATIC_BLOCK : GLOBAL_BLOCK);
+      sym = lookup_block_symbol (block, name, linkage_name, domain);
+      if (!sym)
+	error (_("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s<type>)."),
+	       kind == GLOBAL_BLOCK ? "global" : "static",
+	       name, symtab->filename, name, name);
+    }
+  return fixup_symbol_section (sym, objfile);
 }
 
 /* A default version of lookup_symbol_nonlocal for use by languages
@@ -1722,7 +1389,15 @@ lookup_symbol_global (const char *name,
   if (sym != NULL)
     return sym;
 
-  return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, linkage_name, domain);
+  ALL_OBJFILES (objfile)
+  {
+    sym = lookup_symbol_aux_quick (objfile, GLOBAL_BLOCK, name,
+				   linkage_name, domain);
+    if (sym)
+      return sym;
+  }
+
+  return NULL;
 }
 
 int
@@ -1745,108 +1420,60 @@ symbol_matches_domain (enum language symbol_language,
   return (symbol_domain == domain);
 }
 
-/* Look, in partial_symtab PST, for symbol whose natural name is NAME.
-   If LINKAGE_NAME is non-NULL, check in addition that the symbol's
-   linkage name matches it.  Check the global symbols if GLOBAL, the
-   static symbols if not */
+/* Look up a type named NAME in the struct_domain.  The type returned
+   must not be opaque -- i.e., must have at least one field
+   defined.  */
 
-struct partial_symbol *
-lookup_partial_symbol (struct partial_symtab *pst, const char *name,
-		       const char *linkage_name, int global,
-		       domain_enum domain)
+struct type *
+lookup_transparent_type (const char *name)
 {
-  struct partial_symbol *temp;
-  struct partial_symbol **start, **psym;
-  struct partial_symbol **top, **real_top, **bottom, **center;
-  int length = (global ? pst->n_global_syms : pst->n_static_syms);
-  int do_linear_search = 1;
-
-  if (length == 0)
-    {
-      return (NULL);
-    }
-  start = (global ?
-	   pst->objfile->global_psymbols.list + pst->globals_offset :
-	   pst->objfile->static_psymbols.list + pst->statics_offset);
+  return current_language->la_lookup_transparent_type (name);
+}
 
-  if (global)			/* This means we can use a binary search. */
-    {
-      do_linear_search = 0;
-
-      /* Binary search.  This search is guaranteed to end with center
-         pointing at the earliest partial symbol whose name might be
-         correct.  At that point *all* partial symbols with an
-         appropriate name will be checked against the correct
-         domain.  */
-
-      bottom = start;
-      top = start + length - 1;
-      real_top = top;
-      while (top > bottom)
-	{
-	  center = bottom + (top - bottom) / 2;
-	  if (!(center < top))
-	    internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
-	  if (!do_linear_search
-	      && (SYMBOL_LANGUAGE (*center) == language_java))
-	    {
-	      do_linear_search = 1;
-	    }
-	  if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0)
-	    {
-	      top = center;
-	    }
-	  else
-	    {
-	      bottom = center + 1;
-	    }
-	}
-      if (!(top == bottom))
-	internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+/* A helper for basic_lookup_transparent_type that interfaces with the
+   "quick" symbol table functions.  */
 
-      while (top <= real_top
-	     && (linkage_name != NULL
-		 ? strcmp (SYMBOL_LINKAGE_NAME (*top), linkage_name) == 0
-		 : SYMBOL_MATCHES_SEARCH_NAME (*top,name)))
-	{
-	  if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
-				     SYMBOL_DOMAIN (*top), domain))
-	    return (*top);
-	  top++;
-	}
-    }
+static struct type *
+basic_lookup_transparent_type_quick (struct objfile *objfile, int kind,
+				     const char *name)
+{
+  struct symtab *symtab;
+  struct blockvector *bv;
+  struct block *block;
+  struct symbol *sym;
 
-  /* Can't use a binary search or else we found during the binary search that
-     we should also do a linear search. */
+  if (!objfile->sf)
+    return NULL;
+  symtab = objfile->sf->qf->lookup_symbol (objfile, kind, name, NULL,
+					   STRUCT_DOMAIN);
+  if (!symtab)
+    return NULL;
 
-  if (do_linear_search)
+  bv = BLOCKVECTOR (symtab);
+  block = BLOCKVECTOR_BLOCK (bv, kind);
+  sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+  if (!sym)
     {
-      for (psym = start; psym < start + length; psym++)
-	{
-	  if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
-				     SYMBOL_DOMAIN (*psym), domain))
-	    {
-	      if (linkage_name != NULL
-		  ? strcmp (SYMBOL_LINKAGE_NAME (*psym), linkage_name) == 0
-		  : SYMBOL_MATCHES_SEARCH_NAME (*psym, name))
-		{
-		  return (*psym);
-		}
-	    }
-	}
+      int other_kind = kind == GLOBAL_BLOCK ? STATIC_BLOCK : GLOBAL_BLOCK;
+
+      /* This shouldn't be necessary, but as a last resort
+       * try looking in the 'other kind' even though the psymtab
+       * claimed the symbol was one thing. It's possible that
+       * the psymtab gets it wrong in some cases.
+       */
+      block = BLOCKVECTOR_BLOCK (bv, other_kind);
+      sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+      if (!sym)
+	/* FIXME; error is wrong in one case */
+	error (_("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
+%s may be an inlined function, or may be a template function\n\
+(if a template, try specifying an instantiation: %s<type>)."),
+	       name, symtab->filename, name, name);
     }
+  if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+    return SYMBOL_TYPE (sym);
 
-  return (NULL);
-}
-
-/* Look up a type named NAME in the struct_domain.  The type returned
-   must not be opaque -- i.e., must have at least one field
-   defined.  */
-
-struct type *
-lookup_transparent_type (const char *name)
-{
-  return current_language->la_lookup_transparent_type (name);
+  return NULL;
 }
 
 /* The standard implementation of lookup_transparent_type.  This code
@@ -1860,10 +1487,10 @@ basic_lookup_transparent_type (const char *name)
 {
   struct symbol *sym;
   struct symtab *s = NULL;
-  struct partial_symtab *ps;
   struct blockvector *bv;
   struct objfile *objfile;
   struct block *block;
+  struct type *t;
 
   /* Now search all the global symbols.  Do the symtab's first, then
      check the psymtab's. If a psymtab indicates the existence
@@ -1881,33 +1508,11 @@ basic_lookup_transparent_type (const char *name)
       }
   }
 
-  ALL_PSYMTABS (objfile, ps)
+  ALL_OBJFILES (objfile)
   {
-    if (!ps->readin && lookup_partial_symbol (ps, name, NULL,
-					      1, STRUCT_DOMAIN))
-      {
-	s = PSYMTAB_TO_SYMTAB (ps);
-	bv = BLOCKVECTOR (s);
-	block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-	sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
-	if (!sym)
-	  {
-	    /* This shouldn't be necessary, but as a last resort
-	     * try looking in the statics even though the psymtab
-	     * claimed the symbol was global. It's possible that
-	     * the psymtab gets it wrong in some cases.
-	     */
-	    block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-	    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
-	    if (!sym)
-	      error (_("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
-%s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>)."),
-		     name, ps->filename, name, name);
-	  }
-	if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
-	  return SYMBOL_TYPE (sym);
-      }
+    t = basic_lookup_transparent_type_quick (objfile, GLOBAL_BLOCK, name);
+    if (t)
+      return t;
   }
 
   /* Now search the static file-level symbols.
@@ -1929,53 +1534,34 @@ basic_lookup_transparent_type (const char *name)
       }
   }
 
-  ALL_PSYMTABS (objfile, ps)
+  ALL_OBJFILES (objfile)
   {
-    if (!ps->readin && lookup_partial_symbol (ps, name, NULL, 0, STRUCT_DOMAIN))
-      {
-	s = PSYMTAB_TO_SYMTAB (ps);
-	bv = BLOCKVECTOR (s);
-	block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-	sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
-	if (!sym)
-	  {
-	    /* This shouldn't be necessary, but as a last resort
-	     * try looking in the globals even though the psymtab
-	     * claimed the symbol was static. It's possible that
-	     * the psymtab gets it wrong in some cases.
-	     */
-	    block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-	    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
-	    if (!sym)
-	      error (_("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
-%s may be an inlined function, or may be a template function\n\
-(if a template, try specifying an instantiation: %s<type>)."),
-		     name, ps->filename, name, name);
-	  }
-	if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
-	  return SYMBOL_TYPE (sym);
-      }
+    t = basic_lookup_transparent_type_quick (objfile, STATIC_BLOCK, name);
+    if (t)
+      return t;
   }
+
   return (struct type *) 0;
 }
 
 
-/* Find the psymtab containing main(). */
+/* Find the name of the file containing main(). */
 /* FIXME:  What about languages without main() or specially linked
    executables that have no main() ? */
 
-struct partial_symtab *
-find_main_psymtab (void)
+char *
+find_main_filename (void)
 {
-  struct partial_symtab *pst;
   struct objfile *objfile;
+  char *result, *name = main_name ();
 
-  ALL_PSYMTABS (objfile, pst)
+  ALL_OBJFILES (objfile)
   {
-    if (lookup_partial_symbol (pst, main_name (), NULL, 1, VAR_DOMAIN))
-      {
-	return (pst);
-      }
+    if (!objfile->sf)
+      continue;
+    result = objfile->sf->qf->find_symbol_file (objfile, name);
+    if (result)
+      return result;
   }
   return (NULL);
 }
@@ -2110,11 +1696,16 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section)
 	/* In order to better support objfiles that contain both
 	   stabs and coff debugging info, we continue on if a psymtab
 	   can't be found. */
-	if ((objfile->flags & OBJF_REORDERED) && objfile->psymtabs)
+	if ((objfile->flags & OBJF_REORDERED) && objfile->sf)
 	  {
-	    ps = find_pc_sect_psymtab (pc, section);
-	    if (ps)
-	      return PSYMTAB_TO_SYMTAB (ps);
+	    struct symtab *result;
+	    result
+	      = objfile->sf->qf->find_pc_sect_symtab (objfile,
+						      msymbol,
+						      pc, section,
+						      0);
+	    if (result)
+	      return result;
 	  }
 	if (section != 0)
 	  {
@@ -2138,20 +1729,20 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section)
   if (best_s != NULL)
     return (best_s);
 
-  s = NULL;
-  ps = find_pc_sect_psymtab (pc, section);
-  if (ps)
-    {
-      if (ps->readin)
-	/* Might want to error() here (in case symtab is corrupt and
-	   will cause a core dump), but maybe we can successfully
-	   continue, so let's not.  */
-	warning (_("\
-(Internal error: pc %s in read in psymtab, but not in symtab.)\n"),
-		 paddress (get_objfile_arch (ps->objfile), pc));
-      s = PSYMTAB_TO_SYMTAB (ps);
-    }
-  return (s);
+  ALL_OBJFILES (objfile)
+  {
+    struct symtab *result;
+    if (!objfile->sf)
+      continue;
+    result = objfile->sf->qf->find_pc_sect_symtab (objfile,
+						   msymbol,
+						   pc, section,
+						   1);
+    if (result)
+      return result;
+  }
+
+  return NULL;
 }
 
 /* Find the symtab associated with PC.  Look through the psymtabs and
@@ -2471,18 +2062,17 @@ find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match)
 
       struct objfile *objfile;
       struct symtab *s;
-      struct partial_symtab *p;
 
       if (best_index >= 0)
 	best = best_linetable->item[best_index].line;
       else
 	best = 0;
 
-      ALL_PSYMTABS (objfile, p)
+      ALL_OBJFILES (objfile)
       {
-        if (FILENAME_CMP (symtab->filename, p->filename) != 0)
-          continue;
-        PSYMTAB_TO_SYMTAB (p);
+	if (objfile->sf)
+	  objfile->sf->qf->expand_symtabs_with_filename (objfile,
+							 symtab->filename);
       }
 
       /* Get symbol full file name if possible.  */
@@ -3026,6 +2616,14 @@ output_source_filename (const char *name, int *first)
   fputs_filtered (name, gdb_stdout);
 }
 
+/* A callback for map_partial_symbol_filenames.  */
+static void
+output_partial_symbol_filename (const char *fullname, const char *filename,
+				void *data)
+{
+  output_source_filename (fullname ? fullname : filename, data);
+}
+
 static void
 sources_info (char *ignore, int from_tty)
 {
@@ -3052,19 +2650,12 @@ sources_info (char *ignore, int from_tty)
   printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
 
   first = 1;
-  ALL_PSYMTABS (objfile, ps)
-  {
-    if (!ps->readin)
-      {
-	const char *fullname = psymtab_to_fullname (ps);
-	output_source_filename (fullname ? fullname : ps->filename, &first);
-      }
-  }
+  map_partial_symbol_filenames (output_partial_symbol_filename, &first);
   printf_filtered ("\n");
 }
 
 static int
-file_matches (char *file, char *files[], int nfiles)
+file_matches (const char *file, char *files[], int nfiles)
 {
   int i;
 
@@ -3154,6 +2745,31 @@ sort_search_symbols (struct symbol_search *prevtail, int nfound)
   return symp;
 }
 
+/* An object of this type is passed as the user_data to the
+   expand_symtabs_matching method.  */
+struct search_symbols_data
+{
+  int nfiles;
+  char **files;
+  char *regexp;
+};
+
+/* A callback for expand_symtabs_matching.  */
+static int
+search_symbols_file_matches (const char *filename, void *user_data)
+{
+  struct search_symbols_data *data = user_data;
+  return file_matches (filename, data->files, data->nfiles);
+}
+
+/* A callback for expand_symtabs_matching.  */
+static int
+search_symbols_name_matches (const char *symname, void *user_data)
+{
+  struct search_symbols_data *data = user_data;
+  return data->regexp == NULL || re_exec (symname);
+}
+
 /* Search the symbol table for matches to the regular expression REGEXP,
    returning the results in *MATCHES.
 
@@ -3173,13 +2789,11 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
 		struct symbol_search **matches)
 {
   struct symtab *s;
-  struct partial_symtab *ps;
   struct blockvector *bv;
   struct block *b;
   int i = 0;
   struct dict_iterator iter;
   struct symbol *sym;
-  struct partial_symbol **psym;
   struct objfile *objfile;
   struct minimal_symbol *msymbol;
   char *val;
@@ -3204,6 +2818,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
   struct symbol_search *psr;
   struct symbol_search *tail;
   struct cleanup *old_chain = NULL;
+  struct search_symbols_data datum;
 
   if (kind < VARIABLES_DOMAIN)
     error (_("must search on specific domain"));
@@ -3256,60 +2871,17 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
      matching the regexp.  That way we don't have to reproduce all of
      the machinery below. */
 
-  ALL_PSYMTABS (objfile, ps)
+  datum.nfiles = nfiles;
+  datum.files = files;
+  datum.regexp = regexp;
+  ALL_OBJFILES (objfile)
   {
-    struct partial_symbol **bound, **gbound, **sbound;
-    int keep_going = 1;
-
-    if (ps->readin)
-      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;
-    bound = gbound;
-
-    /* Go through all of the symbols stored in a partial
-       symtab in one loop. */
-    psym = objfile->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;
-		bound = sbound;
-	      }
-	    else
-	      keep_going = 0;
-	    continue;
-	  }
-	else
-	  {
-	    QUIT;
-
-	    /* If it would match (logic taken from loop below)
-	       load the file and go on to the next one.  We check the
-	       filename here, but that's a bit bogus: we don't know
-	       what file it really comes from until we have full
-	       symtabs.  The symbol might be in a header file included by
-	       this psymtab.  This only affects Insight.  */
-	    if (file_matches (ps->filename, files, nfiles)
-		&& ((regexp == NULL
-		     || re_exec (SYMBOL_NATURAL_NAME (*psym)) != 0)
-		    && ((kind == VARIABLES_DOMAIN && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
-			 && SYMBOL_CLASS (*psym) != LOC_UNRESOLVED
-			 && SYMBOL_CLASS (*psym) != LOC_BLOCK
-			 && SYMBOL_CLASS (*psym) != LOC_CONST)
-			|| (kind == FUNCTIONS_DOMAIN && SYMBOL_CLASS (*psym) == LOC_BLOCK)
-			|| (kind == TYPES_DOMAIN && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))))
-	      {
-		PSYMTAB_TO_SYMTAB (ps);
-		keep_going = 0;
-	      }
-	  }
-	psym++;
-      }
+    if (objfile->sf)
+      objfile->sf->qf->expand_symtabs_matching (objfile,
+						search_symbols_file_matches,
+						search_symbols_name_matches,
+						kind,
+						&datum);
   }
 
   /* Here, we search through the minimal symbol tables for functions
@@ -3836,10 +3408,10 @@ completion_list_add_fields (struct symbol *sym, char *sym_text,
     }
 }
 
-/* Type of the user_data argument passed to add_macro_name.  The
-   contents are simply whatever is needed by
-   completion_list_add_name.  */
-struct add_macro_name_data
+/* Type of the user_data argument passed to add_macro_name or
+   add_partial_symbol_name.  The contents are simply whatever is
+   needed by completion_list_add_name.  */
+struct add_name_data
 {
   char *sym_text;
   int sym_text_len;
@@ -3853,7 +3425,17 @@ static void
 add_macro_name (const char *name, const struct macro_definition *ignore,
 		void *user_data)
 {
-  struct add_macro_name_data *datum = (struct add_macro_name_data *) user_data;
+  struct add_name_data *datum = (struct add_name_data *) user_data;
+  completion_list_add_name ((char *) name,
+			    datum->sym_text, datum->sym_text_len,
+			    datum->text, datum->word);
+}
+
+/* A callback for map_partial_symbol_names.  */
+static void
+add_partial_symbol_name (const char *name, void *user_data)
+{
+  struct add_name_data *datum = (struct add_name_data *) user_data;
   completion_list_add_name ((char *) name,
 			    datum->sym_text, datum->sym_text_len,
 			    datum->text, datum->word);
@@ -3868,17 +3450,16 @@ default_make_symbol_completion_list (char *text, char *word)
 
   struct symbol *sym;
   struct symtab *s;
-  struct partial_symtab *ps;
   struct minimal_symbol *msymbol;
   struct objfile *objfile;
   struct block *b;
   const struct block *surrounding_static_block, *surrounding_global_block;
   struct dict_iterator iter;
-  struct partial_symbol **psym;
   /* The symbol we are completing on.  Points in same buffer as text.  */
   char *sym_text;
   /* Length of sym_text.  */
   int sym_text_len;
+  struct add_name_data datum;
 
   /* Now look for the symbol we are supposed to complete on.  */
   {
@@ -3940,35 +3521,14 @@ default_make_symbol_completion_list (char *text, char *word)
   return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
   return_val[0] = NULL;
 
+  datum.sym_text = sym_text;
+  datum.sym_text_len = sym_text_len;
+  datum.text = text;
+  datum.word = word;
+
   /* Look through the partial symtabs for all symbols which begin
      by matching SYM_TEXT.  Add each one that you find to the list.  */
-
-  ALL_PSYMTABS (objfile, ps)
-  {
-    /* If the psymtab's been read in we'll get it when we search
-       through the blockvector.  */
-    if (ps->readin)
-      continue;
-
-    for (psym = objfile->global_psymbols.list + ps->globals_offset;
-	 psym < (objfile->global_psymbols.list + ps->globals_offset
-		 + ps->n_global_syms);
-	 psym++)
-      {
-	/* If interrupted, then quit. */
-	QUIT;
-	COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word);
-      }
-
-    for (psym = objfile->static_psymbols.list + ps->statics_offset;
-	 psym < (objfile->static_psymbols.list + ps->statics_offset
-		 + ps->n_static_syms);
-	 psym++)
-      {
-	QUIT;
-	COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word);
-      }
-  }
+  map_partial_symbol_names (add_partial_symbol_name, &datum);
 
   /* At this point scan through the misc symbol vectors and add each
      symbol you find to the list.  Eventually we want to ignore
@@ -4048,12 +3608,6 @@ default_make_symbol_completion_list (char *text, char *word)
   if (current_language->la_macro_expansion == macro_expansion_c)
     {
       struct macro_scope *scope;
-      struct add_macro_name_data datum;
-
-      datum.sym_text = sym_text;
-      datum.sym_text_len = sym_text_len;
-      datum.text = text;
-      datum.word = word;
 
       /* Add any macros visible in the default scope.  Note that this
 	 may yield the occasional wrong result, because an expression
@@ -4258,6 +3812,57 @@ not_interesting_fname (const char *fname)
   return 0;
 }
 
+/* An object of this type is passed as the user_data argument to
+   map_partial_symbol_filenames.  */
+struct add_partial_filename_data
+{
+  int *first;
+  char *text;
+  char *word;
+  int text_len;
+  char ***list;
+  int *list_used;
+  int *list_alloced;
+};
+
+/* A callback for map_partial_symbol_filenames.  */
+static void
+maybe_add_partial_symtab_filename (const char *fullname, const char *filename,
+				   void *user_data)
+{
+  struct add_partial_filename_data *data = user_data;
+
+  if (not_interesting_fname (filename))
+    return;
+  if (!filename_seen (filename, 1, data->first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+      && strncasecmp (filename, data->text, data->text_len) == 0
+#else
+      && strncmp (filename, data->text, data->text_len) == 0
+#endif
+      )
+    {
+      /* This file matches for a completion; add it to the
+	 current list of matches.  */
+      add_filename_to_list (filename, data->text, data->word,
+			    data->list, data->list_used, data->list_alloced);
+    }
+  else
+    {
+      const char *base_name = lbasename (filename);
+      if (base_name != filename
+	  && !filename_seen (base_name, 1, data->first)
+#if HAVE_DOS_BASED_FILE_SYSTEM
+	  && strncasecmp (base_name, data->text, data->text_len) == 0
+#else
+	  && strncmp (base_name, data->text, data->text_len) == 0
+#endif
+	  )
+	add_filename_to_list (base_name, data->text, data->word,
+			      data->list, data->list_used, data->list_alloced);
+    }
+}
+
 /* Return a NULL terminated array of all source files whose names
    begin with matching TEXT.  The file names are looked up in the
    symbol tables of this program.  If the answer is no matchess, then
@@ -4267,7 +3872,6 @@ char **
 make_source_files_completion_list (char *text, char *word)
 {
   struct symtab *s;
-  struct partial_symtab *ps;
   struct objfile *objfile;
   int first = 1;
   int list_alloced = 1;
@@ -4275,6 +3879,7 @@ make_source_files_completion_list (char *text, char *word)
   size_t text_len = strlen (text);
   char **list = (char **) xmalloc (list_alloced * sizeof (char *));
   const char *base_name;
+  struct add_partial_filename_data datum;
 
   list[0] = NULL;
 
@@ -4318,42 +3923,14 @@ make_source_files_completion_list (char *text, char *word)
 	}
     }
 
-  ALL_PSYMTABS (objfile, ps)
-    {
-      if (not_interesting_fname (ps->filename))
-	continue;
-      if (!ps->readin)
-	{
-	  if (!filename_seen (ps->filename, 1, &first)
-#if HAVE_DOS_BASED_FILE_SYSTEM
-	      && strncasecmp (ps->filename, text, text_len) == 0
-#else
-	      && strncmp (ps->filename, text, text_len) == 0
-#endif
-	      )
-	    {
-	      /* This file matches for a completion; add it to the
-		 current list of matches.  */
-	      add_filename_to_list (ps->filename, text, word,
-				    &list, &list_used, &list_alloced);
-
-	    }
-	  else
-	    {
-	      base_name = lbasename (ps->filename);
-	      if (base_name != ps->filename
-		  && !filename_seen (base_name, 1, &first)
-#if HAVE_DOS_BASED_FILE_SYSTEM
-		  && strncasecmp (base_name, text, text_len) == 0
-#else
-		  && strncmp (base_name, text, text_len) == 0
-#endif
-		  )
-		add_filename_to_list (base_name, text, word,
-				      &list, &list_used, &list_alloced);
-	    }
-	}
-    }
+  datum.first = &first;
+  datum.text = text;
+  datum.word = word;
+  datum.text_len = text_len;
+  datum.list = &list;
+  datum.list_used = &list_used;
+  datum.list_alloced = &list_alloced;
+  map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum);
 
   return list;
 }
@@ -4778,15 +4355,15 @@ expand_line_sal (struct symtab_and_line sal)
 
       old_chain = save_current_program_space ();
       ALL_PSPACES (pspace)
-	ALL_PSPACE_PSYMTABS (pspace, objfile, psymtab)
+      {
+	set_current_program_space (pspace);
+	ALL_PSPACE_OBJFILES (pspace, objfile)
 	{
-	  if (FILENAME_CMP (match_filename, psymtab->filename) == 0)
-	    {
-	      set_current_program_space (pspace);
-
-	      PSYMTAB_TO_SYMTAB (psymtab);
-	    }
+	  if (objfile->sf)
+	    objfile->sf->qf->expand_symtabs_with_filename (objfile,
+							   sal.symtab->filename);
 	}
+      }
       do_cleanups (old_chain);
 
       /* Now search the symtab for exact matches and append them.  If
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 800ffd8..e238865 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -632,36 +632,6 @@ struct symbol
 #define SYMBOL_REGISTER_OPS(symbol)     (symbol)->ops.ops_register
 #define SYMBOL_LOCATION_BATON(symbol)   (symbol)->aux_value
 
-/* A partial_symbol records the name, domain, and address class of
-   symbols whose types we have not parsed yet.  For functions, it also
-   contains their memory address, so we can find them from a PC value.
-   Each partial_symbol sits in a partial_symtab, all of which are chained
-   on a  partial symtab list and which points to the corresponding 
-   normal symtab once the partial_symtab has been referenced.  */
-
-/* This structure is space critical.  See space comments at the top. */
-
-struct partial_symbol
-{
-
-  /* The general symbol info required for all types of symbols. */
-
-  struct general_symbol_info ginfo;
-
-  /* Name space code.  */
-
-  ENUM_BITFIELD(domain_enum_tag) domain : 6;
-
-  /* Address class (for info_symbols) */
-
-  ENUM_BITFIELD(address_class) aclass : 6;
-
-};
-
-#define PSYMBOL_DOMAIN(psymbol)	(psymbol)->domain
-#define PSYMBOL_CLASS(psymbol)		(psymbol)->aclass
-
-
 /* Each item represents a line-->pc (or the reverse) mapping.  This is
    somewhat more wasteful of space than one might wish, but since only
    the files which are actually debugged are read in to core, we don't
@@ -828,110 +798,6 @@ struct symtab
 #define SYMTAB_PSPACE(symtab)	(symtab)->objfile->pspace
 
 
-/* Each source file that has not been fully read in is represented by
-   a partial_symtab.  This contains the information on where in the
-   executable the debugging symbols for a specific file are, and a
-   list of names of global symbols which are located in this file.
-   They are all chained on partial symtab lists.
-
-   Even after the source file has been read into a symtab, the
-   partial_symtab remains around.  They are allocated on an obstack,
-   objfile_obstack.  FIXME, this is bad for dynamic linking or VxWorks-
-   style execution of a bunch of .o's.  */
-
-struct partial_symtab
-{
-
-  /* Chain of all existing partial symtabs.  */
-
-  struct partial_symtab *next;
-
-  /* Name of the source file which this partial_symtab defines */
-
-  char *filename;
-
-  /* Full path of the source file.  NULL if not known.  */
-
-  char *fullname;
-
-  /* Directory in which it was compiled, or NULL if we don't know.  */
-
-  char *dirname;
-
-  /* Information about the object file from which symbols should be read.  */
-
-  struct objfile *objfile;
-
-  /* Set of relocation offsets to apply to each section.  */
-
-  struct section_offsets *section_offsets;
-
-  /* Range of text addresses covered by this file; texthigh is the
-     beginning of the next section. */
-
-  CORE_ADDR textlow;
-  CORE_ADDR texthigh;
-
-  /* Array of pointers to all of the partial_symtab's which this one
-     depends on.  Since this array can only be set to previous or
-     the current (?) psymtab, this dependency tree is guaranteed not
-     to have any loops.  "depends on" means that symbols must be read
-     for the dependencies before being read for this psymtab; this is
-     for type references in stabs, where if foo.c includes foo.h, declarations
-     in foo.h may use type numbers defined in foo.c.  For other debugging
-     formats there may be no need to use dependencies.  */
-
-  struct partial_symtab **dependencies;
-
-  int number_of_dependencies;
-
-  /* Global symbol list.  This list will be sorted after readin to
-     improve access.  Binary search will be the usual method of
-     finding a symbol within it. globals_offset is an integer offset
-     within global_psymbols[].  */
-
-  int globals_offset;
-  int n_global_syms;
-
-  /* Static symbol list.  This list will *not* be sorted after readin;
-     to find a symbol in it, exhaustive search must be used.  This is
-     reasonable because searches through this list will eventually
-     lead to either the read in of a files symbols for real (assumed
-     to take a *lot* of time; check) or an error (and we don't care
-     how long errors take).  This is an offset and size within
-     static_psymbols[].  */
-
-  int statics_offset;
-  int n_static_syms;
-
-  /* Pointer to symtab eventually allocated for this source file, 0 if
-     !readin or if we haven't looked for the symtab after it was readin.  */
-
-  struct symtab *symtab;
-
-  /* Pointer to function which will read in the symtab corresponding to
-     this psymtab.  */
-
-  void (*read_symtab) (struct partial_symtab *);
-
-  /* Information that lets read_symtab() locate the part of the symbol table
-     that this psymtab corresponds to.  This information is private to the
-     format-dependent symbol reading routines.  For further detail examine
-     the various symbol reading modules.  Should really be (void *) but is
-     (char *) as with other such gdb variables.  (FIXME) */
-
-  char *read_symtab_private;
-
-  /* Non-zero if the symtab corresponding to this psymtab has been readin */
-
-  unsigned char readin;
-};
-
-/* A fast way to get from a psymtab to its symtab (after the first time).  */
-#define	PSYMTAB_TO_SYMTAB(pst)  \
-    ((pst) -> symtab != NULL ? (pst) -> symtab : psymtab_to_symtab (pst))
-
-
 /* The virtual function table is now an array of structures which have the
    form { int16 offset, delta; void *pfn; }. 
 
@@ -1025,13 +891,6 @@ extern struct symbol *lookup_symbol_aux_block (const char *name,
 					       const struct block *block,
 					       const domain_enum domain);
 
-/* Lookup a partial symbol.  */
-
-extern struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
-						     const char *,
-						     const char *, int,
-						     domain_enum);
-
 /* lookup a symbol by name, within a specified block */
 
 extern struct symbol *lookup_block_symbol (const struct block *, const char *,
@@ -1063,20 +922,10 @@ extern int find_pc_partial_function (CORE_ADDR, char **, CORE_ADDR *,
 
 extern void clear_pc_function_cache (void);
 
-/* from symtab.c: */
-
-/* lookup partial symbol table by filename */
-
-extern struct partial_symtab *lookup_partial_symtab (const char *);
-
-/* lookup partial symbol table by address */
-
-extern struct partial_symtab *find_pc_psymtab (CORE_ADDR);
-
 /* lookup partial symbol table by address and section */
 
-extern struct partial_symtab *find_pc_sect_psymtab (CORE_ADDR,
-						    struct obj_section *);
+extern struct symtab *find_pc_sect_symtab_via_partial (CORE_ADDR,
+						       struct obj_section *);
 
 /* lookup full symbol table by address */
 
@@ -1086,17 +935,6 @@ extern struct symtab *find_pc_symtab (CORE_ADDR);
 
 extern struct symtab *find_pc_sect_symtab (CORE_ADDR, struct obj_section *);
 
-/* lookup partial symbol by address */
-
-extern struct partial_symbol *find_pc_psymbol (struct partial_symtab *,
-					       CORE_ADDR);
-
-/* lookup partial symbol by address and section */
-
-extern struct partial_symbol *find_pc_sect_psymbol (struct partial_symtab *,
-						    CORE_ADDR,
-						    struct obj_section *);
-
 extern int find_pc_line_pc_range (CORE_ADDR, CORE_ADDR *, CORE_ADDR *);
 
 extern void reread_symbols (void);
@@ -1268,8 +1106,6 @@ extern void free_symtab (struct symtab *);
 
 /* Symbol-reading stuff in symfile.c and solib.c.  */
 
-extern struct symtab *psymtab_to_symtab (struct partial_symtab *);
-
 extern void clear_solib (void);
 
 /* source.c */
@@ -1295,7 +1131,7 @@ extern char **make_source_files_completion_list (char *, char *);
 
 int matching_obj_sections (struct obj_section *, struct obj_section *);
 
-extern struct partial_symtab *find_main_psymtab (void);
+extern char *find_main_filename (void);
 
 extern struct symtab *find_line_symtab (struct symtab *, int, int *, int *);
 
@@ -1322,10 +1158,6 @@ extern CORE_ADDR skip_prologue_using_sal (struct gdbarch *gdbarch,
 extern struct symbol *fixup_symbol_section (struct symbol *,
 					    struct objfile *);
 
-extern struct partial_symbol *fixup_psymbol_section (struct partial_symbol
-						     *psym,
-						     struct objfile *objfile);
-
 /* Symbol searching */
 
 /* When using search_symbols, a list of the following structs is returned.
@@ -1373,4 +1205,7 @@ struct symbol *lookup_global_symbol_from_objfile (const struct objfile *objfile,
 extern struct symtabs_and_lines
 expand_line_sal (struct symtab_and_line sal);
 
+void fixup_section (struct general_symbol_info *ginfo,
+		    CORE_ADDR addr, struct objfile *objfile);
+
 #endif /* !defined(SYMTAB_H) */
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 6301b61..88d4273 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -50,6 +50,7 @@
 #include "stabsread.h"
 #include "expression.h"
 #include "complaints.h"
+#include "psympriv.h"
 
 #include "gdb-stabs.h"
 
@@ -3040,6 +3041,7 @@ static struct sym_fns xcoff_sym_fns =
   default_symfile_segments,	/* sym_segments: Get segment information from
 				   a file.  */
   aix_process_linenos,          /* sym_read_linetable */
+  &psym_functions,
   NULL				/* next: pointer to next struct sym_fns */
 };
 
-- 
1.6.2.5


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