public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Andrew Burgess (Code Review)" <gerrit@gnutoolchain-gerrit.osci.io>
To: gdb-patches@sourceware.org
Cc: Joel Brobecker <brobecker@adacore.com>
Subject: [review v4] gdb/mi: Add -max-results parameter to some -symbol-info-* commands
Date: Fri, 22 Nov 2019 16:42:00 -0000	[thread overview]
Message-ID: <20191122164154.E2F9D2816F@gnutoolchain-gerrit.osci.io> (raw)
In-Reply-To: <gerrit.1571909344000.I90a28feb55b388fb46461a096c5db08b6b0bd427@gnutoolchain-gerrit.osci.io>

Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/269
......................................................................

gdb/mi: Add -max-results parameter to some -symbol-info-* commands

Adds a new parameter -max-results to -symbol-info-functions,
-symbol-info-variables, -symbol-info-types, and -symbol-info-modules.
This parameter limits the number of results returned.

This change still leaves -symbol-info-module-functions and
-symbol-info-module-variables always returning all results, fixing
these commands is slightly harder.

There's currently no mechanism for the user of these commands to know
if the result list has been truncated if you get back the maximum
number of results, so if there are exactly 10 functions and you call
'-symbol-info-functions --max-results 10' the reply would appear no
different than if you had 20 functions and called with a max of 10.
Right now, if you get back the maximum then you should assume that
there might be more results available.

gdb/ChangeLog:

	* mi/mi-symbol-cmds.c (mi_symbol_info): Take extra parameter, and
	add it into the search spec.
	(mi_info_functions_or_variables): Parse -max-results flag and pass
	it to mi_symbol_info.
	(mi_cmd_symbol_info_modules): Likewise.
	(mi_cmd_symbol_info_types): Likewise.
	* symtab.c (symbol_search::compare_search_syms): Update header
	comment.
	(global_symbol_searcher::is_suitable_msymbol): New function.
	(global_symbol_searcher::expand_symtabs): New function.
	(global_symbol_searcher::add_matching_symbols): New function.
	(global_symbol_searcher::add_matching_msymbols): New function.
	(global_symbol_searcher::search_symbols): Move most of the content
	into the new functions above, and call them as needed.
	* symtab.h: Add 'set' include.
	(global_symbol_searcher) <set_max_seach_results>: New member
	function.
	(global_symbol_searcher) <m_max_search_results>: New member
	variable.
	(global_symbol_searcher) <expand_symtabs>: New member function.
	(global_symbol_searcher) <add_matching_symbols>: New member
	function.
	(global_symbol_searcher) <add_matching_msymbols>: New member
	function.
	(global_symbol_searcher) <is_suitable_msymbol>: New member
	function.

gdb/doc/ChangeLog:

	* doc/gdb.texinfo (GDB/MI Symbol Query): Add documentation of
	-max-results to some -symbol-info-* commands.

gdb/testsuite/ChangeLog:

	* gdb.mi/mi-sym-info.exp: Add tests for -max-results parameter.

Change-Id: I90a28feb55b388fb46461a096c5db08b6b0bd427
---
M gdb/ChangeLog
M gdb/doc/ChangeLog
M gdb/doc/gdb.texinfo
M gdb/mi/mi-symbol-cmds.c
M gdb/symtab.c
M gdb/symtab.h
M gdb/testsuite/ChangeLog
M gdb/testsuite/gdb.mi/mi-sym-info.exp
8 files changed, 431 insertions(+), 216 deletions(-)



diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e67635f..ea41270 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,34 @@
 2019-11-22  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+	* mi/mi-symbol-cmds.c (mi_symbol_info): Take extra parameter, and
