gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / symtab.c
index 4c14edae177668c41a159a97dbd1629136774214..791ce11a7372c11583eec384b5d44bf13d4366ea 100644 (file)
@@ -1,6 +1,6 @@
 /* Symbol table lookup for the GNU debugger, GDB.
 
 /* Symbol table lookup for the GNU debugger, GDB.
 
-   Copyright (C) 1986-2019 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    This file is part of GDB.
 
@@ -183,6 +183,16 @@ struct symbol_cache_slot
   } value;
 };
 
   } value;
 };
 
+/* Clear out SLOT.  */
+
+static void
+symbol_cache_clear_slot (struct symbol_cache_slot *slot)
+{
+  if (slot->state == SYMBOL_SLOT_NOT_FOUND)
+    xfree (slot->value.not_found.name);
+  slot->state = SYMBOL_SLOT_UNUSED;
+}
+
 /* Symbols don't specify global vs static block.
    So keep them in separate caches.  */
 
 /* Symbols don't specify global vs static block.
    So keep them in separate caches.  */
 
@@ -201,6 +211,19 @@ struct block_symbol_cache
   struct symbol_cache_slot symbols[1];
 };
 
   struct symbol_cache_slot symbols[1];
 };
 
+/* Clear all slots of BSC and free BSC.  */
+
+static void
+destroy_block_symbol_cache (struct block_symbol_cache *bsc)
+{
+  if (bsc != nullptr)
+    {
+      for (unsigned int i = 0; i < bsc->size; i++)
+       symbol_cache_clear_slot (&bsc->symbols[i]);
+      xfree (bsc);
+    }
+}
+
 /* The symbol cache.
 
    Searching for symbols in the static and global blocks over multiple objfiles
 /* The symbol cache.
 
    Searching for symbols in the static and global blocks over multiple objfiles
@@ -217,8 +240,8 @@ struct symbol_cache
 
   ~symbol_cache ()
   {
 
   ~symbol_cache ()
   {
-    xfree (global_symbols);
-    xfree (static_symbols);
+    destroy_block_symbol_cache (global_symbols);
+    destroy_block_symbol_cache (static_symbols);
   }
 
   struct block_symbol_cache *global_symbols = nullptr;
   }
 
   struct block_symbol_cache *global_symbols = nullptr;
@@ -572,7 +595,7 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
   struct fn_field *method = &f[signature_id];
   const char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id);
   const char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id);
   struct fn_field *method = &f[signature_id];
   const char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id);
   const char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id);
-  const char *newname = TYPE_NAME (type);
+  const char *newname = type->name ();
 
   /* Does the form of physname indicate that it is the full mangled name
      of a constructor (not just the args)?  */
 
   /* Does the form of physname indicate that it is the full mangled name
      of a constructor (not just the args)?  */
@@ -644,44 +667,27 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
   return (mangled_name);
 }
 
   return (mangled_name);
 }
 
-/* Set the demangled name of GSYMBOL to NAME.  NAME must be already
-   correctly allocated.  */
+/* See symtab.h.  */
 
 void
 
 void
-symbol_set_demangled_name (struct general_symbol_info *gsymbol,
-                           const char *name,
-                           struct obstack *obstack)
+general_symbol_info::set_demangled_name (const char *name,
+                                        struct obstack *obstack)
 {
 {
-  if (gsymbol->language == language_ada)
+  if (language () == language_ada)
     {
       if (name == NULL)
        {
     {
       if (name == NULL)
        {
-         gsymbol->ada_mangled = 0;
-         gsymbol->language_specific.obstack = obstack;
+         ada_mangled = 0;
+         language_specific.obstack = obstack;
        }
       else
        {
        }
       else
        {
-         gsymbol->ada_mangled = 1;
-         gsymbol->language_specific.demangled_name = name;
+         ada_mangled = 1;
+         language_specific.demangled_name = name;
        }
     }
   else
        }
     }
   else
-    gsymbol->language_specific.demangled_name = name;
-}
-
-/* Return the demangled name of GSYMBOL.  */
-
-const char *
-symbol_get_demangled_name (const struct general_symbol_info *gsymbol)
-{
-  if (gsymbol->language == language_ada)
-    {
-      if (!gsymbol->ada_mangled)
-       return NULL;
-      /* Fall through.  */
-    }
-
-  return gsymbol->language_specific.demangled_name;
+    language_specific.demangled_name = name;
 }
 
 \f
 }
 
 \f
@@ -689,28 +695,26 @@ symbol_get_demangled_name (const struct general_symbol_info *gsymbol)
    depending upon the language for the symbol.  */
 
 void
    depending upon the language for the symbol.  */
 
 void
-symbol_set_language (struct general_symbol_info *gsymbol,
-                     enum language language,
-                    struct obstack *obstack)
+general_symbol_info::set_language (enum language language,
+                                  struct obstack *obstack)
 {
 {
-  gsymbol->language = language;
-  if (gsymbol->language == language_cplus
-      || gsymbol->language == language_d
-      || gsymbol->language == language_go
-      || gsymbol->language == language_objc
-      || gsymbol->language == language_fortran)
+  m_language = language;
+  if (language == language_cplus
+      || language == language_d
+      || language == language_go
+      || language == language_objc
+      || language == language_fortran)
     {
     {
-      symbol_set_demangled_name (gsymbol, NULL, obstack);
+      set_demangled_name (NULL, obstack);
     }
     }
-  else if (gsymbol->language == language_ada)
+  else if (language == language_ada)
     {
     {
-      gdb_assert (gsymbol->ada_mangled == 0);
-      gsymbol->language_specific.obstack = obstack;
+      gdb_assert (ada_mangled == 0);
+      language_specific.obstack = obstack;
     }
   else
     {
     }
   else
     {
-      memset (&gsymbol->language_specific, 0,
-             sizeof (gsymbol->language_specific));
+      memset (&language_specific, 0, sizeof (language_specific));
     }
 }
 
     }
 }
 
@@ -770,34 +774,40 @@ create_demangled_names_hash (struct objfile_per_bfd_storage *per_bfd)
   /* Choose 256 as the starting size of the hash table, somewhat arbitrarily.
      The hash table code will round this up to the next prime number.
      Choosing a much larger table size wastes memory, and saves only about
   /* Choose 256 as the starting size of the hash table, somewhat arbitrarily.
      The hash table code will round this up to the next prime number.
      Choosing a much larger table size wastes memory, and saves only about
-     1% in symbol reading.  */
+     1% in symbol reading.  However, if the minsym count is already
+     initialized (e.g. because symbol name setting was deferred to
+     a background thread) we can initialize the hashtable with a count
+     based on that, because we will almost certainly have at least that
+     many entries.  If we have a nonzero number but less than 256,
+     we still stay with 256 to have some space for psymbols, etc.  */
+
+  /* htab will expand the table when it is 3/4th full, so we account for that
+     here.  +2 to round up.  */
+  int minsym_based_count = (per_bfd->minimal_symbol_count + 2) / 3 * 4;
+  int count = std::max (per_bfd->minimal_symbol_count, minsym_based_count);
 
   per_bfd->demangled_names_hash.reset (htab_create_alloc
 
   per_bfd->demangled_names_hash.reset (htab_create_alloc
-    (256, hash_demangled_name_entry, eq_demangled_name_entry,
+    (count, hash_demangled_name_entry, eq_demangled_name_entry,
      free_demangled_name_entry, xcalloc, xfree));
 }
 
      free_demangled_name_entry, xcalloc, xfree));
 }
 
-/* Try to determine the demangled name for a symbol, based on the
-   language of that symbol.  If the language is set to language_auto,
-   it will attempt to find any demangling algorithm that works and
-   then set the language appropriately.  The returned name is allocated
-   by the demangler and should be xfree'd.  */
+/* See symtab.h  */
 
 
-static char *
+char *
 symbol_find_demangled_name (struct general_symbol_info *gsymbol,
                            const char *mangled)
 {
   char *demangled = NULL;
   int i;
 
 symbol_find_demangled_name (struct general_symbol_info *gsymbol,
                            const char *mangled)
 {
   char *demangled = NULL;
   int i;
 
-  if (gsymbol->language == language_unknown)
-    gsymbol->language = language_auto;
+  if (gsymbol->language () == language_unknown)
+    gsymbol->m_language = language_auto;
 
 
-  if (gsymbol->language != language_auto)
+  if (gsymbol->language () != language_auto)
     {
     {
-      const struct language_defn *lang = language_def (gsymbol->language);
+      const struct language_defn *lang = language_def (gsymbol->language ());
 
 
-      language_sniff_from_mangled_name (lang, mangled, &demangled);
+      lang->sniff_from_mangled_name (mangled, &demangled);
       return demangled;
     }
 
       return demangled;
     }
 
@@ -806,9 +816,9 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
       enum language l = (enum language) i;
       const struct language_defn *lang = language_def (l);
 
       enum language l = (enum language) i;
       const struct language_defn *lang = language_def (l);
 
-      if (language_sniff_from_mangled_name (lang, mangled, &demangled))
+      if (lang->sniff_from_mangled_name (mangled, &demangled))
        {
        {
-         gsymbol->language = l;
+         gsymbol->m_language = l;
          return demangled;
        }
     }
          return demangled;
        }
     }
@@ -828,28 +838,24 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
    so the pointer can be discarded after calling this function.  */
 
 void
    so the pointer can be discarded after calling this function.  */
 
 void
