Handle dereferencing Rust trait objects
[binutils-gdb.git] / gdb / psymtab.c
index f848990867235d201b5b62d7bc9e6d7a5c2afea9..c74ea21d6f4ca1104630a39990c909d900d0d4bc 100644 (file)
@@ -36,6 +36,7 @@
 #include "cp-support.h"
 #include "gdbcmd.h"
 #include <algorithm>
+#include <set>
 
 struct psymbol_bcache
 {
@@ -46,7 +47,7 @@ static struct partial_symbol *match_partial_symbol (struct objfile *,
                                                    struct partial_symtab *,
                                                    int,
                                                    const char *, domain_enum,
-                                                   symbol_compare_ftype *,
+                                                   symbol_name_match_type,
                                                    symbol_compare_ftype *);
 
 static struct partial_symbol *lookup_partial_symbol (struct objfile *,
@@ -510,6 +511,8 @@ psym_lookup_symbol (struct objfile *objfile,
   const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
   struct compunit_symtab *stab_best = NULL;
 
+  lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
+
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
   {
     if (!ps->readin && lookup_partial_symbol (objfile, ps, name,
@@ -532,10 +535,10 @@ psym_lookup_symbol (struct objfile *objfile,
           information (but NAME might contain it).  */
 
        if (sym != NULL
-           && SYMBOL_MATCHES_SEARCH_NAME (sym, name))
+           && SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
          return stab;
        if (with_opaque != NULL
-           && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, name))
+           && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, lookup_name))
          stab_best = stab;
 
        /* Keep looking through other psymtabs.  */
@@ -545,6 +548,18 @@ psym_lookup_symbol (struct objfile *objfile,
   return stab_best;
 }
 
+/* Returns true if PSYM matches LOOKUP_NAME.  */
+
+static bool
+psymbol_name_matches (partial_symbol *psym,
+                     const lookup_name_info &lookup_name)
+{
+  const language_defn *lang = language_def (SYMBOL_LANGUAGE (psym));
+  symbol_name_matcher_ftype *name_match
+    = language_get_symbol_name_matcher (lang, lookup_name);
+  return name_match (SYMBOL_SEARCH_NAME (psym), lookup_name, NULL);
+}
+
 /* Look in PST for a symbol in DOMAIN whose name matches NAME.  Search
    the global block of PST if GLOBAL, and otherwise the static block.
    MATCH is the comparison operation that returns true iff MATCH (s,
@@ -557,7 +572,7 @@ static struct partial_symbol *
 match_partial_symbol (struct objfile *objfile,
                      struct partial_symtab *pst, int global,
                      const char *name, domain_enum domain,
-                     symbol_compare_ftype *match,
+                     symbol_name_match_type match_type,
                      symbol_compare_ftype *ordered_compare)
 {
   struct partial_symbol **start, **psym;
@@ -566,7 +581,10 @@ match_partial_symbol (struct objfile *objfile,
   int do_linear_search = 1;
 
   if (length == 0)
-      return NULL;
+    return NULL;
+
+  lookup_name_info lookup_name (name, match_type);
+
   start = (global ?
           &objfile->global_psymbols[pst->globals_offset] :
           &objfile->static_psymbols[pst->statics_offset]);
@@ -588,7 +606,12 @@ match_partial_symbol (struct objfile *objfile,
        {
          center = bottom + (top - bottom) / 2;
          gdb_assert (center < top);
-         if (ordered_compare (SYMBOL_SEARCH_NAME (*center), name) >= 0)
+
+         enum language lang = SYMBOL_LANGUAGE (*center);
+         const char *lang_ln
+           = lookup_name.language_lookup_name (lang).c_str ();
+
+         if (ordered_compare (SYMBOL_SEARCH_NAME (*center), lang_ln) >= 0)
            top = center;
          else
            bottom = center + 1;
@@ -596,7 +619,7 @@ match_partial_symbol (struct objfile *objfile,
       gdb_assert (top == bottom);
 
       while (top <= real_top
-            && match (SYMBOL_SEARCH_NAME (*top), name) == 0)
+            && psymbol_name_matches (*top, lookup_name))
        {
          if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
                                     SYMBOL_DOMAIN (*top), domain))
@@ -614,7 +637,7 @@ match_partial_symbol (struct objfile *objfile,
        {
          if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
                                     SYMBOL_DOMAIN (*psym), domain)
-             && match (SYMBOL_SEARCH_NAME (*psym), name) == 0)
+             && psymbol_name_matches (*psym, lookup_name))
            return *psym;
        }
     }
@@ -669,6 +692,9 @@ lookup_partial_symbol (struct objfile *objfile,
     return NULL;
 
   gdb::unique_xmalloc_ptr<char> search_name = psymtab_search_name (name);
+
+  lookup_name_info lookup_name (search_name.get (), symbol_name_match_type::FULL);
+
   start = (global ?
           &objfile->global_psymbols[pst->globals_offset] :
           &objfile->static_psymbols[pst->statics_offset]);
@@ -708,15 +734,13 @@ lookup_partial_symbol (struct objfile *objfile,
 
       /* For `case_sensitivity == case_sensitive_off' strcmp_iw_ordered will
         search more exactly than what matches SYMBOL_MATCHES_SEARCH_NAME.  */
-      while (top >= start && SYMBOL_MATCHES_SEARCH_NAME (*top,
-                                                        search_name.get ()))
+      while (top >= start && SYMBOL_MATCHES_SEARCH_NAME (*top, lookup_name))
        top--;
 
       /* Fixup to have a symbol which matches SYMBOL_MATCHES_SEARCH_NAME.  */
       top++;
 
-      while (top <= real_top
-            && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name.get ()))
+      while (top <= real_top && SYMBOL_MATCHES_SEARCH_NAME (*top, lookup_name))
        {
          if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
                                     SYMBOL_DOMAIN (*top), domain))
@@ -734,7 +758,7 @@ lookup_partial_symbol (struct objfile *objfile,
        {
          if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
                                     SYMBOL_DOMAIN (*psym), domain)
-             && SYMBOL_MATCHES_SEARCH_NAME (*psym, search_name.get ()))
+             && SYMBOL_MATCHES_SEARCH_NAME (*psym, lookup_name))
            return *psym;
        }
     }
