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.

One other thing to note is that the global_symbol_searcher::search by
default returns SIZE_MAX results, there's no longer a mechanism to
return an unlimited number of results, though hopefully this will not
be a huge issue.

gdb/ChangeLog:

	* mi/mi-symbol-cmds.c (mi_symbol_info): Take extra parameter, and
	add it into the search spec.
	(parse_max_results_option): New function.
	(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 (global_symbol_searcher::add_matching_symbols): Change
	return type to bool, change result container into a set, and don't
	add new results if we have enough already.
	(global_symbol_searcher::add_matching_msymbols): Change return
	type to bool, and don't add new results if we have enough already.
	(sort_search_symbols_remove_dups): Delete.
	(global_symbol_searcher::search): Early exit from search loop when
	we have enough results.  Use a std::set to collect the results
	from calling add_matching_symbols.
	* symtab.h (global_symbol_searcher) <set_max_seach_results>: New
	member function.
	(global_symbol_searcher) <m_max_search_results>: New member
	variable.
	(global_symbol_searcher) <add_matching_symbols>: Update header
	comment and change return type to bool.
	(global_symbol_searcher) <add_matching_msymbols>: Update header
	comment and change return type to bool.

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
This commit is contained in:
Andrew Burgess 2019-10-15 00:02:51 +01:00
parent f97a63c5aa
commit c2512106f8
8 changed files with 179 additions and 35 deletions

View File

@ -1,3 +1,30 @@
2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
* mi/mi-symbol-cmds.c (mi_symbol_info): Take extra parameter, and
add it into the search spec.
(parse_max_results_option): New function.
(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 (global_symbol_searcher::add_matching_symbols): Change
return type to bool, change result container into a set, and don't
add new results if we have enough already.
(global_symbol_searcher::add_matching_msymbols): Change return
type to bool, and don't add new results if we have enough already.
(sort_search_symbols_remove_dups): Delete.
(global_symbol_searcher::search): Early exit from search loop when
we have enough results. Use a std::set to collect the results
from calling add_matching_symbols.
* symtab.h (global_symbol_searcher) <set_max_seach_results>: New
member function.
(global_symbol_searcher) <m_max_search_results>: New member
variable.
(global_symbol_searcher) <add_matching_symbols>: Update header
comment and change return type to bool.
(global_symbol_searcher) <add_matching_msymbols>: Update header
comment and change return type to bool.
2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com> 2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
* symtab.c (symbol_search::compare_search_syms): Update header * symtab.c (symbol_search::compare_search_syms): Update header

View File

@ -1,3 +1,8 @@
2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
* doc/gdb.texinfo (GDB/MI Symbol Query): Add documentation of
-max-results to some -symbol-info-* commands.
2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com> 2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
* doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command * doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command

View File

@ -33962,6 +33962,7 @@ N.A.
-symbol-info-functions [--include-nondebug] -symbol-info-functions [--include-nondebug]
[--type @var{type_regexp}] [--type @var{type_regexp}]
[--name @var{name_regexp}] [--name @var{name_regexp}]
[--max-results @var{limit}]
@end smallexample @end smallexample
@noindent @noindent
@ -33977,6 +33978,11 @@ The options @code{--type} and @code{--name} allow the symbols returned
to be filtered based on either the name of the function, or the type to be filtered based on either the name of the function, or the type
signature of the function. 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 @subsubheading @value{GDBN} Command
The corresponding @value{GDBN} command is @samp{info functions}. The corresponding @value{GDBN} command is @samp{info functions}.
@ -34208,6 +34214,8 @@ The corresponding @value{GDBN} command is @samp{info module variables}.
@smallexample @smallexample
-symbol-info-modules [--name @var{name_regexp}] -symbol-info-modules [--name @var{name_regexp}]
[--max-results @var{limit}]
@end smallexample @end smallexample
@noindent @noindent
@ -34218,6 +34226,11 @@ which each modules is defined.
The option @code{--name} allows the modules returned to be filtered The option @code{--name} allows the modules returned to be filtered
based the name of the module. 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 @subsubheading @value{GDBN} Command
The corresponding @value{GDBN} command is @samp{info modules}. The corresponding @value{GDBN} command is @samp{info modules}.
@ -34262,6 +34275,8 @@ The corresponding @value{GDBN} command is @samp{info modules}.
@smallexample @smallexample
-symbol-info-types [--name @var{name_regexp}] -symbol-info-types [--name @var{name_regexp}]
[--max-results @var{limit}]
@end smallexample @end smallexample
@noindent @noindent
@ -34275,6 +34290,11 @@ line number.
The option @code{--name} allows the list of types returned to be The option @code{--name} allows the list of types returned to be
filtered by name. 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 @subsubheading @value{GDBN} Command
The corresponding @value{GDBN} command is @samp{info types}. The corresponding @value{GDBN} command is @samp{info types}.
@ -34322,6 +34342,8 @@ The corresponding @value{GDBN} command is @samp{info types}.
-symbol-info-variables [--include-nondebug] -symbol-info-variables [--include-nondebug]
[--type @var{type_regexp}] [--type @var{type_regexp}]
[--name @var{name_regexp}] [--name @var{name_regexp}]
[--max-results @var{limit}]
@end smallexample @end smallexample
@noindent @noindent
@ -34337,6 +34359,11 @@ The options @code{--type} and @code{--name} allow the symbols returned
to be filtered based on either the name of the variable, or the type to be filtered based on either the name of the variable, or the type
of the variable. 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 @subsubheading @value{GDBN} Command
The corresponding @value{GDBN} command is @samp{info variables}. The corresponding @value{GDBN} command is @samp{info variables}.

View File

@ -111,11 +111,13 @@ output_nondebug_symbol (ui_out *uiout,
static void static void
mi_symbol_info (enum search_domain kind, const char *name_regexp, mi_symbol_info (enum search_domain kind, const char *name_regexp,
const char *type_regexp, bool exclude_minsyms) const char *type_regexp, bool exclude_minsyms,
size_t max_results)
{ {
global_symbol_searcher sym_search (kind, name_regexp); global_symbol_searcher sym_search (kind, name_regexp);
sym_search.set_symbol_type_regexp (type_regexp); sym_search.set_symbol_type_regexp (type_regexp);
sym_search.set_exclude_minsyms (exclude_minsyms); sym_search.set_exclude_minsyms (exclude_minsyms);
sym_search.set_max_search_results (max_results);
std::vector<symbol_search> symbols = sym_search.search (); std::vector<symbol_search> symbols = sym_search.search ();
ui_out *uiout = current_uiout; ui_out *uiout = current_uiout;
int i = 0; int i = 0;
@ -166,25 +168,42 @@ mi_symbol_info (enum search_domain kind, const char *name_regexp,
} }
} }
/* Helper to parse the option text from an -max-results argument and return
the parsed value. If the text can't be parsed then an error is thrown. */
static size_t
parse_max_results_option (char *arg)
{
char *ptr = arg;
long long val = strtoll (arg, &ptr, 10);
if (arg == ptr || *ptr != '\0' || val > SIZE_MAX || val < 0)
error (_("invalid value for --max-results argument"));
size_t max_results = (size_t) val;
return max_results;
}
/* Helper for mi_cmd_symbol_info_{functions,variables} - depending on KIND. /* Helper for mi_cmd_symbol_info_{functions,variables} - depending on KIND.
Processes command line options from ARGV and ARGC. */ Processes command line options from ARGV and ARGC. */
static void static void
mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc) mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc)
{ {
size_t max_results = SIZE_MAX;
const char *regexp = nullptr; const char *regexp = nullptr;
const char *t_regexp = nullptr; const char *t_regexp = nullptr;
bool exclude_minsyms = true; bool exclude_minsyms = true;
enum opt 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[] = static const struct mi_opt opts[] =
{ {
{"-include-nondebug" , INCLUDE_NONDEBUG_OPT, 0}, {"-include-nondebug" , INCLUDE_NONDEBUG_OPT, 0},
{"-type", TYPE_REGEXP_OPT, 1}, {"-type", TYPE_REGEXP_OPT, 1},
{"-name", NAME_REGEXP_OPT, 1}, {"-name", NAME_REGEXP_OPT, 1},
{"-max-results", MAX_RESULTS_OPT, 1},
{ 0, 0, 0 } { 0, 0, 0 }
}; };
@ -210,10 +229,13 @@ mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc)
case NAME_REGEXP_OPT: case NAME_REGEXP_OPT:
regexp = oarg; regexp = oarg;
break; break;
case MAX_RESULTS_OPT:
max_results = parse_max_results_option (oarg);
break;
} }
} }
mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms); mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms, max_results);
} }
/* Type for an iterator over a vector of module_symbol_search results. */ /* Type for an iterator over a vector of module_symbol_search results. */
@ -384,15 +406,17 @@ mi_cmd_symbol_info_module_variables (const char *command, char **argv,
void void
mi_cmd_symbol_info_modules (const char *command, char **argv, int argc) mi_cmd_symbol_info_modules (const char *command, char **argv, int argc)
{ {
size_t max_results = SIZE_MAX;
const char *regexp = nullptr; const char *regexp = nullptr;
enum opt enum opt
{ {
NAME_REGEXP_OPT NAME_REGEXP_OPT, MAX_RESULTS_OPT
}; };
static const struct mi_opt opts[] = static const struct mi_opt opts[] =
{ {
{"-name", NAME_REGEXP_OPT, 1}, {"-name", NAME_REGEXP_OPT, 1},
{"-max-results", MAX_RESULTS_OPT, 1},
{ 0, 0, 0 } { 0, 0, 0 }
}; };
@ -410,10 +434,13 @@ mi_cmd_symbol_info_modules (const char *command, char **argv, int argc)
case NAME_REGEXP_OPT: case NAME_REGEXP_OPT:
regexp = oarg; regexp = oarg;
break; break;
case MAX_RESULTS_OPT:
max_results = parse_max_results_option (oarg);
break;
} }
} }
mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true); mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true, max_results);
} }
/* Implement -symbol-info-types command. */ /* Implement -symbol-info-types command. */
@ -421,15 +448,17 @@ mi_cmd_symbol_info_modules (const char *command, char **argv, int argc)
void void
mi_cmd_symbol_info_types (const char *command, char **argv, int argc) mi_cmd_symbol_info_types (const char *command, char **argv, int argc)
{ {
size_t max_results = SIZE_MAX;
const char *regexp = nullptr; const char *regexp = nullptr;
enum opt enum opt
{ {
NAME_REGEXP_OPT NAME_REGEXP_OPT, MAX_RESULTS_OPT
}; };
static const struct mi_opt opts[] = static const struct mi_opt opts[] =
{ {
{"-name", NAME_REGEXP_OPT, 1}, {"-name", NAME_REGEXP_OPT, 1},
{"-max-results", MAX_RESULTS_OPT, 1},
{ 0, 0, 0 } { 0, 0, 0 }
}; };
@ -447,10 +476,13 @@ mi_cmd_symbol_info_types (const char *command, char **argv, int argc)
case NAME_REGEXP_OPT: case NAME_REGEXP_OPT:
regexp = oarg; regexp = oarg;
break; break;
case MAX_RESULTS_OPT:
max_results = parse_max_results_option (oarg);
break;
} }
} }
mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true); mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true, max_results);
} }
/* Implement -symbol-info-variables command. */ /* Implement -symbol-info-variables command. */