+	add it into the search spec.
+	(mi_info_functions_or_variables): Parse -max-results flag and pass
+	it to mi_symbol_info.
+	(mi_cmd_symbol_info_modules): Likewise.
+	(mi_cmd_symbol_info_types): Likewise.
+	* symtab.c (symbol_search::compare_search_syms): Update header
+	comment.
+	(global_symbol_searcher::is_suitable_msymbol): New function.
+	(global_symbol_searcher::expand_symtabs): New function.
+	(global_symbol_searcher::add_matching_symbols): New function.
+	(global_symbol_searcher::add_matching_msymbols): New function.
+	(global_symbol_searcher::search_symbols): Move most of the content
+	into the new functions above, and call them as needed.
+	* symtab.h: Add 'set' include.
+	(global_symbol_searcher) <set_max_seach_results>: New member
+	function.
+	(global_symbol_searcher) <m_max_search_results>: New member
+	variable.
+	(global_symbol_searcher) <expand_symtabs>: New member function.
+	(global_symbol_searcher) <add_matching_symbols>: New member
+	function.
+	(global_symbol_searcher) <add_matching_msymbols>: New member
+	function.
+	(global_symbol_searcher) <is_suitable_msymbol>: New member
+	function.
+
+2019-11-22  Andrew Burgess  <andrew.burgess@embecosm.com>
+
 	* mi/mi-cmds.c (mi_cmds): Add -symbol-info-module-functions and
 	-symbol-info-module-variables entries.
 	* mi/mi-cmds.h (mi_cmd_symbol_info_module_functions): Declare.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index ae310ea..36bde5a 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,5 +1,10 @@
 2019-11-22  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+	* doc/gdb.texinfo (GDB/MI Symbol Query): Add documentation of
+	-max-results to some -symbol-info-* commands.
+
+2019-11-22  Andrew Burgess  <andrew.burgess@embecosm.com>
+
 	* doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command
 	-symbol-info-module-functions and -symbol-info-module-variables.
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index fb32528..e004ae3 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -33886,6 +33886,7 @@
  -symbol-info-functions [--include-nondebug]
                         [--type @var{type_regexp}]
                         [--name @var{name_regexp}]
+                        [--max-results @var{limit}]
 @end smallexample
 
 @noindent
@@ -33901,6 +33902,11 @@
 to be filtered based on either the name of the function, or the type
 signature of the function.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info functions}.
@@ -34132,6 +34138,8 @@
 
 @smallexample
  -symbol-info-modules [--name @var{name_regexp}]
+                      [--max-results @var{limit}]
+
 @end smallexample
 
 @noindent
@@ -34142,6 +34150,11 @@
 The option @code{--name} allows the modules returned to be filtered
 based the name of the module.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info modules}.
@@ -34186,6 +34199,8 @@
 
 @smallexample
  -symbol-info-types [--name @var{name_regexp}]
+                    [--max-results @var{limit}]
+
 @end smallexample
 
 @noindent
@@ -34199,6 +34214,11 @@
 The option @code{--name} allows the list of types returned to be
 filtered by name.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info types}.
@@ -34246,6 +34266,8 @@
  -symbol-info-variables [--include-nondebug]
                         [--type @var{type_regexp}]
                         [--name @var{name_regexp}]
+                        [--max-results @var{limit}]
+
 @end smallexample
 
 @noindent
@@ -34261,6 +34283,11 @@
 to be filtered based on either the name of the variable, or the type
 of the variable.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info variables}.
diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c
index 7072d95..57bc103 100644
--- a/gdb/mi/mi-symbol-cmds.c
+++ b/gdb/mi/mi-symbol-cmds.c
@@ -248,12 +248,14 @@
 
 static void
 mi_symbol_info (enum search_domain kind, const char *regexp,
-		const char *t_regexp, bool exclude_minsyms)
+		const char *t_regexp, bool exclude_minsyms,
+		int max_results)
 {
   /* Must make sure that if we're interrupted, symbols gets freed.  */
   global_symbol_searcher sym_search (kind, regexp);
   sym_search.set_symbol_type_regexp (t_regexp);
   sym_search.set_exclude_minsyms (exclude_minsyms);
+  sym_search.set_max_search_results (max_results);
   std::vector<symbol_search> symbols = sym_search.search ();
 
   mi_symbol_info_emitter emitter (current_uiout);
@@ -270,19 +272,21 @@
 static void
 mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc)
 {
+  int max_results = -1;	/* -1 for unlimited.  */
   const char *regexp = nullptr;
   const char *t_regexp = nullptr;
   bool exclude_minsyms = true;
 
   enum opt
     {
-     INCLUDE_NONDEBUG_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT
+     INCLUDE_NONDEBUG_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT, MAX_RESULTS_OPT
     };
   static const struct mi_opt opts[] =
   {
     {"-include-nondebug" , INCLUDE_NONDEBUG_OPT, 0},
     {"-type", TYPE_REGEXP_OPT, 1},
     {"-name", NAME_REGEXP_OPT, 1},
+    {"-max-results", MAX_RESULTS_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -308,10 +312,19 @@
 	case NAME_REGEXP_OPT:
 	  regexp = oarg;
 	  break;
+	case MAX_RESULTS_OPT:
+	  {
+	    char *eptr = oarg;
+	    long val = strtol (oarg, &eptr, 10);
+	    if (oarg == eptr || val > INT_MAX || val < 0)
+	      error (_("invalid value for --max-results argument"));
+	    max_results = (int) val;
+	  }
+	  break;
 	}
     }
 
-  mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms);
+  mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms, max_results);
 }
 
 /* Core of -symbol-info-module-functions and -symbol-info-module-variables.
@@ -445,15 +458,17 @@
 void
 mi_cmd_symbol_info_modules (const char *command, char **argv, int argc)
 {
+  int max_results = -1; /* -1 for unlimited.  */
   const char *regexp = nullptr;
 
   enum opt
     {
-     NAME_REGEXP_OPT
+     NAME_REGEXP_OPT, MAX_RESULTS_OPT
     };
   static const struct mi_opt opts[] =
   {
     {"-name", NAME_REGEXP_OPT, 1},
+    {"-max-results", MAX_RESULTS_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -471,10 +486,19 @@
 	case NAME_REGEXP_OPT:
 	  regexp = oarg;
 	  break;
+	case MAX_RESULTS_OPT:
+	  {
+	    char *eptr = oarg;
+	    long val = strtol (oarg, &eptr, 10);
+	    if (oarg == eptr || val > INT_MAX || val < 0)
+	      error (_("invalid value for --max-results argument"));
+	    max_results = (int) val;
+	  }
+	  break;
 	}
     }
 
-  mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true);
+  mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true, max_results);
 }
 
 /* Implement -symbol-info-types command.  */
@@ -482,15 +506,17 @@
 void
 mi_cmd_symbol_info_types (const char *command, char **argv, int argc)
 {
+  int max_results = -1; /* -1 for unlimited.  */
   const char *regexp = nullptr;
 
   enum opt
     {
-     NAME_REGEXP_OPT
+     NAME_REGEXP_OPT, MAX_RESULTS_OPT
     };
   static const struct mi_opt opts[] =
   {
     {"-name", NAME_REGEXP_OPT, 1},
+    {"-max-results", MAX_RESULTS_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -508,10 +534,19 @@
 	case NAME_REGEXP_OPT:
 	  regexp = oarg;
 	  break;
+	case MAX_RESULTS_OPT:
+	  {
+	    char *eptr = oarg;
+	    long val = strtol (oarg, &eptr, 10);
+	    if (oarg == eptr || val > INT_MAX || val < 0)
+	      error (_("invalid value for --max-results argument"));
+	    max_results = (int) val;
+	  }
+	  break;
 	}
     }
 
-  mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true);
+  mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true, max_results);
 }
 
 /* Implement -symbol-info-variables command.  */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index afdbfa7..19772b9 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4359,8 +4359,8 @@
   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,