@@ -800,6 +824,8 @@ psym_relocate (struct objfile *objfile,
       if (SYMBOL_SECTION (psym) >= 0)
        SYMBOL_VALUE_ADDRESS (psym) += ANOFFSET (delta, SYMBOL_SECTION (psym));
     }
+
+  objfile->psymbol_map.clear ();
 }
 
 /* Psymtab version of find_last_source_symtab.  See its definition in
@@ -1213,13 +1239,16 @@ static int
 map_block (const char *name, domain_enum domain, struct objfile *objfile,
           struct block *block,
           int (*callback) (struct block *, struct symbol *, void *),
-          void *data, symbol_compare_ftype *match)
+          void *data, symbol_name_match_type match)
 {
   struct block_iterator iter;
   struct symbol *sym;
 
-  for (sym = block_iter_match_first (block, name, match, &iter);
-       sym != NULL; sym = block_iter_match_next (name, match, &iter))
+  lookup_name_info lookup_name (name, match);
+
+  for (sym = block_iter_match_first (block, lookup_name, &iter);
+       sym != NULL;
+       sym = block_iter_match_next (lookup_name, &iter))
     {
       if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
                                 SYMBOL_DOMAIN (sym), domain))
@@ -1242,7 +1271,7 @@ psym_map_matching_symbols (struct objfile *objfile,
                           int (*callback) (struct block *,
                                            struct symbol *, void *),
                           void *data,
-                          symbol_compare_ftype *match,
+                          symbol_name_match_type match,
                           symbol_compare_ftype *ordered_compare)
 {
   const int block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
@@ -1277,7 +1306,8 @@ psym_map_matching_symbols (struct objfile *objfile,
 
 static bool
 recursively_search_psymtabs
-  (struct partial_symtab *ps, struct objfile *objfile, enum search_domain kind,
+  (struct partial_symtab *ps, struct objfile *objfile, enum search_domain domain,
+   const lookup_name_info &lookup_name,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> sym_matcher)
 {
   int keep_going = 1;
@@ -1298,7 +1328,8 @@ recursively_search_psymtabs
        continue;
 
       r = recursively_search_psymtabs (ps->dependencies[i],
-                                      objfile, kind, sym_matcher);
+                                      objfile, domain, lookup_name,
+                                      sym_matcher);
       if (r != 0)
        {
          ps->searched_flag = PST_SEARCHED_AND_FOUND;
@@ -1332,15 +1363,16 @@ recursively_search_psymtabs
        {
          QUIT;
 
-         if ((kind == ALL_DOMAIN
-              || (kind == VARIABLES_DOMAIN
+         if ((domain == ALL_DOMAIN
+              || (domain == VARIABLES_DOMAIN
                   && PSYMBOL_CLASS (*psym) != LOC_TYPEDEF
                   && PSYMBOL_CLASS (*psym) != LOC_BLOCK)
-              || (kind == FUNCTIONS_DOMAIN
+              || (domain == FUNCTIONS_DOMAIN
                   && PSYMBOL_CLASS (*psym) == LOC_BLOCK)
-              || (kind == TYPES_DOMAIN
+              || (domain == TYPES_DOMAIN
                   && PSYMBOL_CLASS (*psym) == LOC_TYPEDEF))
-             && sym_matcher (SYMBOL_SEARCH_NAME (*psym)))
+             && psymbol_name_matches (*psym, lookup_name)
+             && (sym_matcher == NULL || sym_matcher (SYMBOL_SEARCH_NAME (*psym))))
            {
              /* Found a match, so notify our caller.  */
              result = PST_SEARCHED_AND_FOUND;