-symbol_set_names (struct general_symbol_info *gsymbol,
-                 gdb::string_view linkage_name, bool copy_name,
-                 struct objfile_per_bfd_storage *per_bfd)
+general_symbol_info::compute_and_set_names (gdb::string_view linkage_name,
+                                           bool copy_name,
+                                           objfile_per_bfd_storage *per_bfd,
+                                           gdb::optional<hashval_t> hash)
 {
   struct demangled_name_entry **slot;
 
 {
   struct demangled_name_entry **slot;
 
-  if (gsymbol->language == language_ada)
+  if (language () == language_ada)
     {
       /* In Ada, we do the symbol lookups using the mangled name, so
          we can save some space by not storing the demangled name.  */
       if (!copy_name)
     {
       /* In Ada, we do the symbol lookups using the mangled name, so
          we can save some space by not storing the demangled name.  */
       if (!copy_name)
-       gsymbol->name = linkage_name.data ();
+       m_name = linkage_name.data ();
       else
       else
-       {
-         char *name = (char *) obstack_alloc (&per_bfd->storage_obstack,
-                                              linkage_name.length () + 1);
-
-         memcpy (name, linkage_name.data (), linkage_name.length ());
-         name[linkage_name.length ()] = '\0';
-         gsymbol->name = name;
-       }
-      symbol_set_demangled_name (gsymbol, NULL, &per_bfd->storage_obstack);
+       m_name = obstack_strndup (&per_bfd->storage_obstack,
+                                 linkage_name.data (),
+                                 linkage_name.length ());
+      set_demangled_name (NULL, &per_bfd->storage_obstack);
 
       return;
     }
 
       return;
     }
@@ -858,15 +864,27 @@ symbol_set_names (struct general_symbol_info *gsymbol,
     create_demangled_names_hash (per_bfd);
 
   struct demangled_name_entry entry (linkage_name);
     create_demangled_names_hash (per_bfd);
 
   struct demangled_name_entry entry (linkage_name);
+  if (!hash.has_value ())
+    hash = hash_demangled_name_entry (&entry);
   slot = ((struct demangled_name_entry **)
   slot = ((struct demangled_name_entry **)
-         htab_find_slot (per_bfd->demangled_names_hash.get (),
-                         &entry, INSERT));
+          htab_find_slot_with_hash (per_bfd->demangled_names_hash.get (),
+                                   &entry, *hash, INSERT));
+
+  /* The const_cast is safe because the only reason it is already
+     initialized is if we purposefully set it from a background
+     thread to avoid doing the work here.  However, it is still
+     allocated from the heap and needs to be freed by us, just
+     like if we called symbol_find_demangled_name here.  If this is
+     nullptr, we call symbol_find_demangled_name below, but we put
+     this smart pointer here to be sure that we don't leak this name.  */
+  gdb::unique_xmalloc_ptr<char> demangled_name
+    (const_cast<char *> (language_specific.demangled_name));
 
   /* If this name is not in the hash table, add it.  */
   if (*slot == NULL
       /* A C version of the symbol may have already snuck into the table.
         This happens to, e.g., main.init (__go_init_main).  Cope.  */
 
   /* If this name is not in the hash table, add it.  */
   if (*slot == NULL
       /* A C version of the symbol may have already snuck into the table.
         This happens to, e.g., main.init (__go_init_main).  Cope.  */
-      || (gsymbol->language == language_go && (*slot)->demangled == nullptr))
+      || (language () == language_go && (*slot)->demangled == nullptr))
     {
       /* A 0-terminated copy of the linkage name.  Callers must set COPY_NAME
          to true if the string might not be nullterminated.  We have to make
     {
       /* A 0-terminated copy of the linkage name.  Callers must set COPY_NAME
          to true if the string might not be nullterminated.  We have to make
@@ -884,8 +902,9 @@ symbol_set_names (struct general_symbol_info *gsymbol,
       else
        linkage_name_copy = linkage_name;
 
       else
        linkage_name_copy = linkage_name;
 
-      gdb::unique_xmalloc_ptr<char> demangled_name_ptr
-       (symbol_find_demangled_name (gsymbol, linkage_name_copy.data ()));
+      if (demangled_name.get () == nullptr)
+        demangled_name.reset
+          (symbol_find_demangled_name (this, linkage_name_copy.data ()));
 
       /* Suppose we have demangled_name==NULL, copy_name==0, and
         linkage_name_copy==linkage_name.  In this case, we already have the
 
       /* Suppose we have demangled_name==NULL, copy_name==0, and
         linkage_name_copy==linkage_name.  In this case, we already have the
@@ -919,64 +938,59 @@ symbol_set_names (struct general_symbol_info *gsymbol,
          new (*slot) demangled_name_entry
            (gdb::string_view (mangled_ptr, linkage_name.length ()));
        }
          new (*slot) demangled_name_entry
            (gdb::string_view (mangled_ptr, linkage_name.length ()));
        }
-      (*slot)->demangled = std::move (demangled_name_ptr);
-      (*slot)->language = gsymbol->language;
+      (*slot)->demangled = std::move (demangled_name);
+      (*slot)->language = language ();
     }
     }
-  else if (gsymbol->language == language_unknown
-          || gsymbol->language == language_auto)
-    gsymbol->language = (*slot)->language;
+  else if (language () == language_unknown || language () == language_auto)
+    m_language = (*slot)->language;
 
 
-  gsymbol->name = (*slot)->mangled.data ();
-  if ((*slot)->demangled != nullptr)
-    symbol_set_demangled_name (gsymbol, (*slot)->demangled.get (),
-                              &per_bfd->storage_obstack);
-  else
-    symbol_set_demangled_name (gsymbol, NULL, &per_bfd->storage_obstack);
+  m_name = (*slot)->mangled.data ();
+  set_demangled_name ((*slot)->demangled.get (), &per_bfd->storage_obstack);
 }
 
 }
 
-/* Return the source code name of a symbol.  In languages where
-   demangling is necessary, this is the demangled name.  */
+/* See symtab.h.  */
 
 const char *
 
 const char *
-symbol_natural_name (const struct general_symbol_info *gsymbol)
+general_symbol_info::natural_name () const
 {
 {
-  switch (gsymbol->language)
+  switch (language ())
     {
     case language_cplus:
     case language_d:
     case language_go:
     case language_objc:
     case language_fortran:
     {
     case language_cplus:
     case language_d:
     case language_go:
     case language_objc:
     case language_fortran:
-      if (symbol_get_demangled_name (gsymbol) != NULL)
-       return symbol_get_demangled_name (gsymbol);
+    case language_rust:
+      if (language_specific.demangled_name != nullptr)
+       return language_specific.demangled_name;
       break;
     case language_ada:
       break;
     case language_ada:
-      return ada_decode_symbol (gsymbol);
+      return ada_decode_symbol (this);
     default:
       break;
     }
     default:
       break;
     }
-  return gsymbol->name;
+  return linkage_name ();
 }
 
 }
 
-/* Return the demangled name for a symbol based on the language for
-   that symbol.  If no demangled name exists, return NULL.  */
+/* See symtab.h.  */
 
 const char *
 
 const char *
-symbol_demangled_name (const struct general_symbol_info *gsymbol)
+general_symbol_info::demangled_name () const
 {
   const char *dem_name = NULL;
 
 {
   const char *dem_name = NULL;
 
-  switch (gsymbol->language)
+  switch (language ())
     {
     case language_cplus:
     case language_d:
     case language_go:
     case language_objc:
     case language_fortran:
     {
     case language_cplus:
     case language_d:
     case language_go:
     case language_objc:
     case language_fortran:
-      dem_name = symbol_get_demangled_name (gsymbol);
+    case language_rust:
+      dem_name = language_specific.demangled_name;
       break;
     case language_ada:
       break;
     case language_ada:
-      dem_name = ada_decode_symbol (gsymbol);
+      dem_name = ada_decode_symbol (this);
       break;
     default:
       break;
       break;
     default:
       break;
@@ -984,18 +998,15 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
   return dem_name;
 }
 
   return dem_name;
 }
 
-/* Return the search name of a symbol---generally the demangled or
-   linkage name of the symbol, depending on how it will be searched for.
-   If there is no distinct demangled name, then returns the same value
-   (same pointer) as SYMBOL_LINKAGE_NAME.  */
+/* See symtab.h.  */
 
 const char *
 
 const char *
-symbol_search_name (const struct general_symbol_info *gsymbol)
+general_symbol_info::search_name () const
 {
 {
-  if (gsymbol->language == language_ada)
-    return gsymbol->name;
+  if (language () == language_ada)
+    return linkage_name ();
   else
   else
-    return symbol_natural_name (gsymbol);
+    return natural_name ();
 }
 
 /* See symtab.h.  */
 }
 
 /* See symtab.h.  */
@@ -1005,8 +1016,8 @@ symbol_matches_search_name (const struct general_symbol_info *gsymbol,
                            const lookup_name_info &name)
 {
   symbol_name_matcher_ftype *name_match
                            const lookup_name_info &name)
 {
   symbol_name_matcher_ftype *name_match
-    = get_symbol_name_matcher (language_def (gsymbol->language), name);
-  return name_match (symbol_search_name (gsymbol), name, NULL);
+    = get_symbol_name_matcher (language_def (gsymbol->language ()), name);
+  return name_match (gsymbol->search_name (), name, NULL);
 }
 
 \f
 }
 
 \f
@@ -1146,7 +1157,7 @@ eq_symbol_entry (const struct symbol_cache_slot *slot,
     }
   else
     {
     }
   else
     {
-      slot_name = SYMBOL_SEARCH_NAME (slot->value.found.symbol);
+      slot_name = slot->value.found.symbol->search_name ();
       slot_domain = SYMBOL_DOMAIN (slot->value.found.symbol);
     }
 
       slot_domain = SYMBOL_DOMAIN (slot->value.found.symbol);
     }
 
@@ -1163,7 +1174,7 @@ eq_symbol_entry (const struct symbol_cache_slot *slot,
       /* It's important that we use the same comparison that was done
         the first time through.  If the slot records a found symbol,
         then this means using the symbol name comparison function of
       /* It's important that we use the same comparison that was done
         the first time through.  If the slot records a found symbol,
         then this means using the symbol name comparison function of
-        the symbol's language with SYMBOL_SEARCH_NAME.  See
+        the symbol's language with symbol->search_name ().  See
         dictionary.c.  It also means using symbol_matches_domain for
         found symbols.  See block.c.
 
         dictionary.c.  It also means using symbol_matches_domain for
         found symbols.  See block.c.
 
@@ -1185,8 +1196,7 @@ eq_symbol_entry (const struct symbol_cache_slot *slot,
          if (!SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
            return 0;
 
          if (!SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
            return 0;
 
-         if (!symbol_matches_domain (SYMBOL_LANGUAGE (sym),
-                                     slot_domain, domain))
+         if (!symbol_matches_domain (sym->language (), slot_domain, domain))
            return 0;
        }
     }
            return 0;
        }
     }
@@ -1223,8 +1233,8 @@ resize_symbol_cache (struct symbol_cache *cache, unsigned int new_size)
          && new_size == 0))
     return;
 
          && new_size == 0))
     return;
 
-  xfree (cache->global_symbols);
-  xfree (cache->static_symbols);
+  destroy_block_symbol_cache (cache->global_symbols);
+  destroy_block_symbol_cache (cache->static_symbols);
 
   if (new_size == 0)
     {
 
   if (new_size == 0)
     {
@@ -1266,9 +1276,7 @@ get_symbol_cache (struct program_space *pspace)
 static void
 set_symbol_cache_size (unsigned int new_size)
 {
 static void
 set_symbol_cache_size (unsigned int new_size)
 {
-  struct program_space *pspace;
-
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     {
       struct symbol_cache *cache = symbol_cache_key.get (pspace);
 
     {
       struct symbol_cache *cache = symbol_cache_key.get (pspace);
 
@@ -1362,16 +1370,6 @@ symbol_cache_lookup (struct symbol_cache *cache,
   return {};
 }
 
   return {};
 }
 
-/* Clear out SLOT.  */
-
-static void
-symbol_cache_clear_slot (struct symbol_cache_slot *slot)
-{
-  if (slot->state == SYMBOL_SLOT_NOT_FOUND)
-    xfree (slot->value.not_found.name);
-  slot->state = SYMBOL_SLOT_UNUSED;
-}
-
 /* Mark SYMBOL as found in SLOT.
    OBJFILE_CONTEXT is the current objfile when the lookup was done, or NULL
    if it's not needed to distinguish lookups (STATIC_BLOCK).  It is *not*
 /* Mark SYMBOL as found in SLOT.
    OBJFILE_CONTEXT is the current objfile when the lookup was done, or NULL
    if it's not needed to distinguish lookups (STATIC_BLOCK).  It is *not*
@@ -1512,7 +1510,7 @@ symbol_cache_dump (const struct symbol_cache *cache)
 
                printf_filtered ("  [%4u] = %s, %s %s\n", i,
                                 host_address_to_string (context),
 
                printf_filtered ("  [%4u] = %s, %s %s\n", i,
                                 host_address_to_string (context),
-                                SYMBOL_PRINT_NAME (found),
+                                found->print_name (),
                                 domain_name (SYMBOL_DOMAIN (found)));
                break;
              }
                                 domain_name (SYMBOL_DOMAIN (found)));
                break;
              }
@@ -1526,9 +1524,7 @@ symbol_cache_dump (const struct symbol_cache *cache)
 static void
 maintenance_print_symbol_cache (const char *args, int from_tty)
 {
 static void
 maintenance_print_symbol_cache (const char *args, int from_tty)
 {
-  struct program_space *pspace;
-
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     {
       struct symbol_cache *cache;
 
     {
       struct symbol_cache *cache;
 
@@ -1552,9 +1548,7 @@ maintenance_print_symbol_cache (const char *args, int from_tty)
 static void
 maintenance_flush_symbol_cache (const char *args, int from_tty)
 {
 static void
 maintenance_flush_symbol_cache (const char *args, int from_tty)
 {
-  struct program_space *pspace;
-
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     {
       symbol_cache_flush (pspace);
     }
     {
       symbol_cache_flush (pspace);
     }
@@ -1597,9 +1591,7 @@ symbol_cache_stats (struct symbol_cache *cache)
 static void
 maintenance_print_symbol_cache_statistics (const char *args, int from_tty)
 {
 static void
 maintenance_print_symbol_cache_statistics (const char *args, int from_tty)
 {
-  struct program_space *pspace;
-
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     {
       struct symbol_cache *cache;
 
     {
       struct symbol_cache *cache;
 
@@ -1649,7 +1641,8 @@ fixup_section (struct general_symbol_info *ginfo,
      e.g. on PowerPC64, where the minimal symbol for a function will
      point to the function descriptor, while the debug symbol will
      point to the actual function code.  */
      e.g. on PowerPC64, where the minimal symbol for a function will
      point to the function descriptor, while the debug symbol will
      point to the actual function code.  */
-  msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->name, objfile);
+  msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->linkage_name (),
+                                          objfile);
   if (msym)
     ginfo->section = MSYMBOL_SECTION (msym);
   else
   if (msym)
     ginfo->section = MSYMBOL_SECTION (msym);
   else
@@ -1666,11 +1659,10 @@ fixup_section (struct general_symbol_info *ginfo,
 
         So, instead, search the section table when lookup by name has
         failed.  The ``addr'' and ``endaddr'' fields may have already
 
         So, instead, search the section table when lookup by name has
         failed.  The ``addr'' and ``endaddr'' fields may have already
-        been relocated.  If so, the relocation offset (i.e. the
-        ANOFFSET value) needs to be subtracted from these values when
-        performing the comparison.  We unconditionally subtract it,
-        because, when no relocation has been performed, the ANOFFSET
-        value will simply be zero.
+        been relocated.  If so, the relocation offset needs to be
+        subtracted from these values when performing the comparison.
+        We unconditionally subtract it, because, when no relocation
+        has been performed, the value will simply be zero.
 
         The address of the symbol whose section we're fixing up HAS
         NOT BEEN adjusted (relocated) yet.  It can't have been since
 
         The address of the symbol whose section we're fixing up HAS
         NOT BEEN adjusted (relocated) yet.  It can't have been since
@@ -1696,7 +1688,7 @@ fixup_section (struct general_symbol_info *ginfo,
       ALL_OBJFILE_OSECTIONS (objfile, s)
        {
          int idx = s - objfile->sections;
       ALL_OBJFILE_OSECTIONS (objfile, s)
        {
          int idx = s - objfile->sections;
-         CORE_ADDR offset = ANOFFSET (objfile->section_offsets, idx);
+         CORE_ADDR offset = objfile->section_offsets[idx];
 
          if (fallback == -1)
            fallback = idx;
 
          if (fallback == -1)
            fallback = idx;
@@ -1759,7 +1751,7 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
       return sym;
     }
 
       return sym;
     }
 
-  fixup_section (&sym->ginfo, addr, objfile);
+  fixup_section (sym, addr, objfile);
 
   return sym;
 }
 
   return sym;
 }
@@ -1774,7 +1766,7 @@ demangle_for_lookup_info::demangle_for_lookup_info
   if (lookup_name.ignore_parameters () && lang == language_cplus)
     {
       gdb::unique_xmalloc_ptr<char> without_params
   if (lookup_name.ignore_parameters () && lang == language_cplus)
     {
       gdb::unique_xmalloc_ptr<char> without_params
-       = cp_remove_params_if_any (lookup_name.name ().c_str (),
+       = cp_remove_params_if_any (lookup_name.c_str (),
                                   lookup_name.completion_mode ());
 
       if (without_params != NULL)
                                   lookup_name.completion_mode ());
 
       if (without_params != NULL)
@@ -1787,9 +1779,9 @@ demangle_for_lookup_info::demangle_for_lookup_info
     }
 
   if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
     }
 
   if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
-    m_demangled_name = lookup_name.name ();
+    m_demangled_name = lookup_name.c_str ();
   else
   else
-    m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (),
+    m_demangled_name = demangle_for_lookup (lookup_name.c_str (),
                                            lang, storage);
 }
 
                                            lang, storage);
 }
 
