gdb: Introduce global_symbol_searcher
authorAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 10 Oct 2019 09:48:01 +0000 (10:48 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 27 Nov 2019 12:01:47 +0000 (12:01 +0000)
Introduce a new class to wrap up the parameters needed for the
function search_symbols, which has now become a member function of
this new class.

The motivation is that search_symbols already takes a lot of
parameters, and a future commit is going to add even more.  This
commit hopefully makes collecting the state required for a search
easier.

As part of this conversion the list of filenames in which to search
has been converted to a std::vector.

There should be no user visible changes after this commit.

gdb/ChangeLog:

* python/python.c (gdbpy_rbreak): Convert to using
global_symbol_searcher.
* symtab.c (file_matches): Convert return type to bool, change
file list to std::vector, update header comment.
(search_symbols): Rename to...
(global_symbol_searcher::search): ...this and update now its
a member function of global_symbol_searcher.  Take account of the
changes to file_matches.
(symtab_symbol_info): Convert to using global_symbol_searcher.
(rbreak_command): Likewise.
(search_module_symbols): Likewise.
* symtab.h (enum symbol_search): Update comment.
(search_symbols): Remove declaration.
(class global_symbol_searcher): New class.

Change-Id: I488ab292a892d9e9e84775c632c5f198b6ad3710

gdb/ChangeLog
gdb/python/python.c
gdb/symtab.c
gdb/symtab.h

index 6c6c000f7b5ec1119be3a6c5edb5d4373b4cbec1..56536c459ee559d4abe37523a749ea7bf57af9e1 100644 (file)
@@ -1,3 +1,20 @@
+2019-11-27  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * python/python.c (gdbpy_rbreak): Convert to using
+       global_symbol_searcher.
+       * symtab.c (file_matches): Convert return type to bool, change
+       file list to std::vector, update header comment.
+       (search_symbols): Rename to...
+       (global_symbol_searcher::search): ...this and update now its
+       a member function of global_symbol_searcher.  Take account of the
+       changes to file_matches.
+       (symtab_symbol_info): Convert to using global_symbol_searcher.
+       (rbreak_command): Likewise.
+       (search_module_symbols): Likewise.
+       * symtab.h (enum symbol_search): Update comment.
+       (search_symbols): Remove declaration.
+       (class global_symbol_searcher): New class.
+
 2019-11-26  Tom Tromey  <tromey@adacore.com>
 
        * cp-support.c (_initialize_cp_support): Conditionally initialize
index 2f4fb0fe10d87069ab7e56efc9f321c2ee05da1d..fad54e9cdb0592550ce762ebc7cd2df2337ccf15 100644 (file)
@@ -644,19 +644,6 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
 static PyObject *
 gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
 {
-  /* A simple type to ensure clean up of a vector of allocated strings
-     when a C interface demands a const char *array[] type
-     interface.  */
-  struct symtab_list_type
-  {
-    ~symtab_list_type ()
-    {
-      for (const char *elem: vec)
-       xfree ((void *) elem);
-    }
-    std::vector<const char *> vec;
-  };
-
   char *regex = NULL;
   std::vector<symbol_search> symbols;
   unsigned long count = 0;
@@ -666,7 +653,6 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
   unsigned int throttle = 0;
   static const char *keywords[] = {"regex","minsyms", "throttle",
                                   "symtabs", NULL};
-  symtab_list_type symtab_paths;
 
   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!IO", keywords,
                                        &regex, &PyBool_Type,
@@ -683,6 +669,12 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
       minsyms_p = cmp;
     }
 
+  global_symbol_searcher spec (FUNCTIONS_DOMAIN, regex);
+  SCOPE_EXIT {
+    for (const char *elem : spec.filenames)
+      xfree ((void *) elem);
+  };
+
   /* The "symtabs" keyword is any Python iterable object that returns
      a gdb.Symtab on each iteration.  If specified, iterate through
      the provided gdb.Symtabs and extract their full path.  As
@@ -728,20 +720,13 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
 
          /* Make sure there is a definite place to store the value of
             filename before it is released.  */
-         symtab_paths.vec.push_back (nullptr);
-         symtab_paths.vec.back () = filename.release ();
+         spec.filenames.push_back (nullptr);
+         spec.filenames.back () = filename.release ();
        }
     }
 