@@ -1361,12 +1393,15 @@ static void
 psym_expand_symtabs_matching
   (struct objfile *objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+   const lookup_name_info &lookup_name_in,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
-   enum search_domain kind)
+   enum search_domain domain)
 {
   struct partial_symtab *ps;
 
+  lookup_name_info lookup_name = lookup_name_in.make_ignore_params ();
+
   /* Clear the search flags.  */
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
     {
@@ -1405,7 +1440,8 @@ psym_expand_symtabs_matching
            continue;
        }
 
-      if (recursively_search_psymtabs (ps, objfile, kind, symbol_matcher))
+      if (recursively_search_psymtabs (ps, objfile, domain,
+                                      lookup_name, symbol_matcher))
        {
          struct compunit_symtab *symtab =
            psymtab_to_symtab (objfile, ps);
@@ -1425,6 +1461,84 @@ psym_has_symbols (struct objfile *objfile)
   return objfile->psymtabs != NULL;
 }
 
+/* Helper function for psym_find_compunit_symtab_by_address that fills
+   in psymbol_map for a given range of psymbols.  */
+
+static void
+psym_fill_psymbol_map (struct objfile *objfile,
+                      struct partial_symtab *psymtab,
+                      std::set<CORE_ADDR> *seen_addrs,
+                      const std::vector<partial_symbol *> &symbols,
+                      int start,
+                      int length)
+{
+  for (int i = 0; i < length; ++i)
+    {
+      struct partial_symbol *psym = symbols[start + i];
+
+      if (PSYMBOL_CLASS (psym) == LOC_STATIC)
+       {
+         CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (psym);
+         if (seen_addrs->find (addr) == seen_addrs->end ())
+           {
+             seen_addrs->insert (addr);
+             objfile->psymbol_map.emplace_back (addr, psymtab);
+           }
+       }
+    }
+}
+
+/* See find_compunit_symtab_by_address in quick_symbol_functions, in
+   symfile.h.  */
+
+static compunit_symtab *
+psym_find_compunit_symtab_by_address (struct objfile *objfile,
+                                     CORE_ADDR address)
+{
+  if (objfile->psymbol_map.empty ())
+    {
+      struct partial_symtab *pst;
+
+      std::set<CORE_ADDR> seen_addrs;
+
+      ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
+      {
+       psym_fill_psymbol_map (objfile, pst,
+                              &seen_addrs,
+                              objfile->global_psymbols,
+                              pst->globals_offset,
+                              pst->n_global_syms);
+       psym_fill_psymbol_map (objfile, pst,
+                              &seen_addrs,
+                              objfile->static_psymbols,
+                              pst->statics_offset,
+                              pst->n_static_syms);
+      }
+
+      objfile->psymbol_map.shrink_to_fit ();
+
+      std::sort (objfile->psymbol_map.begin (), objfile->psymbol_map.end (),
+                [] (const std::pair<CORE_ADDR, partial_symtab *> &a,
+                    const std::pair<CORE_ADDR, partial_symtab *> &b)
+                {
+                  return a.first < b.first;
+                });
+    }
+
+  auto iter = std::lower_bound
+    (objfile->psymbol_map.begin (), objfile->psymbol_map.end (), address,
+     [] (const std::pair<CORE_ADDR, partial_symtab *> &a,
+        CORE_ADDR b)
+     {
+       return a.first < b;
+     });
+
+  if (iter == objfile->psymbol_map.end () || iter->first != address)
+    return NULL;
+
+  return psymtab_to_symtab (objfile, iter->second);
+}
+
 const struct quick_symbol_functions psym_functions =
 {
   psym_has_symbols,
@@ -1441,6 +1555,7 @@ const struct quick_symbol_functions psym_functions =
   psym_map_matching_symbols,
   psym_expand_symtabs_matching,
   psym_find_pc_sect_compunit_symtab,
+  psym_find_compunit_symtab_by_address,
   psym_map_symbol_filenames
 };
 
@@ -1515,7 +1630,9 @@ psymbol_hash (const void *addr, int length)
   h = hash_continue (&lang, sizeof (unsigned int), h);
   h = hash_continue (&domain, sizeof (unsigned int), h);
   h = hash_continue (&theclass, sizeof (unsigned int), h);
-  h = hash_continue (psymbol->ginfo.name, strlen (psymbol->ginfo.name), h);
+  /* Note that psymbol names are interned via symbol_set_names, so
+     there's no need to hash the contents of the name here.  */
+  h = hash_continue (&psymbol->ginfo.name, sizeof (psymbol->ginfo.name), h);
 
   return h;
 }
@@ -1535,6 +1652,9 @@ psymbol_compare (const void *addr1, const void *addr2, int length)
          && sym1->ginfo.language == sym2->ginfo.language
           && PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)
           && PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2)
+         /* Note that psymbol names are interned via
+            symbol_set_names, so there's no need to compare the
+            contents of the name here.  */
           && sym1->ginfo.name == sym2->ginfo.name);
 }