@@ -4422,15 +4422,242 @@
   return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
 }
 
+/* See symtab.h.  */
 
-/* Sort the symbols in RESULT and remove duplicates.  */
-
-static void
-sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
+bool
+global_symbol_searcher::is_suitable_msymbol
+	(const enum search_domain kind, const minimal_symbol *msymbol)
 {
-  std::sort (result->begin (), result->end ());
-  result->erase (std::unique (result->begin (), result->end ()),
-		 result->end ());
+  static const enum minimal_symbol_type types[]
+    = {mst_data, mst_text};
+  static const enum minimal_symbol_type types2[]
+    = {mst_bss, mst_file_text};
+  static const enum minimal_symbol_type types3[]
+    = {mst_file_data, mst_solib_trampoline};
+  static const enum minimal_symbol_type types4[]
+    = {mst_file_bss, mst_text_gnu_ifunc};
+
+  gdb_assert (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN);
+  gdb_assert (kind <= sizeof (types));
+
+  enum minimal_symbol_type ourtype = types[kind];
+  enum minimal_symbol_type ourtype2 = types2[kind];
+  enum minimal_symbol_type ourtype3 = types3[kind];
+  enum minimal_symbol_type ourtype4 = types4[kind];
+
+  return (MSYMBOL_TYPE (msymbol) == ourtype
+	  || MSYMBOL_TYPE (msymbol) == ourtype2
+	  || MSYMBOL_TYPE (msymbol) == ourtype3
+	  || MSYMBOL_TYPE (msymbol) == ourtype4);
+}
+
+/* See symtab.h.  */
+
+bool
+global_symbol_searcher::expand_symtabs
+	(objfile *objfile, const gdb::optional<compiled_regex> &preg) const
+{
+  enum search_domain kind = m_kind;
+  bool found_misc = false;
+
+  if (objfile->sf)
+    objfile->sf->qf->expand_symtabs_matching
+      (objfile,
+       [&] (const char *filename, bool basenames)
+       {
+	 /* EXPAND_SYMTABS_MATCHING expects a callback
+	    that returns an integer, not a boolean as
+	    FILE_MATCHES does.  */
+	 return file_matches (filename, filenames, basenames) ? 1 : 0;
+       },
+       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_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 (filenames.empty ()
+      && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
+    {
+      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 (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 = true;
+		}
+	    }
+	}
+    }
+
+  return found_misc;
+}
+
+/* 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
+{
+  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 (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+	{
+	  struct block_iterator iter;
+	  struct symbol *sym;
+	  const struct block *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, 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 (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))))
+		{
+		  if (m_max_search_results == -1
+		      || result_set->size () < m_max_search_results)
+		    {
+		      /* Match, insert if not already in the results.  */
+		      symbol_search ss (i, sym);
+		      if (result_set->find (ss) == result_set->end ())
+			result_set->insert (ss);
+		    }
+		  else
+		    return false;
+		}
+	    }
+	}
+    }
+
+  return true;
+}
+
+/* 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;
+
+  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 (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)
+		    {
+		      /* Matching msymbol, add it to the results list.  */
+		      if (m_max_search_results == -1
+			  || (results->size () < m_max_search_results))
+			results->emplace_back (GLOBAL_BLOCK, msymbol, objfile);
+		      else
+			return false;
+		    }
+		}
+	    }
+	}
+    }
+
+  return true;
 }
 
 /* See symtab.h.  */
@@ -4438,35 +4665,11 @@
 std::vector<symbol_search>
 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_assert (m_kind != ALL_DOMAIN);
 
-  ourtype = types[m_kind];
-  ourtype2 = types2[m_kind];
-  ourtype3 = types3[m_kind];
-  ourtype4 = types4[m_kind];
-
   if (m_symbol_name_regexp != NULL)
     {
       const char *symbol_name_regexp = m_symbol_name_regexp;
@@ -4519,192 +4722,36 @@
 		    _("Invalid m_symbol_namregexp"));
     }
 