View File

@ -4547,12 +4547,12 @@ global_symbol_searcher::expand_symtabs
/* See symtab.h. */ /* See symtab.h. */
void bool
global_symbol_searcher::add_matching_symbols global_symbol_searcher::add_matching_symbols
(objfile *objfile, (objfile *objfile,
const gdb::optional<compiled_regex> &preg, const gdb::optional<compiled_regex> &preg,
const gdb::optional<compiled_regex> &treg, const gdb::optional<compiled_regex> &treg,
std::vector<symbol_search> *results) const std::set<symbol_search> *result_set) const
{ {
enum search_domain kind = m_kind; enum search_domain kind = m_kind;
@ -4610,17 +4610,26 @@ global_symbol_searcher::add_matching_symbols
&& SYMBOL_DOMAIN (sym) == MODULE_DOMAIN && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
&& SYMBOL_LINE (sym) != 0)))) && SYMBOL_LINE (sym) != 0))))
{ {
/* Matching msymbol, add it to the results list. */ if (result_set->size () < m_max_search_results)
results->emplace_back (block, sym); {
/* 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;
} }
/* See symtab.h. */ /* See symtab.h. */
void bool
global_symbol_searcher::add_matching_msymbols global_symbol_searcher::add_matching_msymbols
(objfile *objfile, const gdb::optional<compiled_regex> &preg, (objfile *objfile, const gdb::optional<compiled_regex> &preg,
std::vector<symbol_search> *results) const std::vector<symbol_search> *results) const
@ -4652,22 +4661,17 @@ global_symbol_searcher::add_matching_msymbols
VAR_DOMAIN).symbol == NULL) VAR_DOMAIN).symbol == NULL)
{ {
/* Matching msymbol, add it to the results list. */ /* Matching msymbol, add it to the results list. */
results->emplace_back (GLOBAL_BLOCK, msymbol, objfile); if (results->size () < m_max_search_results)
results->emplace_back (GLOBAL_BLOCK, msymbol, objfile);
else
return false;
} }
} }
} }
} }
} }
}
/* Sort the symbols in RESULT and remove duplicates. */ return true;
static void
sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
{
std::sort (result->begin (), result->end ());
result->erase (std::unique (result->begin (), result->end ()),
result->end ());
} }
/* See symtab.h. */ /* See symtab.h. */
@ -4733,20 +4737,24 @@ global_symbol_searcher::search () const
} }
bool found_msymbol = false; bool found_msymbol = false;
std::vector<symbol_search> result; std::set<symbol_search> result_set;
for (objfile *objfile : current_program_space->objfiles ()) for (objfile *objfile : current_program_space->objfiles ())
{ {
/* Expand symtabs within objfile that possibly contain matching /* Expand symtabs within objfile that possibly contain matching
symbols. */ symbols. */
found_msymbol |= expand_symtabs (objfile, preg); found_msymbol |= expand_symtabs (objfile, preg);
/* Find matching symbols within OBJFILE and add them in to the RESULT /* Find matching symbols within OBJFILE and add them in to the
vector. */ RESULT_SET set. Use a set here so that we can easily detect
add_matching_symbols (objfile, preg, treg, &result); 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 (!result.empty ()) /* Convert the result set into a sorted result list, as std::set is
sort_search_symbols_remove_dups (&result); 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 there are no debug symbols, then add matching minsyms. But if the /* 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 user wants to see symbols matching a type regexp, then never give a
@ -4758,7 +4766,8 @@ global_symbol_searcher::search () const
{ {
gdb_assert (m_kind == VARIABLES_DOMAIN || m_kind == FUNCTIONS_DOMAIN); gdb_assert (m_kind == VARIABLES_DOMAIN || m_kind == FUNCTIONS_DOMAIN);
for (objfile *objfile : current_program_space->objfiles ()) for (objfile *objfile : current_program_space->objfiles ())
add_matching_msymbols (objfile, preg, &result); if (!add_matching_msymbols (objfile, preg, &result))
break;
} }
return result; return result;

View File

@ -23,6 +23,7 @@
#include <array> #include <array>
#include <vector> #include <vector>
#include <string> #include <string>
#include <set>
#include "gdbsupport/gdb_vecs.h" #include "gdbsupport/gdb_vecs.h"
#include "gdbtypes.h" #include "gdbtypes.h"
#include "gdb_obstack.h" #include "gdb_obstack.h"
@ -2092,6 +2093,12 @@ public:
m_exclude_minsyms = exclude_minsyms; m_exclude_minsyms = exclude_minsyms;
} }
/* Set the maximum number of search results to be returned. */
void set_max_search_results (size_t max_search_results)
{
m_max_search_results = max_search_results;
}
/* Search the symbols from all objfiles in the current program space /* Search the symbols from all objfiles in the current program space
looking for matches as defined by the current state of this object. looking for matches as defined by the current state of this object.
@ -2125,6 +2132,10 @@ private:
be included in the results, otherwise they are excluded. */ be included in the results, otherwise they are excluded. */
bool m_exclude_minsyms = false; bool m_exclude_minsyms = false;
/* Maximum number of search results. We currently impose a hard limit
of SIZE_MAX, there is no "unlimited". */
size_t m_max_search_results = SIZE_MAX;
/* Expand symtabs in OBJFILE that match PREG, are of type M_KIND. Return /* 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 true if any msymbols were seen that we should later consider adding to
the results list. */ the results list. */
@ -2132,15 +2143,23 @@ private:
const gdb::optional<compiled_regex> &preg) const; const gdb::optional<compiled_regex> &preg) const;
/* Add symbols from symtabs in OBJFILE that match PREG, and TREG, and are /* Add symbols from symtabs in OBJFILE that match PREG, and TREG, and are
of type M_KIND, to the results vector RESULTS. */ of type M_KIND, to the results set RESULTS_SET. Return false if we
void add_matching_symbols (objfile *objfile, stop adding results early due to having already found too many results
(based on M_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> &preg,
const gdb::optional<compiled_regex> &treg, const gdb::optional<compiled_regex> &treg,
std::vector<symbol_search> *results) const; std::set<symbol_search> *result_set) const;
/* Add msymbols from OBJFILE that match PREG and M_KIND, to the /* Add msymbols from OBJFILE that match PREG and M_KIND, to the results
results vector RESULTS. */ vector RESULTS. Return false if we stop adding results early due to
void add_matching_msymbols (objfile *objfile, having already found too many results (based on max search results
limit M_MAX_SEARCH_RESULTS), 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, const gdb::optional<compiled_regex> &preg,
std::vector<symbol_search> *results) const; std::vector<symbol_search> *results) const;

View File

@ -1,3 +1,7 @@
2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.mi/mi-sym-info.exp: Add tests for -max-results parameter.
2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com> 2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.mi/mi-fortran-modules.exp: Add additional tests for * gdb.mi/mi-fortran-modules.exp: Add additional tests for

View File

@ -127,3 +127,24 @@ set lineno2 [gdb_get_line_number "typedef int another_int_t;" ${srcfile2}]
mi_gdb_test "120-symbol-info-types --name _int_" \ 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\"\}\\\]\}\\\]\}" \ "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_" "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"