-  if (symtab_list)
-    {
-      const char **files = symtab_paths.vec.data ();
-
-      symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL,
-                               symtab_paths.vec.size (), files, false);
-    }
-  else
-    symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL, 0, NULL, false);
+  /* The search spec.  */
+  symbols = spec.search ();
 
   /* Count the number of symbols (both symbols and optionally minimal
      symbols) so we can correctly check the throttle limit.  */
index b5c8109fde327d698a3180b2f8e5cddf38989f79..e5ed42a49b6d35b7e9d027fb1f75151b1de4d47d 100644 (file)
@@ -4347,27 +4347,24 @@ info_sources_command (const char *args, int from_tty)
   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
@@ -4443,30 +4440,10 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
                 result->end ());
 }
 
-/* Search the symbol table for matches to the regular expression REGEXP,
-   returning the results.
-
-   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
-
-   Within each file the results are sorted locally; each symtab's global and
-   static blocks are separately alphabetized.
-   Duplicate entries are removed.
-
-   When EXCLUDE_MINSYMS is false then matching minsyms are also returned,
-   otherwise they are excluded.  */
+/* See symtab.h.  */
 
 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;
@@ -4490,21 +4467,23 @@ search_symbols (const char *regexp, enum search_domain kind,
   gdb::optional<compiled_regex> preg;
   gdb::optional<compiled_regex> treg;
 
-  gdb_assert (kind != ALL_DOMAIN);
+  gdb_assert (m_kind != ALL_DOMAIN);
 
-  ourtype = types[kind];
-  ourtype2 = types2[kind];
-  ourtype3 = types3[kind];
-  ourtype4 = types4[kind];
+  ourtype = types[m_kind];
+  ourtype2 = types2[m_kind];
+  ourtype3 = types3[m_kind];
+  ourtype4 = types4[m_kind];
 
-  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;
-      const char *opname = operator_chars (regexp, &opend);
+      const char *opname = operator_chars (symbol_name_regexp, &opend);
 
       if (*opname)
        {
@@ -4529,28 +4508,30 @@ 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);
-             regexp = tmp;
+             symbol_name_regexp = tmp;
            }
        }
 
       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);