-  /* Search through the partial symtabs *first* for all symbols
-     matching the m_symbol_namregexp.  That way we don't have to reproduce all of
-     the machinery below.  */
-  expand_symtabs_matching ([&] (const char *filename, bool basenames)
-			   {
-			     /* EXPAND_SYMTABS_MATCHING expects a callback
-				that returns an integer, not a boolean as
-				FILE_MATCHES does.  */
-			     return file_matches (filename, filenames,
-						  basenames) ? 1 : 0;
-			   },
-			   lookup_name_info::match_any (),
-			   [&] (const char *symname)
-			   {
-			     return (!preg.has_value ()
-				     || preg->exec (symname,
-						    0, NULL, 0) == 0);
-			   },
-			   NULL,
-			   m_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 (filenames.empty () && (m_kind == VARIABLES_DOMAIN
-			     || m_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 (m_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;
-		    }
-		}
-	    }
-	}
-    }
-
+  bool found_misc = false;
+  std::set<symbol_search> result_set;
   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);
+      /* Expand symtabs within objfile that possibly contain matching
+	 symbols.  */
+      found_misc |= expand_symtabs (objfile, preg);
 
-		  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 (SYMBOL_NATURAL_NAME (sym), 0,
-					  NULL, 0) == 0)
-			  && ((m_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)))
-			      || (m_kind == FUNCTIONS_DOMAIN
-				  && SYMBOL_CLASS (sym) == LOC_BLOCK
-				  && (!treg.has_value ()
-				      || treg_matches_sym_type_name (*treg,
-								     sym)))
-			      || (m_kind == TYPES_DOMAIN
-				  && SYMBOL_CLASS (sym) == LOC_TYPEDEF
-				  && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN)
-			      || (m_kind == MODULES_DOMAIN
-				  && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
-				  && SYMBOL_LINE (sym) != 0))))
-		    {
-		      /* match */
-		      result.emplace_back (i, sym);
-		    }
-		}
-	    }
-	}
+      /* Find matching symbols within OBJFILE and add them in to
+	 RESULT_SET.  */
+      if (!add_matching_symbols (objfile, preg, treg, &result_set))
+	break;
     }
 
-  if (!result.empty ())
-    sort_search_symbols_remove_dups (&result);
+  /* Convert the result set into a sorted result list.  */
+  std::vector<symbol_search> result (result_set.begin (), result_set.end ());
+  std::sort (result.begin (), result.end ());
 