@@ -1800,7 +1792,7 @@ lookup_name_info::match_any ()
 {
   /* Lookup any symbol that "" would complete.  I.e., this matches all
      symbol names.  */
 {
   /* Lookup any symbol that "" would complete.  I.e., this matches all
      symbol names.  */
-  static const lookup_name_info lookup_name ({}, symbol_name_match_type::FULL,
+  static const lookup_name_info lookup_name ("", symbol_name_match_type::FULL,
                                             true);
 
   return lookup_name;
                                             true);
 
   return lookup_name;
@@ -1838,9 +1830,9 @@ demangle_for_lookup (const char *name, enum language lang,
 
       /* If we were given a non-mangled name, canonicalize it
         according to the language (so far only for C++).  */
 
       /* If we were given a non-mangled name, canonicalize it
         according to the language (so far only for C++).  */
-      std::string canon = cp_canonicalize_string (name);
-      if (!canon.empty ())
-       return storage.swap_string (canon);
+      gdb::unique_xmalloc_ptr<char> canon = cp_canonicalize_string (name);
+      if (canon != nullptr)
+       return storage.set_malloc_ptr (std::move (canon));
     }
   else if (lang == language_d)
     {
     }
   else if (lang == language_d)
     {
@@ -1863,7 +1855,7 @@ demangle_for_lookup (const char *name, enum language lang,
 unsigned int
 search_name_hash (enum language language, const char *search_name)
 {
 unsigned int
 search_name_hash (enum language language, const char *search_name)
 {
-  return language_def (language)->la_search_name_hash (search_name);
+  return language_def (language)->search_name_hash (search_name);
 }
 
 /* See symtab.h.
 }
 
 /* See symtab.h.
@@ -1925,7 +1917,7 @@ lookup_language_this (const struct language_defn *lang,
 
   if (symbol_lookup_debug > 1)
     {
 
   if (symbol_lookup_debug > 1)
     {
-      struct objfile *objfile = lookup_objfile_from_block (block);
+      struct objfile *objfile = block_objfile (block);
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_language_this (%s, %s (objfile %s))",
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_language_this (%s, %s (objfile %s))",
@@ -1945,7 +1937,7 @@ lookup_language_this (const struct language_defn *lang,
          if (symbol_lookup_debug > 1)
            {
              fprintf_unfiltered (gdb_stdlog, " = %s (%s, block %s)\n",
          if (symbol_lookup_debug > 1)
            {
              fprintf_unfiltered (gdb_stdlog, " = %s (%s, block %s)\n",
-                                 SYMBOL_PRINT_NAME (sym),
+                                 sym->print_name (),
                                  host_address_to_string (sym),
                                  host_address_to_string (block));
            }
                                  host_address_to_string (sym),
                                  host_address_to_string (block));
            }
@@ -1974,14 +1966,14 @@ check_field (struct type *type, const char *name,
   /* The type may be a stub.  */
   type = check_typedef (type);
 
   /* The type may be a stub.  */
   type = check_typedef (type);
 
-  for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+  for (i = type->num_fields () - 1; i >= TYPE_N_BASECLASSES (type); i--)
     {
       const char *t_field_name = TYPE_FIELD_NAME (type, i);
 
       if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
        {
          is_a_field_of_this->type = type;
     {
       const char *t_field_name = TYPE_FIELD_NAME (type, i);
 
       if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
        {
          is_a_field_of_this->type = type;
-         is_a_field_of_this->field = &TYPE_FIELD (type, i);
+         is_a_field_of_this->field = &type->field (i);
          return 1;
        }
     }
          return 1;
        }
     }
@@ -2020,7 +2012,8 @@ lookup_symbol_aux (const char *name, symbol_name_match_type match_type,
 
   if (symbol_lookup_debug)
     {
 
   if (symbol_lookup_debug)
     {
-      struct objfile *objfile = lookup_objfile_from_block (block);
+      struct objfile *objfile = (block == nullptr
+                                ? nullptr : block_objfile (block));
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_symbol_aux (%s, %s (objfile %s), %s, %s)\n",
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_symbol_aux (%s, %s (objfile %s), %s, %s)\n",
@@ -2070,11 +2063,11 @@ lookup_symbol_aux (const char *name, symbol_name_match_type match_type,
          /* I'm not really sure that type of this can ever
             be typedefed; just be safe.  */
          t = check_typedef (t);
          /* I'm not really sure that type of this can ever
             be typedefed; just be safe.  */
          t = check_typedef (t);
-         if (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_IS_REFERENCE (t))
+         if (t->code () == TYPE_CODE_PTR || TYPE_IS_REFERENCE (t))
            t = TYPE_TARGET_TYPE (t);
 
            t = TYPE_TARGET_TYPE (t);
 
-         if (TYPE_CODE (t) != TYPE_CODE_STRUCT
-             && TYPE_CODE (t) != TYPE_CODE_UNION)
+         if (t->code () != TYPE_CODE_STRUCT
+             && t->code () != TYPE_CODE_UNION)
            error (_("Internal error: `%s' is not an aggregate"),
                   langdef->la_name_of_this);
 
            error (_("Internal error: `%s' is not an aggregate"),
                   langdef->la_name_of_this);
 
@@ -2165,32 +2158,6 @@ lookup_local_symbol (const char *name,
 
 /* See symtab.h.  */
 
 
 /* See symtab.h.  */
 
-struct objfile *
-lookup_objfile_from_block (const struct block *block)
-{
-  if (block == NULL)
-    return NULL;
-
-  block = block_global_block (block);
-  /* Look through all blockvectors.  */
-  for (objfile *obj : current_program_space->objfiles ())
-    {
-      for (compunit_symtab *cust : obj->compunits ())
-       if (block == BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust),
-                                       GLOBAL_BLOCK))
-         {
-           if (obj->separate_debug_objfile_backlink)
-             obj = obj->separate_debug_objfile_backlink;
-
-           return obj;
-         }
-    }
-
-  return NULL;
-}
-
-/* See symtab.h.  */
-
 struct symbol *
 lookup_symbol_in_block (const char *name, symbol_name_match_type match_type,
                        const struct block *block,
 struct symbol *
 lookup_symbol_in_block (const char *name, symbol_name_match_type match_type,
                        const struct block *block,
@@ -2200,7 +2167,8 @@ lookup_symbol_in_block (const char *name, symbol_name_match_type match_type,
 
   if (symbol_lookup_debug > 1)
     {
 
   if (symbol_lookup_debug > 1)
     {
-      struct objfile *objfile = lookup_objfile_from_block (block);
+      struct objfile *objfile = (block == nullptr
+                                ? nullptr : block_objfile (block));
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_symbol_in_block (%s, %s (objfile %s), %s)",
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_symbol_in_block (%s, %s (objfile %s), %s)",
@@ -2269,6 +2237,8 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile,
                          name, domain_name (domain));
     }
 
                          name, domain_name (domain));
     }
 
+  struct block_symbol other;
+  other.symbol = NULL;
   for (compunit_symtab *cust : objfile->compunits ())
     {
       const struct blockvector *bv;
   for (compunit_symtab *cust : objfile->compunits ())
     {
       const struct blockvector *bv;
@@ -2279,18 +2249,36 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile,
       block = BLOCKVECTOR_BLOCK (bv, block_index);
       result.symbol = block_lookup_symbol_primary (block, name, domain);
       result.block = block;
       block = BLOCKVECTOR_BLOCK (bv, block_index);
       result.symbol = block_lookup_symbol_primary (block, name, domain);
       result.block = block;
-      if (result.symbol != NULL)
+      if (result.symbol == NULL)
+       continue;
+      if (best_symbol (result.symbol, domain))
        {
        {
-         if (symbol_lookup_debug > 1)
+         other = result;
+         break;
+       }
+      if (symbol_matches_domain (result.symbol->language (),
+                                SYMBOL_DOMAIN (result.symbol), domain))
+       {
+         struct symbol *better
+           = better_symbol (other.symbol, result.symbol, domain);
+         if (better != other.symbol)
            {
            {
-             fprintf_unfiltered (gdb_stdlog, " = %s (block %s)\n",
-                                 host_address_to_string (result.symbol),
-                                 host_address_to_string (block));
+             other.symbol = better;
+             other.block = block;
            }
            }
-         result.symbol = fixup_symbol_section (result.symbol, objfile);
-         return result;
+       }
+    }
 
 
+  if (other.symbol != NULL)
+    {
+      if (symbol_lookup_debug > 1)
+       {
+         fprintf_unfiltered (gdb_stdlog, " = %s (block %s)\n",
+                             host_address_to_string (other.symbol),
+                             host_address_to_string (other.block));
        }
        }
+      other.symbol = fixup_symbol_section (other.symbol, objfile);
+      return other;
     }
 
   if (symbol_lookup_debug > 1)
     }
 
   if (symbol_lookup_debug > 1)
@@ -2470,7 +2458,8 @@ lookup_symbol_in_static_block (const char *name,
 
   if (symbol_lookup_debug)
     {
 
   if (symbol_lookup_debug)
     {
-      struct objfile *objfile = lookup_objfile_from_block (static_block);
+      struct objfile *objfile = (block == nullptr
+                                ? nullptr : block_objfile (block));
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_symbol_in_static_block (%s, %s (objfile %s),"
 
       fprintf_unfiltered (gdb_stdlog,
                          "lookup_symbol_in_static_block (%s, %s (objfile %s),"
@@ -2544,6 +2533,33 @@ lookup_symbol_in_objfile (struct objfile *objfile, enum block_enum block_index,
   return result;
 }
 
   return result;
 }
 
+/* Find the language for partial symbol with NAME.  */
+
+static enum language
+find_quick_global_symbol_language (const char *name, const domain_enum domain)
+{
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      if (objfile->sf && objfile->sf->qf
+         && objfile->sf->qf->lookup_global_symbol_language)
+       continue;
+      return language_unknown;
+    }
+
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      bool symbol_found_p;
+      enum language lang
+       = objfile->sf->qf->lookup_global_symbol_language (objfile, name, domain,
+                                                         &symbol_found_p);
+      if (!symbol_found_p)
+       continue;
+      return lang;
+    }
+
+  return language_unknown;
+}
+
 /* Private data to be used with lookup_symbol_global_iterator_cb.  */
 
 struct global_or_static_sym_lookup_data
 /* Private data to be used with lookup_symbol_global_iterator_cb.  */
 
 struct global_or_static_sym_lookup_data
@@ -2623,7 +2639,7 @@ lookup_global_or_static_symbol (const char *name,
       lookup_data.block_index = block_index;
       lookup_data.domain = domain;
       gdbarch_iterate_over_objfiles_in_search_order
       lookup_data.block_index = block_index;
       lookup_data.domain = domain;
       gdbarch_iterate_over_objfiles_in_search_order
-       (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch (),
+       (objfile != NULL ? objfile->arch () : target_gdbarch (),
         lookup_symbol_global_or_static_iterator_cb, &lookup_data, objfile);
       result = lookup_data.result;
     }
         lookup_symbol_global_or_static_iterator_cb, &lookup_data, objfile);
       result = lookup_data.result;
     }
@@ -2655,17 +2671,30 @@ lookup_global_symbol (const char *name,
      global block first.  This yields "more expected" behavior, and is
      needed to support 'FILENAME'::VARIABLE lookups.  */
   const struct block *global_block = block_global_block (block);
      global block first.  This yields "more expected" behavior, and is
      needed to support 'FILENAME'::VARIABLE lookups.  */
   const struct block *global_block = block_global_block (block);
+  symbol *sym = NULL;
   if (global_block != nullptr)
     {
   if (global_block != nullptr)
     {
-      symbol *sym = lookup_symbol_in_block (name,
-                                           symbol_name_match_type::FULL,
-                                           global_block, domain);
-      if (sym != nullptr)
+      sym = lookup_symbol_in_block (name,
+                                   symbol_name_match_type::FULL,
+                                   global_block, domain);
+      if (sym != NULL && best_symbol (sym, domain))
        return { sym, global_block };
     }
 
        return { sym, global_block };
     }
 
-  struct objfile *objfile = lookup_objfile_from_block (block);
-  return lookup_global_or_static_symbol (name, GLOBAL_BLOCK, objfile, domain);
+  struct objfile *objfile = nullptr;
+  if (block != nullptr)
+    {
+      objfile = block_objfile (block);
+      if (objfile->separate_debug_objfile_backlink != nullptr)
+       objfile = objfile->separate_debug_objfile_backlink;
+    }
+
+  block_symbol bs
+    = lookup_global_or_static_symbol (name, GLOBAL_BLOCK, objfile, domain);
+  if (better_symbol (sym, bs.symbol, domain) == sym)
+    return { sym, global_block };
+  else
+    return bs;
 }
 
 bool
 }
 
 bool
@@ -2693,7 +2722,7 @@ symbol_matches_domain (enum language symbol_language,
 struct type *
 lookup_transparent_type (const char *name)
 {
 struct type *
 lookup_transparent_type (const char *name)
 {
-  return current_language->la_lookup_transparent_type (name);
+  return current_language->lookup_transparent_type (name);
 }
 
 /* A helper for basic_lookup_transparent_type that interfaces with the
 }
 
 /* A helper for basic_lookup_transparent_type that interfaces with the
@@ -2822,8 +2851,7 @@ iterate_over_symbols (const struct block *block,
 
   ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym)
     {
 
   ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym)
     {
-      if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
-                                SYMBOL_DOMAIN (sym), domain))
+      if (symbol_matches_domain (sym->language (), SYMBOL_DOMAIN (sym), domain))
        {
          struct block_symbol block_sym = {sym, block};
 
        {
          struct block_symbol block_sym = {sym, block};
 
@@ -3117,7 +3145,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
     if (MSYMBOL_TYPE (msymbol.minsym) == mst_solib_trampoline)
       {
        struct bound_minimal_symbol mfunsym
     if (MSYMBOL_TYPE (msymbol.minsym) == mst_solib_trampoline)
       {
        struct bound_minimal_symbol mfunsym
-         = lookup_minimal_symbol_text (MSYMBOL_LINKAGE_NAME (msymbol.minsym),
+         = lookup_minimal_symbol_text (msymbol.minsym->linkage_name (),
                                        NULL);
 
        if (mfunsym.minsym == NULL)
                                        NULL);
 
        if (mfunsym.minsym == NULL)
@@ -3131,7 +3159,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
           * but the "break" still works, and the warning is annoying.
           * So I commented out the warning.  RT */
          /* warning ("In stub for %s; unable to find real function/line info",
           * but the "break" still works, and the warning is annoying.
           * So I commented out the warning.  RT */
          /* warning ("In stub for %s; unable to find real function/line info",
-            SYMBOL_LINKAGE_NAME (msymbol)); */
+            msymbol->linkage_name ()); */
          ;
        /* fall through */
        else if (BMSYMBOL_VALUE_ADDRESS (mfunsym)
          ;
        /* fall through */
        else if (BMSYMBOL_VALUE_ADDRESS (mfunsym)
@@ -3139,11 +3167,21 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
          /* Avoid infinite recursion */
          /* See above comment about why warning is commented out.  */
          /* warning ("In stub for %s; unable to find real function/line info",
          /* Avoid infinite recursion */
          /* See above comment about why warning is commented out.  */
          /* warning ("In stub for %s; unable to find real function/line info",
-            SYMBOL_LINKAGE_NAME (msymbol)); */
+            msymbol->linkage_name ()); */
          ;
        /* fall through */
        else
          ;
        /* fall through */
        else
-         return find_pc_line (BMSYMBOL_VALUE_ADDRESS (mfunsym), 0);
+         {
+           /* Detect an obvious case of infinite recursion.  If this
+              should occur, we'd like to know about it, so error out,
+              fatally.  */
+           if (BMSYMBOL_VALUE_ADDRESS (mfunsym) == pc)
+             internal_error (__FILE__, __LINE__,
+               _("Infinite recursion detected in find_pc_sect_line;"
+                 "please file a bug report"));
+
+           return find_pc_line (BMSYMBOL_VALUE_ADDRESS (mfunsym), 0);
+         }
       }
 
   symtab_and_line val;
       }
 
   symtab_and_line val;
@@ -3199,7 +3237,12 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
       struct linetable_entry *last = item + len;
       item = std::upper_bound (first, last, pc, pc_compare);
       if (item != first)
       struct linetable_entry *last = item + len;
       item = std::upper_bound (first, last, pc, pc_compare);
       if (item != first)
-       prev = item - 1;                /* Found a matching item.  */
+       {
+         /* Found a matching item.  Skip backwards over any end of
+            sequence markers.  */
+         for (prev = item - 1; prev->line == 0 && prev != first; prev--)
+           /* Nothing.  */;
+       }
 
       /* At this point, prev points at the line whose start addr is <= pc, and
          item points at the next line.  If we ran off the end of the linetable
 
       /* At this point, prev points at the line whose start addr is <= pc, and
          item points at the next line.  If we ran off the end of the linetable
@@ -3216,6 +3259,23 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
          best = prev;
          best_symtab = iter_s;
 
          best = prev;
          best_symtab = iter_s;
 
+         /* If during the binary search we land on a non-statement entry,
+            scan backward through entries at the same address to see if
+            there is an entry marked as is-statement.  In theory this
+            duplication should have been removed from the line table
+            during construction, this is just a double check.  If the line
+            table has had the duplication removed then this should be
+            pretty cheap.  */
+         if (!best->is_stmt)
+           {
+             struct linetable_entry *tmp = best;
+             while (tmp > first && (tmp - 1)->pc == tmp->pc
+                    && (tmp - 1)->line != 0 && !tmp->is_stmt)
+               --tmp;
+             if (tmp->is_stmt)
+               best = tmp;
+           }
+
          /* Discard BEST_END if it's before the PC of the current BEST.  */
          if (best_end <= best->pc)
            best_end = 0;
          /* Discard BEST_END if it's before the PC of the current BEST.  */
          if (best_end <= best->pc)
            best_end = 0;
@@ -3246,6 +3306,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
     }
   else
     {
     }
   else
     {
+      val.is_stmt = best->is_stmt;
       val.symtab = best_symtab;
       val.line = best->line;
       val.pc = best->pc;
       val.symtab = best_symtab;
       val.line = best->line;
       val.pc = best->pc;
@@ -3414,7 +3475,8 @@ find_pcs_for_symtab_line (struct symtab *symtab, int line,
        {
          struct linetable_entry *item = &SYMTAB_LINETABLE (symtab)->item[idx];
 
        {
          struct linetable_entry *item = &SYMTAB_LINETABLE (symtab)->item[idx];
 
-         if (*best_item == NULL || item->line < (*best_item)->line)
+         if (*best_item == NULL
+             || (item->line < (*best_item)->line && item->is_stmt))
            *best_item = item;
 
          break;
            *best_item = item;
 
          break;
@@ -3525,6 +3587,10 @@ find_line_common (struct linetable *l, int lineno,
     {
       struct linetable_entry *item = &(l->item[i]);
 
     {
       struct linetable_entry *item = &(l->item[i]);
 
+      /* Ignore non-statements.  */
+      if (!item->is_stmt)
+       continue;
+
       if (item->line == lineno)
        {
          /* Return the first (lowest address) entry which matches.  */
       if (item->line == lineno)
        {
          /* Return the first (lowest address) entry which matches.  */
@@ -3567,7 +3633,7 @@ find_function_start_sal_1 (CORE_ADDR func_addr, obj_section *section,
       && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
          || SYMTAB_LANGUAGE (sal.symtab) == language_asm))
     {
       && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
          || SYMTAB_LANGUAGE (sal.symtab) == language_asm))
     {
-      struct gdbarch *gdbarch = get_objfile_arch (SYMTAB_OBJFILE (sal.symtab));
+      struct gdbarch *gdbarch = SYMTAB_OBJFILE (sal.symtab)->arch ();
 
       sal.pc = func_addr;
       if (gdbarch_skip_entrypoint_p (gdbarch))
 
       sal.pc = func_addr;
       if (gdbarch_skip_entrypoint_p (gdbarch))
@@ -3710,7 +3776,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
       objfile = symbol_objfile (sym);
       pc = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
       section = SYMBOL_OBJ_SECTION (objfile, sym);
       objfile = symbol_objfile (sym);
       pc = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
       section = SYMBOL_OBJ_SECTION (objfile, sym);
-      name = SYMBOL_LINKAGE_NAME (sym);
+      name = sym->linkage_name ();
     }
   else
     {
     }
   else
     {
@@ -3723,10 +3789,10 @@ skip_prologue_sal (struct symtab_and_line *sal)
       objfile = msymbol.objfile;
       pc = BMSYMBOL_VALUE_ADDRESS (msymbol);
       section = MSYMBOL_OBJ_SECTION (objfile, msymbol.minsym);
       objfile = msymbol.objfile;
       pc = BMSYMBOL_VALUE_ADDRESS (msymbol);
       section = MSYMBOL_OBJ_SECTION (objfile, msymbol.minsym);
-      name = MSYMBOL_LINKAGE_NAME (msymbol.minsym);
+      name = msymbol.minsym->linkage_name ();
     }
 
     }
 
-  gdbarch = get_objfile_arch (objfile);
+  gdbarch = objfile->arch ();
 
   /* Process the prologue in two passes.  In the first pass try to skip the
      prologue (SKIP is true) and verify there is a real need for it (indicated
 
   /* Process the prologue in two passes.  In the first pass try to skip the
      prologue (SKIP is true) and verify there is a real need for it (indicated
@@ -4339,31 +4405,28 @@ info_sources_command (const char *args, int from_tty)
   printf_filtered ("\n");
 }
 
   printf_filtered ("\n");
 }
 
-/* Compare FILE against all the NFILES entries of FILES.  If BASENAMES is
-   non-zero compare only lbasename of FILES.  */
+/* Compare FILE against all the entries of FILENAMES.  If BASENAMES is
+   true compare only lbasename of FILENAMES.  */
 
 
-static int
-file_matches (const char *file, const char *files[], int nfiles, int basenames)
+static bool
+file_matches (const char *file, const std::vector<const char *> &filenames,
+             bool basenames)
 {
 {
-  int i;
+  if (filenames.empty ())
+    return true;
 
 
-  if (file != NULL && nfiles != 0)
+  for (const char *name : filenames)
     {
     {
-      for (i = 0; i < nfiles; i++)
-       {
-         if (compare_filenames_for_search (file, (basenames
-                                                  ? lbasename (files[i])
-                                                  : files[i])))
-           return 1;
-       }
+      name = (basenames ? lbasename (name) : name);
+      if (compare_filenames_for_search (file, name))
+       return true;
     }
     }
-  else if (nfiles == 0)
-    return 1;
-  return 0;
+
+  return false;
 }
 
 }
 
-/* Helper function for sort_search_symbols_remove_dups and qsort.  Can only
-   sort symbols, not minimal symbols.  */
+/* Helper function for std::sort on symbol_search objects.  Can only sort
+   symbols, not minimal symbols.  */
 
 int
 symbol_search::compare_search_syms (const symbol_search &sym_a,
 
 int
 symbol_search::compare_search_syms (const symbol_search &sym_a,
@@ -4379,8 +4442,7 @@ symbol_search::compare_search_syms (const symbol_search &sym_a,
   if (sym_a.block != sym_b.block)
     return sym_a.block - sym_b.block;
 
   if (sym_a.block != sym_b.block)
     return sym_a.block - sym_b.block;
 
-  return strcmp (SYMBOL_PRINT_NAME (sym_a.symbol),
-                SYMBOL_PRINT_NAME (sym_b.symbol));
+  return strcmp (sym_a.symbol->print_name (), sym_b.symbol->print_name ());
 }
 
 /* Returns true if the type_name of symbol_type of SYM matches TREG.
 }
 
 /* Returns true if the type_name of symbol_type of SYM matches TREG.
@@ -4397,7 +4459,7 @@ treg_matches_sym_type_name (const compiled_regex &treg,
     {
       fprintf_unfiltered (gdb_stdlog,
                          "treg_matches_sym_type_name\n     sym %s\n",
     {
       fprintf_unfiltered (gdb_stdlog,
                          "treg_matches_sym_type_name\n     sym %s\n",
-                         SYMBOL_NATURAL_NAME (sym));
+                         sym->natural_name ());
     }
 
   sym_type = SYMBOL_TYPE (sym);
     }
 
   sym_type = SYMBOL_TYPE (sym);
@@ -4425,79 +4487,255 @@ treg_matches_sym_type_name (const compiled_regex &treg,
   return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
 }
 
   return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
 }
 
+/* See symtab.h.  */
+
+bool
+global_symbol_searcher::is_suitable_msymbol
+       (const enum search_domain kind, const minimal_symbol *msymbol)
+{
+  switch (MSYMBOL_TYPE (msymbol))
+    {
+    case mst_data:
+    case mst_bss:
+    case mst_file_data:
+    case mst_file_bss:
+      return kind == VARIABLES_DOMAIN;
+    case mst_text:
+    case mst_file_text:
+    case mst_solib_trampoline:
+    case mst_text_gnu_ifunc:
+      return kind == FUNCTIONS_DOMAIN;
+    default:
+      return false;
+    }
+}
+
+/* See symtab.h.  */
 
 
-/* Sort the symbols in RESULT and remove duplicates.  */
+bool
+global_symbol_searcher::expand_symtabs
+       (objfile *objfile, const gdb::optional<compiled_regex> &preg) const
+{
+  enum search_domain kind = m_kind;
+  bool found_msymbol = false;
+
+  if (objfile->sf)
+    objfile->sf->qf->expand_symtabs_matching
+      (objfile,
+       [&] (const char *filename, bool basenames)
+       {
+        return file_matches (filename, filenames, basenames);
+       },
+       &lookup_name_info::match_any (),
+       [&] (const char *symname)
+       {
+        return (!preg.has_value ()
+                || preg->exec (symname, 0, NULL, 0) == 0);
+       },
+       NULL,
+       kind);
+
+  /* Here, we search through the minimal symbol tables for functions and
+     variables that match, and force their symbols to be read.  This is in
+     particular necessary for demangled variable names, which are no longer
+     put into the partial symbol tables.  The symbol will then be found
+     during the scan of symtabs later.
+
+     For functions, find_pc_symtab should succeed if we have debug info for
+     the function, for variables we have to call
+     lookup_symbol_in_objfile_from_linkage_name to determine if the
+     variable has debug info.  If the lookup fails, set found_msymbol so
+     that we will rescan to print any matching symbols without debug info.
+     We only search the objfile the msymbol came from, we no longer search
+     all objfiles.  In large programs (1000s of shared libs) searching all
+     objfiles is not worth the pain.  */
+  if (filenames.empty ()
+      && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
+    {
+      for (minimal_symbol *msymbol : objfile->msymbols ())
+       {
+         QUIT;
 
 
-static void
-sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
+         if (msymbol->created_by_gdb)
+           continue;
+
+         if (is_suitable_msymbol (kind, msymbol))
+           {
+             if (!preg.has_value ()
+                 || preg->exec (msymbol->natural_name (), 0,
+                                NULL, 0) == 0)
+               {
+                 /* An important side-effect of these lookup functions is
+                    to expand the symbol table if msymbol is found, later
+                    in the process we will add matching symbols or
+                    msymbols to the results list, and that requires that
+                    the symbols tables are expanded.  */
+                 if (kind == FUNCTIONS_DOMAIN
+                     ? (find_pc_compunit_symtab
+                        (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
+                        == NULL)
+                     : (lookup_symbol_in_objfile_from_linkage_name
+                        (objfile, msymbol->linkage_name (),
+                         VAR_DOMAIN)
+                        .symbol == NULL))
+                   found_msymbol = true;
+               }
+           }
+       }
+    }
+
+  return found_msymbol;
+}
+
+/* See symtab.h.  */
+
+bool
+global_symbol_searcher::add_matching_symbols
+       (objfile *objfile,
+        const gdb::optional<compiled_regex> &preg,
+        const gdb::optional<compiled_regex> &treg,
+        std::set<symbol_search> *result_set) const
 {
 {
-  std::sort (result->begin (), result->end ());
-  result->erase (std::unique (result->begin (), result->end ()),
-                result->end ());
+  enum search_domain kind = m_kind;
+
+  /* Add matching symbols (if not already present).  */
+  for (compunit_symtab *cust : objfile->compunits ())
+    {
+      const struct blockvector *bv  = COMPUNIT_BLOCKVECTOR (cust);
+
+      for (block_enum block : { GLOBAL_BLOCK, STATIC_BLOCK })
+       {
+         struct block_iterator iter;
+         struct symbol *sym;
+         const struct block *b = BLOCKVECTOR_BLOCK (bv, block);
+
+         ALL_BLOCK_SYMBOLS (b, iter, sym)
+           {
+             struct symtab *real_symtab = symbol_symtab (sym);
+
+             QUIT;
+
+             /* Check first sole REAL_SYMTAB->FILENAME.  It does
+                not need to be a substring of symtab_to_fullname as
+                it may contain "./" etc.  */
+             if ((file_matches (real_symtab->filename, filenames, false)
+                  || ((basenames_may_differ
+                       || file_matches (lbasename (real_symtab->filename),
+                                        filenames, true))
+                      && file_matches (symtab_to_fullname (real_symtab),
+                                       filenames, false)))
+                 && ((!preg.has_value ()
+                      || preg->exec (sym->natural_name (), 0,
+                                     NULL, 0) == 0)
+                     && ((kind == VARIABLES_DOMAIN
+                          && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+                          && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
+                          && SYMBOL_CLASS (sym) != LOC_BLOCK
+                          /* LOC_CONST can be used for more than
+                             just enums, e.g., c++ static const
+                             members.  We only want to skip enums
+                             here.  */
+                          && !(SYMBOL_CLASS (sym) == LOC_CONST
+                               && (SYMBOL_TYPE (sym)->code ()
+                                   == TYPE_CODE_ENUM))
+                          && (!treg.has_value ()
+                              || treg_matches_sym_type_name (*treg, sym)))
+                         || (kind == FUNCTIONS_DOMAIN
+                             && SYMBOL_CLASS (sym) == LOC_BLOCK
+                             && (!treg.has_value ()
+                                 || treg_matches_sym_type_name (*treg,
+                                                                sym)))
+                         || (kind == TYPES_DOMAIN
+                             && SYMBOL_CLASS (sym) == LOC_TYPEDEF
+                             && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN)
+                         || (kind == MODULES_DOMAIN
+                             && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
+                             && SYMBOL_LINE (sym) != 0))))
+               {
+                 if (result_set->size () < m_max_search_results)
+                   {
+                     /* Match, insert if not already in the results.  */
+                     symbol_search ss (block, sym);
+                     if (result_set->find (ss) == result_set->end ())
+                       result_set->insert (ss);
+                   }
+                 else
+                   return false;
+               }
+           }
+       }
+    }
+
+  return true;
 }
 
 }
 
-/* Search the symbol table for matches to the regular expression REGEXP,
-   returning the results.
+/* See symtab.h.  */
+
+bool
+global_symbol_searcher::add_matching_msymbols
+       (objfile *objfile, const gdb::optional<compiled_regex> &preg,
+        std::vector<symbol_search> *results) const
+{
+  enum search_domain kind = m_kind;
 
 
-   Only symbols of KIND are searched:
-   VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
-                      and constants (enums).
-                     if T_REGEXP is not NULL, only returns var that have
-                     a type matching regular expression T_REGEXP.
-   FUNCTIONS_DOMAIN - search all functions
-   TYPES_DOMAIN     - search all type names
-   ALL_DOMAIN       - an internal error for this function
+  for (minimal_symbol *msymbol : objfile->msymbols ())
+    {
+      QUIT;
+
+      if (msymbol->created_by_gdb)
+       continue;
+
+      if (is_suitable_msymbol (kind, msymbol))
+       {
+         if (!preg.has_value ()
+             || preg->exec (msymbol->natural_name (), 0,
+                            NULL, 0) == 0)
+           {
+             /* For functions we can do a quick check of whether the
+                symbol might be found via find_pc_symtab.  */
+             if (kind != FUNCTIONS_DOMAIN
+                 || (find_pc_compunit_symtab
+                     (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
+                     == NULL))
+               {
+                 if (lookup_symbol_in_objfile_from_linkage_name
+                     (objfile, msymbol->linkage_name (),
+                      VAR_DOMAIN).symbol == NULL)
+                   {
+                     /* Matching msymbol, add it to the results list.  */
+                     if (results->size () < m_max_search_results)
+                       results->emplace_back (GLOBAL_BLOCK, msymbol, objfile);
+                     else
+                       return false;
+                   }
+               }
+           }
+       }
+    }
 
 
-   Within each file the results are sorted locally; each symtab's global and
-   static blocks are separately alphabetized.
-   Duplicate entries are removed.
+  return true;
+}
 
 
-   When EXCLUDE_MINSYMS is false then matching minsyms are also returned,
-   otherwise they are excluded.  */
+/* See symtab.h.  */
 
 std::vector<symbol_search>
 
 std::vector<symbol_search>
-search_symbols (const char *regexp, enum search_domain kind,
-               const char *t_regexp,
-               int nfiles, const char *files[],
-               bool exclude_minsyms)
+global_symbol_searcher::search () const
 {
 {
-  const struct blockvector *bv;
-  const struct block *b;
-  int i = 0;
-  struct block_iterator iter;
-  struct symbol *sym;
-  int found_misc = 0;
-  static const enum minimal_symbol_type types[]
-    = {mst_data, mst_text, mst_unknown};
-  static const enum minimal_symbol_type types2[]
-    = {mst_bss, mst_file_text, mst_unknown};
-  static const enum minimal_symbol_type types3[]
-    = {mst_file_data, mst_solib_trampoline, mst_unknown};
-  static const enum minimal_symbol_type types4[]
-    = {mst_file_bss, mst_text_gnu_ifunc, mst_unknown};
-  enum minimal_symbol_type ourtype;
-  enum minimal_symbol_type ourtype2;
-  enum minimal_symbol_type ourtype3;
-  enum minimal_symbol_type ourtype4;
-  std::vector<symbol_search> result;
   gdb::optional<compiled_regex> preg;
   gdb::optional<compiled_regex> treg;
 
   gdb::optional<compiled_regex> preg;
   gdb::optional<compiled_regex> treg;
 
-  gdb_assert (kind != ALL_DOMAIN);
-
-  ourtype = types[kind];
-  ourtype2 = types2[kind];
-  ourtype3 = types3[kind];
-  ourtype4 = types4[kind];
+  gdb_assert (m_kind != ALL_DOMAIN);
 
 
-  if (regexp != NULL)
+  if (m_symbol_name_regexp != NULL)
     {
     {
+      const char *symbol_name_regexp = m_symbol_name_regexp;
+
       /* Make sure spacing is right for C++ operators.
          This is just a courtesy to make the matching less sensitive
          to how many spaces the user leaves between 'operator'
          and <TYPENAME> or <OPERATOR>.  */
       const char *opend;
       /* Make sure spacing is right for C++ operators.
          This is just a courtesy to make the matching less sensitive
          to how many spaces the user leaves between 'operator'
          and <TYPENAME> or <OPERATOR>.  */
       const char *opend;
-      const char *opname = operator_chars (regexp, &opend);
+      const char *opname = operator_chars (symbol_name_regexp, &opend);
 
       if (*opname)
        {
 
       if (*opname)
        {
@@ -4522,247 +4760,80 @@ search_symbols (const char *regexp, enum search_domain kind,
              char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1);
 
              sprintf (tmp, "operator%.*s%s", fix, " ", opname);
              char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1);
 
              sprintf (tmp, "operator%.*s%s", fix, " ", opname);
-             regexp = tmp;
+             symbol_name_regexp = tmp;
            }
        }
 
       int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
                                ? REG_ICASE : 0);
            }
        }
 
       int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
                                ? REG_ICASE : 0);
-      preg.emplace (regexp, cflags, _("Invalid regexp"));
+      preg.emplace (symbol_name_regexp, cflags,
+                   _("Invalid regexp"));
     }
 
     }
 
-  if (t_regexp != NULL)
+  if (m_symbol_type_regexp != NULL)
     {
       int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
                                ? REG_ICASE : 0);
     {
       int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
                                ? REG_ICASE : 0);
-      treg.emplace (t_regexp, cflags, _("Invalid regexp"));
-    }
-
-  /* Search through the partial symtabs *first* for all symbols
-     matching the regexp.  That way we don't have to reproduce all of
-     the machinery below.  */
-  expand_symtabs_matching ([&] (const char *filename, bool basenames)
-                          {
-                            return file_matches (filename, files, nfiles,
-                                                 basenames);
-                          },
-                          lookup_name_info::match_any (),
-                          [&] (const char *symname)
-                          {
-                            return (!preg.has_value ()
-                                    || preg->exec (symname,
-                                                   0, NULL, 0) == 0);
-                          },
-                          NULL,
-                          kind);
-
-  /* Here, we search through the minimal symbol tables for functions
-     and variables that match, and force their symbols to be read.
-     This is in particular necessary for demangled variable names,
-     which are no longer put into the partial symbol tables.
-     The symbol will then be found during the scan of symtabs below.
-
-     For functions, find_pc_symtab should succeed if we have debug info
-     for the function, for variables we have to call
-     lookup_symbol_in_objfile_from_linkage_name to determine if the variable
-     has debug info.
-     If the lookup fails, set found_misc so that we will rescan to print
-     any matching symbols without debug info.
-     We only search the objfile the msymbol came from, we no longer search
-     all objfiles.  In large programs (1000s of shared libs) searching all
-     objfiles is not worth the pain.  */
-
-  if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
-    {
-      for (objfile *objfile : current_program_space->objfiles ())
-       {
-         for (minimal_symbol *msymbol : objfile->msymbols ())
-           {
-             QUIT;
-
-             if (msymbol->created_by_gdb)
-               continue;
-
-             if (MSYMBOL_TYPE (msymbol) == ourtype
-                 || MSYMBOL_TYPE (msymbol) == ourtype2
-                 || MSYMBOL_TYPE (msymbol) == ourtype3
-                 || MSYMBOL_TYPE (msymbol) == ourtype4)
-               {
-                 if (!preg.has_value ()
-                     || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
-                                    NULL, 0) == 0)
-                   {
-                     /* Note: An important side-effect of these
-                        lookup functions is to expand the symbol
-                        table if msymbol is found, for the benefit of
-                        the next loop on compunits.  */
-                     if (kind == FUNCTIONS_DOMAIN
-                         ? (find_pc_compunit_symtab
-                            (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
-                            == NULL)
-                         : (lookup_symbol_in_objfile_from_linkage_name
-                            (objfile, MSYMBOL_LINKAGE_NAME (msymbol),
-                             VAR_DOMAIN)
-                            .symbol == NULL))
-                       found_misc = 1;
-                   }
-               }
-           }
-       }
+      treg.emplace (m_symbol_type_regexp, cflags,
+                   _("Invalid regexp"));
     }
 
     }
 
+  bool found_msymbol = false;
+  std::set<symbol_search> result_set;
   for (objfile *objfile : current_program_space->objfiles ())
     {
   for (objfile *objfile : current_program_space->objfiles ())
     {
-      for (compunit_symtab *cust : objfile->compunits ())
-       {
-         bv = COMPUNIT_BLOCKVECTOR (cust);
-         for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
-           {
-             b = BLOCKVECTOR_BLOCK (bv, i);
-             ALL_BLOCK_SYMBOLS (b, iter, sym)
-               {
-                 struct symtab *real_symtab = symbol_symtab (sym);
-
-                 QUIT;
-
-                 /* Check first sole REAL_SYMTAB->FILENAME.  It does
-                    not need to be a substring of symtab_to_fullname as
-                    it may contain "./" etc.  */
-                 if ((file_matches (real_symtab->filename, files, nfiles, 0)
-                      || ((basenames_may_differ
-                           || file_matches (lbasename (real_symtab->filename),
-                                            files, nfiles, 1))
-                          && file_matches (symtab_to_fullname (real_symtab),
-                                           files, nfiles, 0)))
-                     && ((!preg.has_value ()
-                          || preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
-                                         NULL, 0) == 0)
-                         && ((kind == VARIABLES_DOMAIN
-                              && SYMBOL_CLASS (sym) != LOC_TYPEDEF
-                              && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
-                              && SYMBOL_CLASS (sym) != LOC_BLOCK
-                              /* LOC_CONST can be used for more than
-                                 just enums, e.g., c++ static const
-                                 members.  We only want to skip enums
-                                 here.  */
-                              && !(SYMBOL_CLASS (sym) == LOC_CONST
-                                   && (TYPE_CODE (SYMBOL_TYPE (sym))
-                                       == TYPE_CODE_ENUM))
-                              && (!treg.has_value ()
-                                  || treg_matches_sym_type_name (*treg, sym)))
-                             || (kind == FUNCTIONS_DOMAIN
-                                 && SYMBOL_CLASS (sym) == LOC_BLOCK
-                                 && (!treg.has_value ()
-                                     || treg_matches_sym_type_name (*treg,
-                                                                    sym)))
-                             || (kind == TYPES_DOMAIN
-                                 && SYMBOL_CLASS (sym) == LOC_TYPEDEF
-                                 && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN)
-                             || (kind == MODULES_DOMAIN
-                                 && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
-                                 && SYMBOL_LINE (sym) != 0))))
-                   {
-                     /* match */
-                     result.emplace_back (i, sym);
-                   }
-               }
-           }
-       }
-    }
+      /* Expand symtabs within objfile that possibly contain matching
+        symbols.  */
+      found_msymbol |= expand_symtabs (objfile, preg);
 
 
-  if (!result.empty ())
-    sort_search_symbols_remove_dups (&result);
+      /* Find matching symbols within OBJFILE and add them in to the
+        RESULT_SET set.  Use a set here so that we can easily detect
+        duplicates as we go, and can therefore track how many unique
+        matches we have found so far.  */
+      if (!add_matching_symbols (objfile, preg, treg, &result_set))
+       break;
+    }
 
 
-  /* If there are no eyes, avoid all contact.  I mean, if there are
-     no debug symbols, then add matching minsyms.  But if the user wants
-     to see symbols matching a type regexp, then never give a minimal symbol,
-     as we assume that a minimal symbol does not have a type.  */
+  /* Convert the result set into a sorted result list, as std::set is
+     defined to be sorted then no explicit call to std::sort is needed.  */
+  std::vector<symbol_search> result (result_set.begin (), result_set.end ());
 
 
-  if ((found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
-      && !exclude_minsyms
+  /* If there are no debug symbols, then add matching minsyms.  But if the
+     user wants to see symbols matching a type regexp, then never give a
+     minimal symbol, as we assume that a minimal symbol does not have a
+     type.  */
+  if ((found_msymbol || (filenames.empty () && m_kind == VARIABLES_DOMAIN))
+      && !m_exclude_minsyms
       && !treg.has_value ())
     {
       && !treg.has_value ())
     {
+      gdb_assert (m_kind == VARIABLES_DOMAIN || m_kind == FUNCTIONS_DOMAIN);
       for (objfile *objfile : current_program_space->objfiles ())
       for (objfile *objfile : current_program_space->objfiles ())
-       {
-         for (minimal_symbol *msymbol : objfile->msymbols ())
-           {
-             QUIT;
-
-             if (msymbol->created_by_gdb)
-               continue;
-
-             if (MSYMBOL_TYPE (msymbol) == ourtype
-                 || MSYMBOL_TYPE (msymbol) == ourtype2
-                 || MSYMBOL_TYPE (msymbol) == ourtype3
-                 || MSYMBOL_TYPE (msymbol) == ourtype4)
-               {
-                 if (!preg.has_value ()
-                     || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
-                                    NULL, 0) == 0)
-                   {
-                     /* For functions we can do a quick check of whether the
-                        symbol might be found via find_pc_symtab.  */
-                     if (kind != FUNCTIONS_DOMAIN
-                         || (find_pc_compunit_symtab
-                             (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
-                             == NULL))
-                       {
-                         if (lookup_symbol_in_objfile_from_linkage_name
-                             (objfile, MSYMBOL_LINKAGE_NAME (msymbol),
-                              VAR_DOMAIN)
-                             .symbol == NULL)
-                           {
-                             /* match */
-                             result.emplace_back (i, msymbol, objfile);
-                           }
-                       }
-                   }
-               }
-           }
-       }
+       if (!add_matching_msymbols (objfile, preg, &result))
+         break;
     }
 
   return result;
 }
 
     }
 
   return result;
 }
 
-/* Helper function for symtab_symbol_info, this function uses
-   the data returned from search_symbols() to print information
-   regarding the match to gdb_stdout.  If LAST is not NULL,
-   print file and line number information for the symbol as
-   well.  Skip printing the filename if it matches LAST.  */
+/* See symtab.h.  */
 
 
-static void
-print_symbol_info (enum search_domain kind,
-                  struct symbol *sym,
-                  int block, const char *last)
+std::string
+symbol_to_info_string (struct symbol *sym, int block,
+                      enum search_domain kind)
 {
 {
-  scoped_switch_to_sym_language_if_auto l (sym);
-  struct symtab *s = symbol_symtab (sym);
+  std::string str;
 
 
-  if (last != NULL)
-    {
-      const char *s_filename = symtab_to_filename_for_display (s);
-
-      if (filename_cmp (last, s_filename) != 0)
-       {
-         printf_filtered (_("\nFile %ps:\n"),
-                          styled_string (file_name_style.style (),
-                                         s_filename));
-       }
-
-      if (SYMBOL_LINE (sym) != 0)
-       printf_filtered ("%d:\t", SYMBOL_LINE (sym));
-      else
-       puts_filtered ("\t");
-    }
+  gdb_assert (block == GLOBAL_BLOCK || block == STATIC_BLOCK);
 
   if (kind != TYPES_DOMAIN && block == STATIC_BLOCK)
 
   if (kind != TYPES_DOMAIN && block == STATIC_BLOCK)
-    printf_filtered ("static ");
+    str += "static ";
 
   /* Typedef that is not a C++ class.  */
   if (kind == TYPES_DOMAIN
       && SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN)
     {
 
   /* Typedef that is not a C++ class.  */
   if (kind == TYPES_DOMAIN
       && SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN)
     {
+      string_file tmp_stream;
+
       /* FIXME: For C (and C++) we end up with a difference in output here
         between how a typedef is printed, and non-typedefs are printed.
         The TYPEDEF_PRINT code places a ";" at the end in an attempt to
       /* FIXME: For C (and C++) we end up with a difference in output here
         between how a typedef is printed, and non-typedefs are printed.
         The TYPEDEF_PRINT code places a ";" at the end in an attempt to
@@ -4771,31 +4842,70 @@ print_symbol_info (enum search_domain kind,
         For the struct printing case below, things are worse, we force
         printing of the ";" in this function, which is going to be wrong
         for languages that don't require a ";" between statements.  */
         For the struct printing case below, things are worse, we force
         printing of the ";" in this function, which is going to be wrong
         for languages that don't require a ";" between statements.  */
-      if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_TYPEDEF)
-       typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
+      if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_TYPEDEF)
+       typedef_print (SYMBOL_TYPE (sym), sym, &tmp_stream);
       else
       else
-       {
-         type_print (SYMBOL_TYPE (sym), "", gdb_stdout, -1);
-         printf_filtered ("\n");
-       }
+       type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1);
+      str += tmp_stream.string ();
     }
   /* variable, func, or typedef-that-is-c++-class.  */
   else if (kind < TYPES_DOMAIN
           || (kind == TYPES_DOMAIN
               && SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
     {
     }
   /* variable, func, or typedef-that-is-c++-class.  */
   else if (kind < TYPES_DOMAIN
           || (kind == TYPES_DOMAIN
               && SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
     {
+      string_file tmp_stream;
+
       type_print (SYMBOL_TYPE (sym),
                  (SYMBOL_CLASS (sym) == LOC_TYPEDEF
       type_print (SYMBOL_TYPE (sym),
                  (SYMBOL_CLASS (sym) == LOC_TYPEDEF
-                  ? "" : SYMBOL_PRINT_NAME (sym)),
-                 gdb_stdout, 0);
+                  ? "" : sym->print_name ()),
+                 &tmp_stream, 0);
 
 
-      printf_filtered (";\n");
+      str += tmp_stream.string ();
+      str += ";";
     }
   /* Printing of modules is currently done here, maybe at some future
      point we might want a language specific method to print the module
      symbol so that we can customise the output more.  */
   else if (kind == MODULES_DOMAIN)
     }
   /* Printing of modules is currently done here, maybe at some future
      point we might want a language specific method to print the module
      symbol so that we can customise the output more.  */
   else if (kind == MODULES_DOMAIN)
-    printf_filtered ("%s\n", SYMBOL_PRINT_NAME (sym));
+    str += sym->print_name ();
+
+  return str;
+}
+
+/* Helper function for symbol info commands, for example 'info functions',
+   'info variables', etc.  KIND is the kind of symbol we searched for, and
+   BLOCK is the type of block the symbols was found in, either GLOBAL_BLOCK
+   or STATIC_BLOCK.  SYM is the symbol we found.  If LAST is not NULL,
+   print file and line number information for the symbol as well.  Skip
+   printing the filename if it matches LAST.  */
+
+static void
+print_symbol_info (enum search_domain kind,
+                  struct symbol *sym,
+                  int block, const char *last)
+{
+  scoped_switch_to_sym_language_if_auto l (sym);
+  struct symtab *s = symbol_symtab (sym);
+
+  if (last != NULL)
+    {
+      const char *s_filename = symtab_to_filename_for_display (s);
+
+      if (filename_cmp (last, s_filename) != 0)
+       {
+         printf_filtered (_("\nFile %ps:\n"),
+                          styled_string (file_name_style.style (),
+                                         s_filename));
+       }
+
+      if (SYMBOL_LINE (sym) != 0)
+       printf_filtered ("%d:\t", SYMBOL_LINE (sym));
+      else
+       puts_filtered ("\t");
+    }
+
+  std::string str = symbol_to_info_string (sym, block, kind);
+  printf_filtered ("%s\n", str.c_str ());
 }
 
 /* This help function for symtab_symbol_info() prints information
 }
 
 /* This help function for symtab_symbol_info() prints information
@@ -4804,7 +4914,7 @@ print_symbol_info (enum search_domain kind,
 static void
 print_msymbol_info (struct bound_minimal_symbol msymbol)
 {
 static void
 print_msymbol_info (struct bound_minimal_symbol msymbol)
 {
-  struct gdbarch *gdbarch = get_objfile_arch (msymbol.objfile);
+  struct gdbarch *gdbarch = msymbol.objfile->arch ();
   char *tmp;
 
   if (gdbarch_addr_bit (gdbarch) <= 32)
   char *tmp;
 
   if (gdbarch_addr_bit (gdbarch) <= 32)
@@ -4821,8 +4931,7 @@ print_msymbol_info (struct bound_minimal_symbol msymbol)
 
   printf_filtered (_("%ps  %ps\n"),
                   styled_string (address_style.style (), tmp),
 
   printf_filtered (_("%ps  %ps\n"),
                   styled_string (address_style.style (), tmp),
-                  styled_string (sym_style,
-                                 MSYMBOL_PRINT_NAME (msymbol.minsym)));
+                  styled_string (sym_style, msymbol.minsym->print_name ()));
 }
 
 /* This is the guts of the commands "info functions", "info types", and
 }
 
 /* This is the guts of the commands "info functions", "info types", and
@@ -4845,10 +4954,10 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
   if (regexp != nullptr && *regexp == '\0')
     regexp = nullptr;
 
   if (regexp != nullptr && *regexp == '\0')
     regexp = nullptr;
 
-  /* Must make sure that if we're interrupted, symbols gets freed.  */
-  std::vector<symbol_search> symbols = search_symbols (regexp, kind,
-                                                      t_regexp, 0, NULL,
-                                                      exclude_minsyms);
+  global_symbol_searcher spec (kind, regexp);
+  spec.set_symbol_type_regexp (t_regexp);
+  spec.set_exclude_minsyms (exclude_minsyms);
+  std::vector<symbol_search> symbols = spec.search ();
 
   if (!quiet)
     {
 
   if (!quiet)
     {
@@ -4905,13 +5014,13 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
    and 'info functions' commands.  These correspond to the -q, -t, and -n
    options.  */
 
    and 'info functions' commands.  These correspond to the -q, -t, and -n
    options.  */
 
-struct info_print_options
+struct info_vars_funcs_options
 {
   bool quiet = false;
   bool exclude_minsyms = false;
   char *type_regexp = nullptr;
 
 {
   bool quiet = false;
   bool exclude_minsyms = false;
   char *type_regexp = nullptr;
 
-  ~info_print_options ()
+  ~info_vars_funcs_options ()
   {
     xfree (type_regexp);
   }
   {
     xfree (type_regexp);
   }
@@ -4920,24 +5029,25 @@ struct info_print_options
 /* The options used by the 'info variables' and 'info functions'
    commands.  */
 
 /* The options used by the 'info variables' and 'info functions'
    commands.  */
 
-static const gdb::option::option_def info_print_options_defs[] = {
-  gdb::option::boolean_option_def<info_print_options> {
+static const gdb::option::option_def info_vars_funcs_options_defs[] = {
+  gdb::option::boolean_option_def<info_vars_funcs_options> {
     "q",
     "q",
-    [] (info_print_options *opt) { return &opt->quiet; },
+    [] (info_vars_funcs_options *opt) { return &opt->quiet; },
     nullptr, /* show_cmd_cb */
     nullptr /* set_doc */
   },
 
     nullptr, /* show_cmd_cb */
     nullptr /* set_doc */
   },
 
-  gdb::option::boolean_option_def<info_print_options> {
+  gdb::option::boolean_option_def<info_vars_funcs_options> {
     "n",
     "n",
-    [] (info_print_options *opt) { return &opt->exclude_minsyms; },
+    [] (info_vars_funcs_options *opt) { return &opt->exclude_minsyms; },
     nullptr, /* show_cmd_cb */
     nullptr /* set_doc */
   },
 
     nullptr, /* show_cmd_cb */
     nullptr /* set_doc */
   },
 
-  gdb::option::string_option_def<info_print_options> {
+  gdb::option::string_option_def<info_vars_funcs_options> {
     "t",
     "t",
-    [] (info_print_options *opt) { return &opt->type_regexp; },
+    [] (info_vars_funcs_options *opt) { return &opt->type_regexp;
+  },
     nullptr, /* show_cmd_cb */
     nullptr /* set_doc */
   }
     nullptr, /* show_cmd_cb */
     nullptr /* set_doc */
   }
@@ -4947,20 +5057,20 @@ static const gdb::option::option_def info_print_options_defs[] = {
    functions'.  */
 
 static gdb::option::option_def_group
    functions'.  */
 
 static gdb::option::option_def_group
-make_info_print_options_def_group (info_print_options *opts)
+make_info_vars_funcs_options_def_group (info_vars_funcs_options *opts)
 {
 {
-  return {{info_print_options_defs}, opts};
+  return {{info_vars_funcs_options_defs}, opts};
 }
 
 /* Command completer for 'info variables' and 'info functions'.  */
 
 static void
 }
 
 /* Command completer for 'info variables' and 'info functions'.  */
 
 static void
-info_print_command_completer (struct cmd_list_element *ignore,
-                             completion_tracker &tracker,
-                             const char *text, const char * /* word */)
+info_vars_funcs_command_completer (struct cmd_list_element *ignore,
+                                  completion_tracker &tracker,
+                                  const char *text, const char * /* word */)
 {
   const auto group
 {
   const auto group
-    = make_info_print_options_def_group (nullptr);
+    = make_info_vars_funcs_options_def_group (nullptr);
   if (gdb::option::complete_options
       (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
     return;
   if (gdb::option::complete_options
       (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
     return;
@@ -4974,8 +5084,8 @@ info_print_command_completer (struct cmd_list_element *ignore,
 static void
 info_variables_command (const char *args, int from_tty)
 {
 static void
 info_variables_command (const char *args, int from_tty)
 {
-  info_print_options opts;
-  auto grp = make_info_print_options_def_group (&opts);
+  info_vars_funcs_options opts;
+  auto grp = make_info_vars_funcs_options_def_group (&opts);
   gdb::option::process_options
     (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
   if (args != nullptr && *args == '\0')
   gdb::option::process_options
     (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
   if (args != nullptr && *args == '\0')
@@ -4990,8 +5100,9 @@ info_variables_command (const char *args, int from_tty)
 static void
 info_functions_command (const char *args, int from_tty)
 {
 static void
 info_functions_command (const char *args, int from_tty)
 {
-  info_print_options opts;
-  auto grp = make_info_print_options_def_group (&opts);
+  info_vars_funcs_options opts;
+
+  auto grp = make_info_vars_funcs_options_def_group (&opts);
   gdb::option::process_options
     (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
   if (args != nullptr && *args == '\0')
   gdb::option::process_options
     (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
   if (args != nullptr && *args == '\0')
@@ -5075,23 +5186,13 @@ info_modules_command (const char *args, int from_tty)
                      from_tty);
 }
 
                      from_tty);
 }
 
-/* Breakpoint all functions matching regular expression.  */
-
-void
-rbreak_command_wrapper (char *regexp, int from_tty)
-{
-  rbreak_command (regexp, from_tty);
-}
-
 static void
 rbreak_command (const char *regexp, int from_tty)
 {
   std::string string;
 static void
 rbreak_command (const char *regexp, int from_tty)
 {
   std::string string;
-  const char **files = NULL;
-  const char *file_name;
-  int nfiles = 0;
+  const char *file_name = nullptr;
 
 
-  if (regexp)
+  if (regexp != nullptr)
     {
       const char *colon = strchr (regexp, ':');
 
     {
       const char *colon = strchr (regexp, ':');
 
@@ -5107,17 +5208,14 @@ rbreak_command (const char *regexp, int from_tty)
          while (isspace (local_name[colon_index]))
            local_name[colon_index--] = 0;
          file_name = local_name;
          while (isspace (local_name[colon_index]))
            local_name[colon_index--] = 0;
          file_name = local_name;
-         files = &file_name;
-         nfiles = 1;
          regexp = skip_spaces (colon + 1);
        }
     }
 
          regexp = skip_spaces (colon + 1);
        }
     }
 
-  std::vector<symbol_search> symbols = search_symbols (regexp,
-                                                      FUNCTIONS_DOMAIN,
-                                                      NULL,
-                                                      nfiles, files,
-                                                      false);
+  global_symbol_searcher spec (FUNCTIONS_DOMAIN, regexp);
+  if (file_name != nullptr)
+    spec.filenames.push_back (file_name);
+  std::vector<symbol_search> symbols = spec.search ();
 
   scoped_rbreak_breakpoints finalize;
   for (const symbol_search &p : symbols)
 
   scoped_rbreak_breakpoints finalize;
   for (const symbol_search &p : symbols)
@@ -5128,18 +5226,18 @@ rbreak_command (const char *regexp, int from_tty)
          const char *fullname = symtab_to_fullname (symtab);
 
          string = string_printf ("%s:'%s'", fullname,
          const char *fullname = symtab_to_fullname (symtab);
 
          string = string_printf ("%s:'%s'", fullname,
-                                 SYMBOL_LINKAGE_NAME (p.symbol));
+                                 p.symbol->linkage_name ());
          break_command (&string[0], from_tty);
          print_symbol_info (FUNCTIONS_DOMAIN, p.symbol, p.block, NULL);
        }
       else
        {
          string = string_printf ("'%s'",
          break_command (&string[0], from_tty);
          print_symbol_info (FUNCTIONS_DOMAIN, p.symbol, p.block, NULL);
        }
       else
        {
          string = string_printf ("'%s'",
-                                 MSYMBOL_LINKAGE_NAME (p.msymbol.minsym));
+                                 p.msymbol.minsym->linkage_name ());
 
          break_command (&string[0], from_tty);
          printf_filtered ("<function, no debug info> %s;\n",
 
          break_command (&string[0], from_tty);
          printf_filtered ("<function, no debug info> %s;\n",
-                          MSYMBOL_PRINT_NAME (p.msymbol.minsym));
+                          p.msymbol.minsym->print_name ());
        }
     }
 }
        }
     }
 }
@@ -5162,7 +5260,7 @@ compare_symbol_name (const char *symbol_name, language symbol_language,
 
 /*  See symtab.h.  */
 
 
 /*  See symtab.h.  */
 
-void
+bool
 completion_list_add_name (completion_tracker &tracker,
                          language symbol_language,
                          const char *symname,
 completion_list_add_name (completion_tracker &tracker,
                          language symbol_language,
                          const char *symname,
@@ -5174,7 +5272,7 @@ completion_list_add_name (completion_tracker &tracker,
 
   /* Clip symbols that cannot match.  */
   if (!compare_symbol_name (symname, symbol_language, lookup_name, match_res))
 
   /* Clip symbols that cannot match.  */
   if (!compare_symbol_name (symname, symbol_language, lookup_name, match_res))
-    return;
+    return false;
 
   /* Refresh SYMNAME from the match string.  It's potentially
      different depending on language.  (E.g., on Ada, the match may be
 
   /* Refresh SYMNAME from the match string.  It's potentially
      different depending on language.  (E.g., on Ada, the match may be
@@ -5198,6 +5296,8 @@ completion_list_add_name (completion_tracker &tracker,
     tracker.add_completion (std::move (completion),
                            &match_res.match_for_lcd, text, word);
   }
     tracker.add_completion (std::move (completion),
                            &match_res.match_for_lcd, text, word);
   }
+
+  return true;
 }
 
 /* completion_list_add_name wrapper for struct symbol.  */
 }
 
 /* completion_list_add_name wrapper for struct symbol.  */
@@ -5208,9 +5308,31 @@ completion_list_add_symbol (completion_tracker &tracker,
                            const lookup_name_info &lookup_name,
                            const char *text, const char *word)
 {
                            const lookup_name_info &lookup_name,
                            const char *text, const char *word)
 {
-  completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
-                           SYMBOL_NATURAL_NAME (sym),
-                           lookup_name, text, word);
+  if (!completion_list_add_name (tracker, sym->language (),
+                                sym->natural_name (),
+                                lookup_name, text, word))
+    return;
+
+  /* C++ function symbols include the parameters within both the msymbol
+     name and the symbol name.  The problem is that the msymbol name will
+     describe the parameters in the most basic way, with typedefs stripped
+     out, while the symbol name will represent the types as they appear in
+     the program.  This means we will see duplicate entries in the
+     completion tracker.  The following converts the symbol name back to
+     the msymbol name and removes the msymbol name from the completion
+     tracker.  */
+  if (sym->language () == language_cplus
+      && SYMBOL_DOMAIN (sym) == VAR_DOMAIN
+      && SYMBOL_CLASS (sym) == LOC_BLOCK)
+    {
+      /* The call to canonicalize returns the empty string if the input
+        string is already in canonical form, thanks to this we don't
+        remove the symbol we just added above.  */
+      gdb::unique_xmalloc_ptr<char> str
+       = cp_canonicalize_string_no_typedefs (sym->natural_name ());
+      if (str != nullptr)
+       tracker.remove_completion (str.get ());
+    }
 }
 
 /* completion_list_add_name wrapper for struct minimal_symbol.  */
 }
 
 /* completion_list_add_name wrapper for struct minimal_symbol.  */
@@ -5221,8 +5343,8 @@ completion_list_add_msymbol (completion_tracker &tracker,
                             const lookup_name_info &lookup_name,
                             const char *text, const char *word)
 {
                             const lookup_name_info &lookup_name,
                             const char *text, const char *word)
 {
-  completion_list_add_name (tracker, MSYMBOL_LANGUAGE (sym),
-                           MSYMBOL_NATURAL_NAME (sym),
+  completion_list_add_name (tracker, sym->language (),
+                           sym->natural_name (),
                            lookup_name, text, word);
 }
 
                            lookup_name, text, word);
 }
 
@@ -5242,7 +5364,7 @@ completion_list_objc_symbol (completion_tracker &tracker,
   const char *method, *category, *selector;
   char *tmp2 = NULL;
 
   const char *method, *category, *selector;
   char *tmp2 = NULL;
 
-  method = MSYMBOL_NATURAL_NAME (msymbol);
+  method = msymbol->natural_name ();
 
   /* Is it a method?  */
   if ((method[0] != '-') && (method[0] != '+'))
 
   /* Is it a method?  */
   if ((method[0] != '-') && (method[0] != '+'))
@@ -5349,13 +5471,13 @@ completion_list_add_fields (completion_tracker &tracker,
   if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
     {
       struct type *t = SYMBOL_TYPE (sym);
   if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
     {
       struct type *t = SYMBOL_TYPE (sym);
-      enum type_code c = TYPE_CODE (t);
+      enum type_code c = t->code ();
       int j;
 
       if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
       int j;
 
       if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
-       for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
+       for (j = TYPE_N_BASECLASSES (t); j < t->num_fields (); j++)
          if (TYPE_FIELD_NAME (t, j))
          if (TYPE_FIELD_NAME (t, j))
-           completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
+           completion_list_add_name (tracker, sym->language (),
                                      TYPE_FIELD_NAME (t, j),
                                      lookup_name, text, word);
     }
                                      TYPE_FIELD_NAME (t, j),
                                      lookup_name, text, word);
     }
@@ -5366,7 +5488,7 @@ completion_list_add_fields (completion_tracker &tracker,
 bool
 symbol_is_function_or_method (symbol *sym)
 {
 bool
 symbol_is_function_or_method (symbol *sym)
 {
-  switch (TYPE_CODE (SYMBOL_TYPE (sym)))
+  switch (SYMBOL_TYPE (sym)->code ())
     {
     case TYPE_CODE_FUNC:
     case TYPE_CODE_METHOD:
     {
     case TYPE_CODE_FUNC:
     case TYPE_CODE_METHOD:
@@ -5401,7 +5523,7 @@ find_gnu_ifunc (const symbol *sym)
   if (SYMBOL_CLASS (sym) != LOC_BLOCK)
     return {};
 
   if (SYMBOL_CLASS (sym) != LOC_BLOCK)
     return {};
 
-  lookup_name_info lookup_name (SYMBOL_SEARCH_NAME (sym),
+  lookup_name_info lookup_name (sym->search_name (),
                                symbol_name_match_type::SEARCH_NAME);
   struct objfile *objfile = symbol_objfile (sym);
 
                                symbol_name_match_type::SEARCH_NAME);
   struct objfile *objfile = symbol_objfile (sym);
 
@@ -5417,7 +5539,7 @@ find_gnu_ifunc (const symbol *sym)
          CORE_ADDR msym_addr = MSYMBOL_VALUE_ADDRESS (objfile, minsym);
          if (MSYMBOL_TYPE (minsym) == mst_data_gnu_ifunc)
            {
          CORE_ADDR msym_addr = MSYMBOL_VALUE_ADDRESS (objfile, minsym);
          if (MSYMBOL_TYPE (minsym) == mst_data_gnu_ifunc)
            {
-             struct gdbarch *gdbarch = get_objfile_arch (objfile);
+             struct gdbarch *gdbarch = objfile->arch ();
              msym_addr
                = gdbarch_convert_from_func_ptr_addr (gdbarch,
                                                      msym_addr,
              msym_addr
                = gdbarch_convert_from_func_ptr_addr (gdbarch,
                                                      msym_addr,
@@ -5466,7 +5588,7 @@ add_symtab_completions (struct compunit_symtab *cust,
 
          if (code == TYPE_CODE_UNDEF
              || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
 
          if (code == TYPE_CODE_UNDEF
              || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
-                 && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
+                 && SYMBOL_TYPE (sym)->code () == code))
            completion_list_add_symbol (tracker, sym,
                                        lookup_name,
                                        text, word);
            completion_list_add_symbol (tracker, sym,
                                        lookup_name,
                                        text, word);
@@ -5617,7 +5739,7 @@ default_collect_symbol_completion_matches_break_on
                                            sym_text, word);
              }
            else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
                                            sym_text, word);
              }
            else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
-                    && TYPE_CODE (SYMBOL_TYPE (sym)) == code)
+                    && SYMBOL_TYPE (sym)->code () == code)
              completion_list_add_symbol (tracker, sym, lookup_name,
                                          sym_text, word);
          }
              completion_list_add_symbol (tracker, sym, lookup_name,
                                          sym_text, word);
          }
@@ -6038,6 +6160,16 @@ find_main_name (void)
 
   /* The languages above didn't identify the name of the main procedure.
      Fallback to "main".  */
 
   /* The languages above didn't identify the name of the main procedure.
      Fallback to "main".  */
+
+  /* Try to find language for main in psymtabs.  */
+  enum language lang
+    = find_quick_global_symbol_language ("main", VAR_DOMAIN);
+  if (lang != language_unknown)
+    {
+      set_main_name ("main", lang);
+      return;
+    }
+
   set_main_name ("main", language_unknown);
 }
 
   set_main_name ("main", language_unknown);
 }
 
@@ -6210,53 +6342,6 @@ initialize_ordinary_address_classes (void)
 
 \f
 
 
 \f
 
-/* Helper function to initialize the fields of an objfile-owned symbol.
-   It assumed that *SYM is already all zeroes.  */
-
-static void
-initialize_objfile_symbol_1 (struct symbol *sym)
-{
-  SYMBOL_OBJFILE_OWNED (sym) = 1;
-  SYMBOL_SECTION (sym) = -1;
-}
-
-/* Initialize the symbol SYM, and mark it as being owned by an objfile.  */
-
-void
-initialize_objfile_symbol (struct symbol *sym)
-{
-  memset (sym, 0, sizeof (*sym));
-  initialize_objfile_symbol_1 (sym);
-}
-
-/* Allocate and initialize a new 'struct symbol' on OBJFILE's
-   obstack.  */
-
-struct symbol *
-allocate_symbol (struct objfile *objfile)
-{
-  struct symbol *result;
-
-  result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol);
-  initialize_objfile_symbol_1 (result);
-
-  return result;
-}
-
-/* Allocate and initialize a new 'struct template_symbol' on OBJFILE's
-   obstack.  */
-
-struct template_symbol *
-allocate_template_symbol (struct objfile *objfile)
-{
-  struct template_symbol *result;
-
-  result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct template_symbol);
-  initialize_objfile_symbol_1 (result);
-
-  return result;
-}
-
 /* See symtab.h.  */
 
 struct objfile *
 /* See symtab.h.  */
 
 struct objfile *
@@ -6273,7 +6358,7 @@ symbol_arch (const struct symbol *symbol)
 {
   if (!SYMBOL_OBJFILE_OWNED (symbol))
     return symbol->owner.arch;
 {
   if (!SYMBOL_OBJFILE_OWNED (symbol))
     return symbol->owner.arch;
-  return get_objfile_arch (SYMTAB_OBJFILE (symbol->owner.symtab));
+  return SYMTAB_OBJFILE (symbol->owner.symtab)->arch ();
 }
 
 /* See symtab.h.  */
 }
 
 /* See symtab.h.  */
@@ -6302,16 +6387,19 @@ get_symbol_address (const struct symbol *sym)
   gdb_assert (sym->maybe_copied);
   gdb_assert (SYMBOL_CLASS (sym) == LOC_STATIC);
 
   gdb_assert (sym->maybe_copied);
   gdb_assert (SYMBOL_CLASS (sym) == LOC_STATIC);
 
-  const char *linkage_name = SYMBOL_LINKAGE_NAME (sym);
+  const char *linkage_name = sym->linkage_name ();
 
   for (objfile *objfile : current_program_space->objfiles ())
     {
 
   for (objfile *objfile : current_program_space->objfiles ())
     {
+      if (objfile->separate_debug_objfile_backlink != nullptr)
+       continue;
+
       bound_minimal_symbol minsym
        = lookup_minimal_symbol_linkage (linkage_name, objfile);
       if (minsym.minsym != nullptr)
        return BMSYMBOL_VALUE_ADDRESS (minsym);
     }
       bound_minimal_symbol minsym
        = lookup_minimal_symbol_linkage (linkage_name, objfile);
       if (minsym.minsym != nullptr)
        return BMSYMBOL_VALUE_ADDRESS (minsym);
     }
-  return sym->ginfo.value.address;
+  return sym->value.address;
 }
 
 /* See symtab.h.  */
 }
 
 /* See symtab.h.  */
@@ -6322,11 +6410,12 @@ get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym)
   gdb_assert (minsym->maybe_copied);
   gdb_assert ((objf->flags & OBJF_MAINLINE) == 0);
 
   gdb_assert (minsym->maybe_copied);
   gdb_assert ((objf->flags & OBJF_MAINLINE) == 0);
 
-  const char *linkage_name = MSYMBOL_LINKAGE_NAME (minsym);
+  const char *linkage_name = minsym->linkage_name ();
 
   for (objfile *objfile : current_program_space->objfiles ())
     {
 
   for (objfile *objfile : current_program_space->objfiles ())
     {
-      if ((objfile->flags & OBJF_MAINLINE) != 0)
+      if (objfile->separate_debug_objfile_backlink == nullptr
+         && (objfile->flags & OBJF_MAINLINE) != 0)
        {
          bound_minimal_symbol found
            = lookup_minimal_symbol_linkage (linkage_name, objfile);
        {
          bound_minimal_symbol found
            = lookup_minimal_symbol_linkage (linkage_name, objfile);
@@ -6334,14 +6423,313 @@ get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym)
            return BMSYMBOL_VALUE_ADDRESS (found);
        }
     }
            return BMSYMBOL_VALUE_ADDRESS (found);
        }
     }
-  return (minsym->value.address
-         + ANOFFSET (objf->section_offsets, minsym->section));
+  return minsym->value.address + objf->section_offsets[minsym->section];
 }
 
 \f
 
 }
 
 \f
 
+/* Hold the sub-commands of 'info module'.  */
+
+static struct cmd_list_element *info_module_cmdlist = NULL;
+
+/* See symtab.h.  */
+
+std::vector<module_symbol_search>
+search_module_symbols (const char *module_regexp, const char *regexp,
+                      const char *type_regexp, search_domain kind)
+{
+  std::vector<module_symbol_search> results;
+
+  /* Search for all modules matching MODULE_REGEXP.  */
+  global_symbol_searcher spec1 (MODULES_DOMAIN, module_regexp);
+  spec1.set_exclude_minsyms (true);
+  std::vector<symbol_search> modules = spec1.search ();
+
+  /* Now search for all symbols of the required KIND matching the required
+     regular expressions.  We figure out which ones are in which modules
+     below.  */
+  global_symbol_searcher spec2 (kind, regexp);
+  spec2.set_symbol_type_regexp (type_regexp);
+  spec2.set_exclude_minsyms (true);
+  std::vector<symbol_search> symbols = spec2.search ();
+
+  /* Now iterate over all MODULES, checking to see which items from
+     SYMBOLS are in each module.  */
+  for (const symbol_search &p : modules)
+    {
+      QUIT;
+
+      /* This is a module.  */
+      gdb_assert (p.symbol != nullptr);
+
+      std::string prefix = p.symbol->print_name ();
+      prefix += "::";
+
+      for (const symbol_search &q : symbols)
+       {
+         if (q.symbol == nullptr)
+           continue;
+
+         if (strncmp (q.symbol->print_name (), prefix.c_str (),
+                      prefix.size ()) != 0)
+           continue;
+
+         results.push_back ({p, q});
+       }
+    }
+
+  return results;
+}
+
+/* Implement the core of both 'info module functions' and 'info module
+   variables'.  */
+
+static void
+info_module_subcommand (bool quiet, const char *module_regexp,
+                       const char *regexp, const char *type_regexp,
+                       search_domain kind)
+{
+  /* Print a header line.  Don't build the header line bit by bit as this
+     prevents internationalisation.  */
+  if (!quiet)
+    {
+      if (module_regexp == nullptr)
+       {
+         if (type_regexp == nullptr)
+           {
+             if (regexp == nullptr)
+               printf_filtered ((kind == VARIABLES_DOMAIN
+                                 ? _("All variables in all modules:")
+                                 : _("All functions in all modules:")));
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression"
+                       " \"%s\" in all modules:")
+                   : _("All functions matching regular expression"
+                       " \"%s\" in all modules:")),
+                  regexp);
+           }
+         else
+           {
+             if (regexp == nullptr)
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables with type matching regular "
+                       "expression \"%s\" in all modules:")
+                   : _("All functions with type matching regular "
+                       "expression \"%s\" in all modules:")),
+                  type_regexp);
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression "
+                       "\"%s\",\n\twith type matching regular "
+                       "expression \"%s\" in all modules:")
+                   : _("All functions matching regular expression "
+                       "\"%s\",\n\twith type matching regular "
+                       "expression \"%s\" in all modules:")),
+                  regexp, type_regexp);
+           }
+       }
+      else
+       {
+         if (type_regexp == nullptr)
+           {
+             if (regexp == nullptr)
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables in all modules matching regular "
+                       "expression \"%s\":")
+                   : _("All functions in all modules matching regular "
+                       "expression \"%s\":")),
+                  module_regexp);
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")
+                   : _("All functions matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")),
+                  regexp, module_regexp);
+           }
+         else
+           {
+             if (regexp == nullptr)
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables with type matching regular "
+                       "expression \"%s\"\n\tin all modules matching "
+                       "regular expression \"%s\":")
+                   : _("All functions with type matching regular "
+                       "expression \"%s\"\n\tin all modules matching "
+                       "regular expression \"%s\":")),
+                  type_regexp, module_regexp);
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression "
+                       "\"%s\",\n\twith type matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")
+                   : _("All functions matching regular expression "
+                       "\"%s\",\n\twith type matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")),
+                  regexp, type_regexp, module_regexp);
+           }
+       }
+      printf_filtered ("\n");
+    }
+
+  /* Find all symbols of type KIND matching the given regular expressions
+     along with the symbols for the modules in which those symbols
+     reside.  */
+  std::vector<module_symbol_search> module_symbols
+    = search_module_symbols (module_regexp, regexp, type_regexp, kind);
+
+  std::sort (module_symbols.begin (), module_symbols.end (),
+            [] (const module_symbol_search &a, const module_symbol_search &b)
+            {
+              if (a.first < b.first)
+                return true;
+              else if (a.first == b.first)
+                return a.second < b.second;
+              else
+                return false;
+            });
+
+  const char *last_filename = "";
+  const symbol *last_module_symbol = nullptr;
+  for (const module_symbol_search &ms : module_symbols)
+    {
+      const symbol_search &p = ms.first;
+      const symbol_search &q = ms.second;
+
+      gdb_assert (q.symbol != nullptr);
+
+      if (last_module_symbol != p.symbol)
+       {
+         printf_filtered ("\n");
+         printf_filtered (_("Module \"%s\":\n"), p.symbol->print_name ());
+         last_module_symbol = p.symbol;
+         last_filename = "";
+       }
+
+      print_symbol_info (FUNCTIONS_DOMAIN, q.symbol, q.block,
+                        last_filename);
+      last_filename
+       = symtab_to_filename_for_display (symbol_symtab (q.symbol));
+    }
+}
+
+/* Hold the option values for the 'info module .....' sub-commands.  */
+
+struct info_modules_var_func_options
+{
+  bool quiet = false;
+  char *type_regexp = nullptr;
+  char *module_regexp = nullptr;
+
+  ~info_modules_var_func_options ()
+  {
+    xfree (type_regexp);
+    xfree (module_regexp);
+  }
+};
+
+/* The options used by 'info module variables' and 'info module functions'
+   commands.  */
+
+static const gdb::option::option_def info_modules_var_func_options_defs [] = {
+  gdb::option::boolean_option_def<info_modules_var_func_options> {
+    "q",
+    [] (info_modules_var_func_options *opt) { return &opt->quiet; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  },
+
+  gdb::option::string_option_def<info_modules_var_func_options> {
+    "t",
+    [] (info_modules_var_func_options *opt) { return &opt->type_regexp; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  },
+
+  gdb::option::string_option_def<info_modules_var_func_options> {
+    "m",
+    [] (info_modules_var_func_options *opt) { return &opt->module_regexp; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  }
+};
+
+/* Return the option group used by the 'info module ...' sub-commands.  */
+
+static inline gdb::option::option_def_group
+make_info_modules_var_func_options_def_group
+       (info_modules_var_func_options *opts)
+{
+  return {{info_modules_var_func_options_defs}, opts};
+}
+
+/* Implements the 'info module functions' command.  */
+
+static void
+info_module_functions_command (const char *args, int from_tty)
+{
+  info_modules_var_func_options opts;
+  auto grp = make_info_modules_var_func_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
+
+  info_module_subcommand (opts.quiet, opts.module_regexp, args,
+                         opts.type_regexp, FUNCTIONS_DOMAIN);
+}
+
+/* Implements the 'info module variables' command.  */
+
+static void
+info_module_variables_command (const char *args, int from_tty)
+{
+  info_modules_var_func_options opts;
+  auto grp = make_info_modules_var_func_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
+
+  info_module_subcommand (opts.quiet, opts.module_regexp, args,
+                         opts.type_regexp, VARIABLES_DOMAIN);
+}
+
+/* Command completer for 'info module ...' sub-commands.  */
+
+static void
+info_module_var_func_command_completer (struct cmd_list_element *ignore,
+                                       completion_tracker &tracker,
+                                       const char *text,
+                                       const char * /* word */)
+{
+
+  const auto group = make_info_modules_var_func_options_def_group (nullptr);
+  if (gdb::option::complete_options
+      (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
+    return;
+
+  const char *word = advance_to_expression_complete_word_point (tracker, text);
+  symbol_completer (ignore, tracker, text, word);
+}
+
+\f
+
+void _initialize_symtab ();
 void
 void
-_initialize_symtab (void)
+_initialize_symtab ()
 {
   cmd_list_element *c;
 
 {
   cmd_list_element *c;
 
@@ -6354,7 +6742,7 @@ Usage: info variables [-q] [-n] [-t TYPEREGEXP] [NAMEREGEXP]\n\
 Prints the global and static variables.\n"),
                                      _("global and static variables"),
                                      true));
 Prints the global and static variables.\n"),
                                      _("global and static variables"),
                                      true));
-  set_cmd_completer_handle_brkchars (c, info_print_command_completer);
+  set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer);
   if (dbx_commands)
     {
       c = add_com ("whereis", class_info, info_variables_command,
   if (dbx_commands)
     {
       c = add_com ("whereis", class_info, info_variables_command,
@@ -6364,7 +6752,7 @@ Usage: whereis [-q] [-n] [-t TYPEREGEXP] [NAMEREGEXP]\n\
 Prints the global and static variables.\n"),
                                         _("global and static variables"),
                                         true));
 Prints the global and static variables.\n"),
                                         _("global and static variables"),
                                         true));
-      set_cmd_completer_handle_brkchars (c, info_print_command_completer);
+      set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer);
     }
 
   c = add_info ("functions", info_functions_command,
     }
 
   c = add_info ("functions", info_functions_command,
@@ -6374,7 +6762,7 @@ Usage: info functions [-q] [-n] [-t TYPEREGEXP] [NAMEREGEXP]\n\
 Prints the functions.\n"),
                                      _("functions"),
                                      true));
 Prints the functions.\n"),
                                      _("functions"),
                                      true));