-      treg.emplace (t_regexp, cflags, _("Invalid regexp"));
+      treg.emplace (m_symbol_type_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.  */
+  /* Search through the partial symtabs *first* for all symbols matching
+     the m_symbol_name_regexp (in preg).  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,
+                            return file_matches (filename, filenames,
                                                  basenames);
                           },
                           lookup_name_info::match_any (),
@@ -4561,7 +4542,7 @@ search_symbols (const char *regexp, enum search_domain kind,
                                                    0, NULL, 0) == 0);
                           },
                           NULL,
-                          kind);
+                          m_kind);
 
   /* Here, we search through the minimal symbol tables for functions
      and variables that match, and force their symbols to be read.
@@ -4579,7 +4560,8 @@ search_symbols (const char *regexp, enum search_domain kind,
      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))
+  if (filenames.empty () && (m_kind == VARIABLES_DOMAIN
+                            || m_kind == FUNCTIONS_DOMAIN))
     {
       for (objfile *objfile : current_program_space->objfiles ())
        {
@@ -4603,7 +4585,7 @@ search_symbols (const char *regexp, enum search_domain kind,
                         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
+                     if (m_kind == FUNCTIONS_DOMAIN
                          ? (find_pc_compunit_symtab
                             (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
                             == NULL)
@@ -4634,16 +4616,16 @@ search_symbols (const char *regexp, enum search_domain kind,
                  /* 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)
+                 if ((file_matches (real_symtab->filename, filenames, false)
                       || ((basenames_may_differ
                            || file_matches (lbasename (real_symtab->filename),
-                                            files, nfiles, 1))
+                                            filenames, true))
                           && file_matches (symtab_to_fullname (real_symtab),
-                                           files, nfiles, 0)))
+                                           filenames, false)))
                      && ((!preg.has_value ()
                           || preg->exec (sym->natural_name (), 0,
                                          NULL, 0) == 0)
-                         && ((kind == VARIABLES_DOMAIN
+                         && ((m_kind == VARIABLES_DOMAIN
                               && SYMBOL_CLASS (sym) != LOC_TYPEDEF
                               && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
                               && SYMBOL_CLASS (sym) != LOC_BLOCK
@@ -4656,15 +4638,15 @@ search_symbols (const char *regexp, enum search_domain kind,
                                        == TYPE_CODE_ENUM))
                               && (!treg.has_value ()
                                   || treg_matches_sym_type_name (*treg, sym)))
-                             || (kind == FUNCTIONS_DOMAIN
+                             || (m_kind == FUNCTIONS_DOMAIN
                                  && SYMBOL_CLASS (sym) == LOC_BLOCK
                                  && (!treg.has_value ()
                                      || treg_matches_sym_type_name (*treg,
                                                                     sym)))
-                             || (kind == TYPES_DOMAIN
+                             || (m_kind == TYPES_DOMAIN
                                  && SYMBOL_CLASS (sym) == LOC_TYPEDEF
                                  && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN)
-                             || (kind == MODULES_DOMAIN
+                             || (m_kind == MODULES_DOMAIN
                                  && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
                                  && SYMBOL_LINE (sym) != 0))))
                    {
@@ -4679,13 +4661,13 @@ search_symbols (const char *regexp, enum search_domain kind,
   if (!result.empty ())
     sort_search_symbols_remove_dups (&result);
 
-  /* 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.  */
+  /* If there are no debug symbols, then add matching minsyms.  But if the
+     user wants to see symbols matching a type m_symbol_type_regexp, then
+     never give a minimal symbol, as we assume that a minimal symbol does
+     not have a type.  */
 
-  if ((found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
-      && !exclude_minsyms
+  if ((found_misc || (filenames.empty () && m_kind != FUNCTIONS_DOMAIN))
+      && !m_exclude_minsyms
       && !treg.has_value ())
     {
       for (objfile *objfile : current_program_space->objfiles ())
@@ -4708,7 +4690,7 @@ search_symbols (const char *regexp, enum search_domain kind,
                    {
                      /* For functions we can do a quick check of whether the
                         symbol might be found via find_pc_symtab.  */
-                     if (kind != FUNCTIONS_DOMAIN
+                     if (m_kind != FUNCTIONS_DOMAIN
                          || (find_pc_compunit_symtab
                              (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
                              == NULL))
@@ -4847,10 +4829,10 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
   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)
     {
@@ -5081,11 +5063,9 @@ 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, ':');
 
@@ -5101,17 +5081,14 @@ rbreak_command (const char *regexp, int from_tty)
          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);
        }
     }
 
-  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)
@@ -6345,17 +6322,17 @@ search_module_symbols (const char *module_regexp, const char *regexp,
   std::vector<module_symbol_search> results;
 
   /* Search for all modules matching MODULE_REGEXP.  */
-  std::vector<symbol_search> modules = search_symbols (module_regexp,
-                                                      MODULES_DOMAIN,
-                                                      NULL, 0, NULL,
-                                                      true);
+  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.  */
-  std::vector<symbol_search> symbols = search_symbols (regexp, kind,
-                                                      type_regexp, 0,
-                                                      NULL, true);
+  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.  */
index 9c2aea7cf74a9ab668dc7f4bdd8e4f17f6a50d1f..680c334086b7f0435357ec4fd3e3f3c43e307283 100644 (file)
@@ -797,7 +797,7 @@ gdb_static_assert (NR_DOMAINS <= (1 << SYMBOL_DOMAIN_BITS));
 
 extern const char *domain_name (domain_enum);
 
-/* Searching domains, used for `search_symbols'.  Element numbers are
+/* Searching domains, used when searching for symbols.  Element numbers are
    hardcoded in GDB, check all enum uses before changing it.  */
 
 enum search_domain
@@ -2011,11 +2011,9 @@ extern struct symbol *fixup_symbol_section (struct symbol *,
 extern symbol *find_function_alias_target (bound_minimal_symbol msymbol);
 
 /* Symbol searching */
-/* Note: struct symbol_search, search_symbols, et.al. are declared here,
-   instead of making them local to symtab.c, for gdbtk's sake.  */
 
-/* When using search_symbols, a vector of the following structs is
-   returned.  */
+/* When using the symbol_searcher struct to search for symbols, a vector of
+   the following structs is returned.  */
 struct symbol_search
 {
   symbol_search (int block_, struct symbol *symbol_)
@@ -2064,12 +2062,68 @@ private:
                                  const symbol_search &sym_b);
 };
 
-extern std::vector<symbol_search> search_symbols (const char *,
-                                                 enum search_domain,
-                                                 const char *,
-                                                 int,
-                                                 const char **,
-                                                 bool);
+/* In order to search for global symbols of a particular kind matching
+   particular regular expressions, create an instance of this structure and
+   call the SEARCH member function.  */
+class global_symbol_searcher
+{
+public:
+
+  /* Constructor.  */
+  global_symbol_searcher (enum search_domain kind,
+                         const char *symbol_name_regexp)
+    : m_kind (kind),
+      m_symbol_name_regexp (symbol_name_regexp)
+  {
+    /* The symbol searching is designed to only find one kind of thing.  */
+    gdb_assert (m_kind != ALL_DOMAIN);
+  }
+
+  /* Set the optional regexp that matches against the symbol type.  */
+  void set_symbol_type_regexp (const char *regexp)
+  {
+    m_symbol_type_regexp = regexp;
+  }
+
+  /* Set the flag to exclude minsyms from the search results.  */
+  void set_exclude_minsyms (bool exclude_minsyms)
+  {
+    m_exclude_minsyms = exclude_minsyms;
+  }
+
+  /* Search the symbols from all objfiles in the current program space
+     looking for matches as defined by the current state of this object.
+
+     Within each file the results are sorted locally; each symtab's global
+     and static blocks are separately alphabetized.  Duplicate entries are
+     removed.  */
+  std::vector<symbol_search> search () const;
+
+  /* The set of source files to search in for matching symbols.  This is
+     currently public so that it can be populated after this object has
+     been constructed.  */
+  std::vector<const char *> filenames;
+
+private:
+  /* The kind of symbols are we searching for.
+     VARIABLES_DOMAIN - Search all symbols, excluding functions, type
+                        names, and constants (enums).
+     FUNCTIONS_DOMAIN - Search all functions..
+     TYPES_DOMAIN     - Search all type names.
+     MODULES_DOMAIN   - Search all Fortran modules.
+     ALL_DOMAIN       - Not valid for this function.  */
+  enum search_domain m_kind;
+
+  /* Regular expression to match against the symbol name.  */
+  const char *m_symbol_name_regexp = nullptr;
+
+  /* Regular expression to match against the symbol type.  */
+  const char *m_symbol_type_regexp = nullptr;
+
+  /* When this flag is false then minsyms that match M_SYMBOL_REGEXP will
+     be included in the results, otherwise they are excluded.  */
+  bool m_exclude_minsyms = false;
+};
 
 /* When searching for Fortran symbols within modules (functions/variables)
    we return a vector of this type.  The first item in the pair is the