-  /* 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 m_symbol_namregexp, then never give a minimal symbol,
-     as we assume that a minimal symbol does not have a type.  */
-
-  if ((found_misc || (filenames.empty () && m_kind != FUNCTIONS_DOMAIN))
+  /* 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_misc || (filenames.empty () && m_kind == VARIABLES_DOMAIN))
       && !m_exclude_minsyms
       && !treg.has_value ())
     {
+      gdb_assert (m_kind == VARIABLES_DOMAIN || m_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)
-		    {
-		      /* For functions we can do a quick check of whether the
-			 symbol might be found via find_pc_symtab.  */
-		      if (m_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;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index d4dbc2c..aa30f39 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -35,6 +35,8 @@
 #include "completer.h"
 #include "gdb-demangle.h"
 
+#include <set>
+
 /* Opaque declarations.  */
 struct ui_file;
 struct frame_info;
@@ -2106,6 +2108,12 @@
     m_exclude_minsyms = exclude_minsyms;
   }
 
+  /* Set the maximum number of search results to be returned.  */
+  void set_max_search_results (int max_search_results)
+  {
+    m_max_search_results = max_search_results;
+  }
+
   /* Search the symbols from all objfiles in the current program space
      looking for matches as defined by the current state of this object.
 
@@ -2138,6 +2146,41 @@
   /* 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;
+
+  /* Maximum number of search results, set to -1 for unlimited, otherwise
+     set to a positive value to limit the number of results returned.  */
+  int m_max_search_results = -1;
+
+  /* Expand symtabs in OBJFILE that match PREG, are of type M_KIND.  Return
+     true if any msymbols were seen that we should later consider adding to
+     the results list.  */
+  bool expand_symtabs (objfile *objfile,
+		       const gdb::optional<compiled_regex> &preg) const;
+
+  /* Add symbols from symtabs in OBJFILE that match PREG, and TREG, and are
+     of type M_KIND, to the results set RESULTS_SET.  Return false if we
+     stop adding results early due to having already found too many results
+     (based on MAX_SEARCH_RESULTS limit), otherwise return true.  Returning
+     true does not indicate that any results were added, just that we
+     didn't _not_ add a result due to reaching MAX_SEARCH_RESULTS.  */
+  bool add_matching_symbols (objfile *objfile,
+			     const gdb::optional<compiled_regex> &preg,
+			     const gdb::optional<compiled_regex> &treg,
+			     std::set<symbol_search> *result_set) const;
+
+  /* Add msymbols from OBJFILE that match PREG and M_KIND, to the
+     results vector RESULTS.  Return false if we stop adding results early
+     due to having already found too many results (based on max search
+     results limit in SEARCH_SPEC), otherwise return true.  Returning true
+     does not indicate that any results were added, just that we didn't
+     _not_ add a result due to reaching MAX_SEARCH_RESULTS.  */
+  bool add_matching_msymbols (objfile *objfile,
+			      const gdb::optional<compiled_regex> &preg,
+			      std::vector<symbol_search> *results) const;
+
+  /* Return true if MSYMBOL is of type KIND.  */
+  static bool is_suitable_msymbol (const enum search_domain kind,
+				   const minimal_symbol *msymbol);
 };
 
 /* When searching for Fortran symbols within modules (functions/variables)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 518d9cb..6807104 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
 2019-11-22  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+	* gdb.mi/mi-sym-info.exp: Add tests for -max-results parameter.
+
+2019-11-22  Andrew Burgess  <andrew.burgess@embecosm.com>
+
 	* gdb.mi/mi-fortran-modules.exp: Add additional tests for
 	-symbol-info-module-functions and -symbol-info-module-variables.
 
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info.exp b/gdb/testsuite/gdb.mi/mi-sym-info.exp
index 33fe865..80468a4 100644
--- a/gdb/testsuite/gdb.mi/mi-sym-info.exp
+++ b/gdb/testsuite/gdb.mi/mi-sym-info.exp
@@ -127,3 +127,28 @@
 mi_gdb_test "120-symbol-info-types --name _int_" \
     "120\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"27\",name=\"my_int_t\"\}\\\]\},\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"23\",name=\"another_int_t\"\}\\\]\}\\\]\}" \
     "List all types matching _int_"
+
+# Test the --max-results parameter.
+mi_gdb_test "121-symbol-info-functions --max-results 0" \
+    "121\\^done,symbols=\{\}" \
+    "-symbol-info-functions --max-results 0"
+
+mi_gdb_test "122-symbol-info-functions --max-results 1" \
+    "122\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"39\",name=\"f3\",type=\"int \\(another_int_t\\)\",description=\"int f3\\(another_int_t\\);\"\}\\\]\}\\\]\}" \
+    "-symbol-info-functions --max-results 1"
+
+mi_gdb_test "123-symbol-info-functions --max-results 2" \
+    "123\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"33\",name=\"f2\",type=\"float \\(another_float_t\\)\",description=\"float f2\\(another_float_t\\);\"\},\{line=\"39\",name=\"f3\",type=\"int \\(another_int_t\\)\",description=\"int f3\\(another_int_t\\);\"\}\\\]\}\\\]\}" \
+    "-symbol-info-functions --max-results 2"
+
+mi_gdb_test "124-symbol-info-variables --max-results 3" \
+    "124\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"global_f2\",type=\"int\",description=\"int global_f2;\"\},\{line=\"20\",name=\"global_i2\",type=\"int\",description=\"int global_i2;\"\},\{line=\"19\",name=\"global_f1\",type=\"float\",description=\"static float global_f1;\"\}\\\]\}\\\]\}" \
+    "-symbol-info-variables --max-results 3"
+
+mi_gdb_test "125-symbol-info-types --max-results 4" \
+    "125\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"24\",name=\"another_float_t\"\},\{line=\"23\",name=\"another_int_t\"\},\{name=\"float\"\},\{name=\"int\"\}\\\]\}\\\]\}" \
+    "-symbol-info-types --max-results 4"
+
+
+
+

-- 
Gerrit-Project: binutils-gdb
Gerrit-Branch: master
Gerrit-Change-Id: I90a28feb55b388fb46461a096c5db08b6b0bd427
Gerrit-Change-Number: 269
Gerrit-PatchSet: 4
Gerrit-Owner: Andrew Burgess <andrew.burgess@embecosm.com>
Gerrit-CC: Joel Brobecker <brobecker@adacore.com>
Gerrit-MessageType: newpatchset

  parent reply	other threads:[~2019-11-22 16:42 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <gerrit.1571909344000.I90a28feb55b388fb46461a096c5db08b6b0bd427@gnutoolchain-gerrit.osci.io>
2019-11-01  1:35 ` [review v2] " Andrew Burgess (Code Review)
2019-11-08  0:50 ` [review v3] " Andrew Burgess (Code Review)
2019-11-08 10:06   ` Eli Zaretskii
2019-11-22 16:42 ` Andrew Burgess (Code Review) [this message]
2019-11-22 17:33 ` [review v5] " Andrew Burgess (Code Review)
2019-11-26 23:26 ` [review v6] " Andrew Burgess (Code Review)
2019-11-26 23:40 ` [review v7] " Andrew Burgess (Code Review)
2019-11-27  5:31 ` Simon Marchi (Code Review)
2019-11-27 14:19 ` [review v8] " Andrew Burgess (Code Review)
2019-11-27 14:21 ` Andrew Burgess (Code Review)
2019-12-02 17:57 ` Andrew Burgess (Code Review)
2019-12-02 18:40 ` Simon Marchi (Code Review)
2019-12-02 19:15 ` [review v9] " Andrew Burgess (Code Review)
2019-12-02 19:18 ` Andrew Burgess (Code Review)
2019-12-02 19:37 ` Simon Marchi (Code Review)
2019-12-02 23:44 ` [review v10] " Andrew Burgess (Code Review)
2019-12-03  0:00 ` [review v11] " Andrew Burgess (Code Review)
2019-12-03  0:00 ` [review v10] " Andrew Burgess (Code Review)
2019-12-03  4:12 ` [review v11] " Simon Marchi (Code Review)
2019-12-03 10:25 ` [review v12] " Andrew Burgess (Code Review)
2019-12-03 10:56 ` [review v13] " Andrew Burgess (Code Review)
2019-12-03 10:59 ` Andrew Burgess (Code Review)
2019-12-03 16:50 ` Simon Marchi (Code Review)
2019-12-03 21:04 ` [review v14] " Andrew Burgess (Code Review)
2019-12-03 21:07 ` Andrew Burgess (Code Review)
2019-12-03 21:12 ` Simon Marchi (Code Review)
2019-12-04 10:49 ` [pushed] " Sourceware to Gerrit sync (Code Review)
2019-12-04 10:49 ` Sourceware to Gerrit sync (Code Review)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191122164154.E2F9D2816F@gnutoolchain-gerrit.osci.io \
    --to=gerrit@gnutoolchain-gerrit.osci.io \
    --cc=andrew.burgess@embecosm.com \
    --cc=brobecker@adacore.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).