-  set_cmd_completer_handle_brkchars (c, info_print_command_completer);
+  set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer);
 
   c = add_info ("types", info_types_command, _("\
 All type names, or those matching REGEXP.\n\
 
   c = add_info ("types", info_types_command, _("\
 All type names, or those matching REGEXP.\n\
@@ -6402,6 +6790,45 @@ Options:\n\
                _("All module names, or those matching REGEXP."));
   set_cmd_completer_handle_brkchars (c, info_types_command_completer);
 
                _("All module names, or those matching REGEXP."));
   set_cmd_completer_handle_brkchars (c, info_types_command_completer);
 
+  add_basic_prefix_cmd ("module", class_info, _("\
+Print information about modules."),
+                       &info_module_cmdlist, "info module ",
+                       0, &infolist);
+
+  c = add_cmd ("functions", class_info, info_module_functions_command, _("\
+Display functions arranged by modules.\n\
+Usage: info module functions [-q] [-m MODREGEXP] [-t TYPEREGEXP] [REGEXP]\n\
+Print a summary of all functions within each Fortran module, grouped by\n\
+module and file.  For each function the line on which the function is\n\
+defined is given along with the type signature and name of the function.\n\
+\n\
+If REGEXP is provided then only functions whose name matches REGEXP are\n\
+listed.  If MODREGEXP is provided then only functions in modules matching\n\
+MODREGEXP are listed.  If TYPEREGEXP is given then only functions whose\n\
+type signature matches TYPEREGEXP are listed.\n\
+\n\
+The -q flag suppresses printing some header information."),
+              &info_module_cmdlist);
+  set_cmd_completer_handle_brkchars
+    (c, info_module_var_func_command_completer);
+
+  c = add_cmd ("variables", class_info, info_module_variables_command, _("\
+Display variables arranged by modules.\n\
+Usage: info module variables [-q] [-m MODREGEXP] [-t TYPEREGEXP] [REGEXP]\n\
+Print a summary of all variables within each Fortran module, grouped by\n\
+module and file.  For each variable the line on which the variable is\n\
+defined is given along with the type and name of the variable.\n\
+\n\
+If REGEXP is provided then only variables whose name matches REGEXP are\n\
+listed.  If MODREGEXP is provided then only variables in modules matching\n\
+MODREGEXP are listed.  If TYPEREGEXP is given then only variables whose\n\
+type matches TYPEREGEXP are listed.\n\
+\n\
+The -q flag suppresses printing some header information."),
+              &info_module_cmdlist);
+  set_cmd_completer_handle_brkchars
+    (c, info_module_var_func_command_completer);
+
   add_com ("rbreak", class_breakpoint, rbreak_command,
           _("Set a breakpoint for all functions matching REGEXP."));
 
   add_com ("rbreak", class_breakpoint, rbreak_command,
           _("Set a breakpoint for all functions matching REGEXP."));
 
This page took 0.060573 seconds and 4 git commands to generate.