[3/3] gdb/mi: Add new commands -symbol-info-{functions,variables,types}

Message ID bf4130022c1c3a92f8e328a898f5c36dd4009781.1569539198.git.andrew.burgess@embecosm.com
State New
Headers show
Series
  • New MI commands for info functions/types/variables
Related show

Commit Message

Andrew Burgess Sept. 26, 2019, 11:09 p.m.
Add new MI commands -symbol-info-functions, -symbol-info-variables,
and -symbol-info-types which correspond to the CLI commands 'info
functions', 'info variables', and 'info types' respectively.

gdb/ChangeLog:

	* mi/mi-cmds.c: Add '-symbol-info-functions',
	'-symbol-info-variables', and '-symbol-info-types'.
	* mi/mi-cmds.h (mi_cmd_symbol_info_functions): Declare.
	(mi_cmd_symbol_info_variables): Declare.
	(mi_cmd_symbol_info_types): Declare.
	* mi/mi-symbol-cmds.c: Add 'source.h' and 'mi-getopt.h' includes.
	(mi_symbol_info): New function.
	(mi_info_functions_or_variables): New function.
	(mi_cmd_symbol_info_functions): New function.
	(mi_cmd_symbol_info_variables): New function.
	(mi_cmd_symbol_info_types): New function.
	* NEWS: Mention new commands.

gdb/testsuite/ChangeLog:

	* gdb.mi/mi-sym-info-1.c: New file.
	* gdb.mi/mi-sym-info-2.c: New file.
	* gdb.mi/mi-sym-info.exp: New file.

gdb/doc/ChangeLog:

	* doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command
	-symbol-info-functions, -symbol-info-types, and
	-symbol-info-variables.
---
 gdb/ChangeLog                        |  15 +++
 gdb/NEWS                             |   4 +
 gdb/doc/ChangeLog                    |   6 +
 gdb/doc/gdb.texinfo                  | 212 ++++++++++++++++++++++++++++++++++-
 gdb/mi/mi-cmds.c                     |   3 +
 gdb/mi/mi-cmds.h                     |   3 +
 gdb/mi/mi-symbol-cmds.c              | 195 ++++++++++++++++++++++++++++++++
 gdb/testsuite/ChangeLog              |   6 +
 gdb/testsuite/gdb.mi/mi-sym-info-1.c |  48 ++++++++
 gdb/testsuite/gdb.mi/mi-sym-info-2.c |  43 +++++++
 gdb/testsuite/gdb.mi/mi-sym-info.exp | 179 +++++++++++++++++++++++++++++
 11 files changed, 708 insertions(+), 6 deletions(-)
 create mode 100644 gdb/testsuite/gdb.mi/mi-sym-info-1.c
 create mode 100644 gdb/testsuite/gdb.mi/mi-sym-info-2.c
 create mode 100644 gdb/testsuite/gdb.mi/mi-sym-info.exp

-- 
2.14.5

Comments

Eli Zaretskii Sept. 27, 2019, 5:43 a.m. | #1
> From: Andrew Burgess <andrew.burgess@embecosm.com>

> Cc: Andrew Burgess <andrew.burgess@embecosm.com>

> Date: Fri, 27 Sep 2019 00:09:37 +0100

> 

> diff --git a/gdb/NEWS b/gdb/NEWS

> index 779fd91d3a6..9c1d08a24c4 100644

> --- a/gdb/NEWS

> +++ b/gdb/NEWS

> @@ -302,6 +302,10 @@ focus, winheight, +, -, >, <

>    These can be used to catch C++ exceptions in a similar fashion to

>    the CLI commands 'catch throw', 'catch rethrow', and 'catch catch'.

>  

> +-symbol-info-functions, -symbol-info-types, and -symbol-info-variables

> +  These commands are the MI equivalent of the CLI commands 'info

> +  functions', 'info types', and 'info variables' respectively.

> +

>  * Other MI changes


This part is OK.

> +@noindent

> +Returns a list containing the names and types for all global functions

   ^^^^^^^
"Return", to be consistent with our style in describing the other MI
commands.

> +taken from the debug information.  The functions are grouped by source

> +file, and the line number on which each function is defined is given.


It is best to avoid passive tense if possible and practical.  In this
case, I suggest to reword the last sentence as

  The functions are grouped by source file, and shown with the line
  number on which each function is defined.

> +When @code{--include-nondebug} is passed then the output also includes

> +code symbols from the symbol table.


Again, this reqording:

  The @code{--include-nondebug} option causes the output to include
  code symbols from the symbol table.

avoids passive tense and makes the text more clear.

> +@subsubheading Example

> +@smallexample

> +(gdb)

> +-symbol-info-functions

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="36",definition="void f4(int *);"@},

> +                    @{line="42",definition="int main();"@},

> +                    @{line="30",definition="static my_int_t f1(int, int);"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="33",definition="float f2(another_float_t);"@},

> +                    @{line="39",definition="int f3(another_int_t);"@},

> +                    @{line="27",definition="static another_float_t f1(int);"@}]@}]@}

> +(gdb)

> +-symbol-info-functions --name f1

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="30",definition="static my_int_t f1(int, int);"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="27",definition="static another_float_t f1(int);"@}]@}]@}

> +(gdb)

> +-symbol-info-functions --type void

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="36",definition="void f4(int *);"@}]@}]@}

> +(gdb)

> +-symbol-info-functions --include-nondebug

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="36",definition="void f4(int *);"@},

> +                     @{line="42",definition="int main();"@},

> +                     @{line="30",definition="static my_int_t f1(int, int);"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="33",definition="float f2(another_float_t);"@},

> +                     @{line="39",definition="int f3(another_int_t);"@},

> +                     @{line="27",definition="static another_float_t f1(int);"@}]@}],

> +    nondebug=

> +     [@{address="0x0000000000400398",name="_init"@},

> +      @{address="0x00000000004003b0",name="_start"@},

> +      ...

> +     ]@}

> +@end smallexample


This long series of examples should have @group..@end group to make
sure TeX doesn't break any example between pages.

> +@noindent

> +Returns a list of all defined types.  The types are grouped by source

   ^^^^^^^
"Return".

> +file, and the line number on which each user defined type is defined.


See previous comments.

> +Some base types are not defined in the source code but are added to

> +the debug information by the compiler, for example @code{int},

> +@code{float}, etc, these types do not have an associated line number.


This slight modification

  @code{float}, etc.; these types do not have an associated line number.

is more grammatically correct, and also reads easier.

> +The options @code{--name} allows the list of types returned to be

       ^^^^^^^
"option", in singular

> +@smallexample

> +(gdb)

> +-symbol-info-types

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{definition="float"@},

> +                    @{definition="int"@},

> +                    @{line="27",definition="typedef int my_int_t;"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="24",definition="typedef float another_float_t;"@},

> +                    @{line="23",definition="typedef int another_int_t;"@},

> +                    @{definition="float"@},

> +                    @{definition="int"@}]@}]@}

> +(gdb)

> +-symbol-info-types --name _int_

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="27",definition="typedef int my_int_t;"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="23",definition="typedef int another_int_t;"@}]@}]@}

> +@end smallexample


See previous comments about the long example.

> +@noindent

> +Returns a list containing the names and types for all global variables

> +taken from the debug information.  The variables are grouped by source

> +file, and the line number on which each variable is definedd given.

> +

> +When @code{--include-nondebug} is passed then the output also includes

> +data symbols from the symbol table.


See previous comments about similar text.

> +@subsubheading Example

> +@smallexample

> +(gdb)

> +-symbol-info-variables

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="25",definition="static float global_f1;"@},

> +                    @{line="24",definition="static int global_i1;"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="21",definition="int global_f2;"@},

> +                    @{line="20",definition="int global_i2;"@},

> +                    @{line="19",definition="static float global_f1;"@},

> +                    @{line="18",definition="static int global_i1;"@}]@}]@}

> +(gdb)

> +-symbol-info-variables --name f1

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="25",definition="static float global_f1;"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="19",definition="static float global_f1;"@}]@}]@}

> +(gdb)

> +-symbol-info-variables --type float

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="25",definition="static float global_f1;"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="19",definition="static float global_f1;"@}]@}]@}

> +(gdb)

> +-symbol-info-variables --include-nondebug

> +^done,symbols=

> +  @{debug=

> +     [@{filename="gdb.mi/mi-sym-info-1.c",

> +       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",

> +       definitions=[@{line="25",definition="static float global_f1;"@},

> +                    @{line="24",definition="static int global_i1;"@}]@},

> +      @{filename="gdb.mi/mi-sym-info-2.c",

> +       fullname="/project/gdb.mi/mi-sym-info-2.c",

> +       definitions=[@{line="21",definition="int global_f2;"@},

> +                    @{line="20",definition="int global_i2;"@},

> +                    @{line="19",definition="static float global_f1;"@},

> +                    @{line="18",definition="static int global_i1;"@}]@}],

> +    nondebug=

> +     [@{address="0x00000000004005d0",name="_IO_stdin_used"@},

> +      @{address="0x00000000004005d8",name="__dso_handle"@}

> +      ...

> +     ]@}

> +@end smallexample


See previous comments about long examples.

Thanks.
Simon Marchi Oct. 4, 2019, 3:01 a.m. | #2
On 2019-09-26 7:09 p.m., Andrew Burgess wrote:
> Add new MI commands -symbol-info-functions, -symbol-info-variables,

> and -symbol-info-types which correspond to the CLI commands 'info

> functions', 'info variables', and 'info types' respectively.


Hi Andrew,

The first thing I tried was to run it on GDB itself and run "-symbol-info-functions"
by itself.  Apparently, it tries to list all functions in the program :).  I think
we need to be careful with that, as it would be really easy for a debug session to
become unresponsive.  Imagine an IDE that has a little box to search symbols by name.
The user while debugging a big program, types "e<enter>", which generates this
MI command:

  -symbol-info-functions --name "e"

This would essentially hang the debug session while GDB expands all the symtabs with
at least a function with "e" in its name.  It would take a huge amount of time and
memory.  I don't know how easy it would be to implement, but for these cases, a
"--max-results N" switch, which would stop the search early, might useful.

Note that the same happens if you type "info functions" in the CLI.  But at least,
when using the CLI interactively, you can ctrl-C, which front-ends don't typically
do.

Also, since this output is meant to be consumed by a front-end, it would be
interesting to have the details of the symbols in separate fields.  For example,
for variables, have the type and name in separate fields.  This gives front-ends
more freedom on how to display them.

For functions, I would even see (maybe not in this patch though) a list of parameters
with their names and types.

Of course, we can always start with something basic and add fields as we go.

I didn't really look at the implementation, since it's getting a bit late, but:

> diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h

> index 91ce4cd4070..5fa4fafbb05 100644

> --- a/gdb/mi/mi-cmds.h

> +++ b/gdb/mi/mi-cmds.h

> @@ -94,6 +94,9 @@ extern mi_cmd_argv_ftype mi_cmd_stack_list_locals;

>  extern mi_cmd_argv_ftype mi_cmd_stack_list_variables;

>  extern mi_cmd_argv_ftype mi_cmd_stack_select_frame;

>  extern mi_cmd_argv_ftype mi_cmd_symbol_list_lines;

> +extern mi_cmd_argv_ftype mi_cmd_symbol_info_functions;

> +extern mi_cmd_argv_ftype mi_cmd_symbol_info_variables;

> +extern mi_cmd_argv_ftype mi_cmd_symbol_info_types;


The last two are not in alphabetical order (in the .c as well).

Simon
André Pönitz Oct. 4, 2019, 1:48 p.m. | #3
On Thu, Oct 03, 2019 at 11:01:12PM -0400, Simon Marchi wrote:
> On 2019-09-26 7:09 p.m., Andrew Burgess wrote:

> > Add new MI commands -symbol-info-functions, -symbol-info-variables,

> > and -symbol-info-types which correspond to the CLI commands 'info

> > functions', 'info variables', and 'info types' respectively.

> 

> Hi Andrew,

> 

> The first thing I tried was to run it on GDB itself and run "-symbol-info-functions"

> by itself.  Apparently, it tries to list all functions in the program :).  I think

> we need to be careful with that, as it would be really easy for a debug session to

> become unresponsive.  Imagine an IDE that has a little box to search symbols by name.

> The user while debugging a big program, types "e<enter>", which generates this

> MI command:

> 

>   -symbol-info-functions --name "e"

> 

> This would essentially hang the debug session while GDB expands all the symtabs with

> at least a function with "e" in its name.  It would take a huge amount of time and

> memory.  I don't know how easy it would be to implement, but for these cases, a

> "--max-results N" switch, which would stop the search early, might useful.


From an (one...) IDE's point of view, any such limit setting would be desirable,
and I'd personally would appreciate some limit on time, with the result record
indication on whether the result is complete or the timeout was hit.

> [...]

> 

> Also, since this output is meant to be consumed by a front-end, it would be

> interesting to have the details of the symbols in separate fields.  For example,

> for variables, have the type and name in separate fields.  This gives front-ends

> more freedom on how to display them.


Indeed.

Andre'
Andrew Burgess Oct. 11, 2019, 12:32 p.m. | #4
* Simon Marchi <simark@simark.ca> [2019-10-03 23:01:12 -0400]:

> On 2019-09-26 7:09 p.m., Andrew Burgess wrote:

> > Add new MI commands -symbol-info-functions, -symbol-info-variables,

> > and -symbol-info-types which correspond to the CLI commands 'info

> > functions', 'info variables', and 'info types' respectively.

> 

> Hi Andrew,

> 

> The first thing I tried was to run it on GDB itself and run "-symbol-info-functions"

> by itself.  Apparently, it tries to list all functions in the program :).  I think

> we need to be careful with that, as it would be really easy for a debug session to

> become unresponsive.  Imagine an IDE that has a little box to search symbols by name.

> The user while debugging a big program, types "e<enter>", which generates this

> MI command:

> 

>   -symbol-info-functions --name "e"

> 

> This would essentially hang the debug session while GDB expands all the symtabs with

> at least a function with "e" in its name.  It would take a huge amount of time and

> memory.  I don't know how easy it would be to implement, but for these cases, a

> "--max-results N" switch, which would stop the search early, might useful.


I looked into how easy this would be to implement, and I'm worried it
might be a rather involved task.

symtab.c:search_symbols is where the limit logic would need to be
applied, the problem is the logic in that function seems to basically
go like this:

   (1) Expand all symtabs that have a matching filename, and which
   contain a symbol that matches the regexp - this will be all symtabs
   in your worst case scenario.  At this point we expand only, symbols
   are not added to the result list.

   (2) Expand symtabs for msymbols with a matching name, again this is
   all msymbols in your worst case scenario, and again we don't add to
   the results list at this point.

   (3) Search through all symtabs adding matching symbols to the
   result list.

   (4) Sort the result list, and remove duplicates.

   (5) Add matching msymbols to the results list.

The problem I see here is that steps (1) and (2) are the costly parts
we would like to limit, however its not until steps (3) and (5) that
we really know how many results we've collected so far.

I'm going to experiment to see if I can find a way to build the
results as we process each objfile / symbtab, but I suspect doing that
might require some significant work.  If you have any suggestions then
I'm happy to listen.

One idea I did have, which isn't exactly a solution, but might be
related would be adding a timeout to the MI command.  This would
basically be like the user sending Ctrl-C after a given time.  You
still wouldn't get partial results, you'd just see that the command
was aborted due to timeout - however, this might provide a nice safety
net for MI commands.

Any suggestions welcome.

Thanks,
Andrew

> 

> Note that the same happens if you type "info functions" in the CLI.  But at least,

> when using the CLI interactively, you can ctrl-C, which front-ends don't typically

> do.

> 

> Also, since this output is meant to be consumed by a front-end, it would be

> interesting to have the details of the symbols in separate fields.  For example,

> for variables, have the type and name in separate fields.  This gives front-ends

> more freedom on how to display them.

> 

> For functions, I would even see (maybe not in this patch though) a list of parameters

> with their names and types.

> 

> Of course, we can always start with something basic and add fields as we go.

> 

> I didn't really look at the implementation, since it's getting a bit late, but:

> 

> > diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h

> > index 91ce4cd4070..5fa4fafbb05 100644

> > --- a/gdb/mi/mi-cmds.h

> > +++ b/gdb/mi/mi-cmds.h

> > @@ -94,6 +94,9 @@ extern mi_cmd_argv_ftype mi_cmd_stack_list_locals;

> >  extern mi_cmd_argv_ftype mi_cmd_stack_list_variables;

> >  extern mi_cmd_argv_ftype mi_cmd_stack_select_frame;

> >  extern mi_cmd_argv_ftype mi_cmd_symbol_list_lines;

> > +extern mi_cmd_argv_ftype mi_cmd_symbol_info_functions;

> > +extern mi_cmd_argv_ftype mi_cmd_symbol_info_variables;

> > +extern mi_cmd_argv_ftype mi_cmd_symbol_info_types;

> 

> The last two are not in alphabetical order (in the .c as well).

> 

> Simon

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index 779fd91d3a6..9c1d08a24c4 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -302,6 +302,10 @@  focus, winheight, +, -, >, <
   These can be used to catch C++ exceptions in a similar fashion to
   the CLI commands 'catch throw', 'catch rethrow', and 'catch catch'.
 
+-symbol-info-functions, -symbol-info-types, and -symbol-info-variables
+  These commands are the MI equivalent of the CLI commands 'info
+  functions', 'info types', and 'info variables' respectively.
+
 * Other MI changes
 
  ** The default version of the MI interpreter is now 3 (-i=mi3).
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index f2713c03960..59c84f029c2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -33694,27 +33694,227 @@ 
 
 @subsubheading Example
 N.A.
+@end ignore
+
+@subheading The @code{-symbol-info-functions} Command
+@findex -symbol-info-functions
+@anchor{-symbol-info-functions}
+
+@subsubheading Synopsis
 
+@smallexample
+ -symbol-info-functions [--include-nondebug] [--type @var{type_regexp}]
+                        [--name @var{name_regexp}]
+@end smallexample
 
-@subheading The @code{-symbol-info-function} Command
-@findex -symbol-info-function
+@noindent
+Returns a list containing the names and types for all global functions
+taken from the debug information.  The functions are grouped by source
+file, and the line number on which each function is defined is given.
+
+When @code{--include-nondebug} is passed then the output also includes
+code symbols from the symbol table.
+
+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
+signature of the function.
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{info functions}.
+
+@subsubheading Example
+@smallexample
+(gdb)
+-symbol-info-functions
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="36",definition="void f4(int *);"@},
+                    @{line="42",definition="int main();"@},
+                    @{line="30",definition="static my_int_t f1(int, int);"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="33",definition="float f2(another_float_t);"@},
+                    @{line="39",definition="int f3(another_int_t);"@},
+                    @{line="27",definition="static another_float_t f1(int);"@}]@}]@}
+(gdb)
+-symbol-info-functions --name f1
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="30",definition="static my_int_t f1(int, int);"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="27",definition="static another_float_t f1(int);"@}]@}]@}
+(gdb)
+-symbol-info-functions --type void
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="36",definition="void f4(int *);"@}]@}]@}
+(gdb)
+-symbol-info-functions --include-nondebug
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="36",definition="void f4(int *);"@},
+                     @{line="42",definition="int main();"@},
+                     @{line="30",definition="static my_int_t f1(int, int);"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="33",definition="float f2(another_float_t);"@},
+                     @{line="39",definition="int f3(another_int_t);"@},
+                     @{line="27",definition="static another_float_t f1(int);"@}]@}],
+    nondebug=
+     [@{address="0x0000000000400398",name="_init"@},
+      @{address="0x00000000004003b0",name="_start"@},
+      ...
+     ]@}
+@end smallexample
+
+@subheading The @code{-symbol-info-types} Command
+@findex -symbol-info-types
+@anchor{-symbol-info-types}
 
 @subsubheading Synopsis
 
 @smallexample
- -symbol-info-function
+ -symbol-info-types [--name @var{name_regexp}]
 @end smallexample
 
-Show which function the symbol lives in.
+@noindent
+Returns a list of all defined types.  The types are grouped by source
+file, and the line number on which each user defined type is defined.
+Some base types are not defined in the source code but are added to
+the debug information by the compiler, for example @code{int},
+@code{float}, etc, these types do not have an associated line number.
+
+The options @code{--name} allows the list of types returned to be
+filtered by name.
 
 @subsubheading @value{GDBN} Command
 
-@samp{gdb_get_function} in @code{gdbtk}.
+The corresponding @value{GDBN} command is @samp{info types}.
 
 @subsubheading Example
-N.A.
+@smallexample
+(gdb)
+-symbol-info-types
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{definition="float"@},
+                    @{definition="int"@},
+                    @{line="27",definition="typedef int my_int_t;"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="24",definition="typedef float another_float_t;"@},
+                    @{line="23",definition="typedef int another_int_t;"@},
+                    @{definition="float"@},
+                    @{definition="int"@}]@}]@}
+(gdb)
+-symbol-info-types --name _int_
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="27",definition="typedef int my_int_t;"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="23",definition="typedef int another_int_t;"@}]@}]@}
+@end smallexample
+
+@subheading The @code{-symbol-info-variables} Command
+@findex -symbol-info-variables
+@anchor{-symbol-info-variables}
+
+@subsubheading Synopsis
+
+@smallexample
+ -symbol-info-variables [--include-nondebug] [--type @var{type_regexp}]
+                        [--name @var{name_regexp}]
+@end smallexample
+
+@noindent
+Returns a list containing the names and types for all global variables
+taken from the debug information.  The variables are grouped by source
+file, and the line number on which each variable is definedd given.
+
+When @code{--include-nondebug} is passed then the output also includes
+data symbols from the symbol table.
 
+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
+of the variable.
 
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{info variables}.
+
+@subsubheading Example
+@smallexample
+(gdb)
+-symbol-info-variables
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="25",definition="static float global_f1;"@},
+                    @{line="24",definition="static int global_i1;"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="21",definition="int global_f2;"@},
+                    @{line="20",definition="int global_i2;"@},
+                    @{line="19",definition="static float global_f1;"@},
+                    @{line="18",definition="static int global_i1;"@}]@}]@}
+(gdb)
+-symbol-info-variables --name f1
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="25",definition="static float global_f1;"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="19",definition="static float global_f1;"@}]@}]@}
+(gdb)
+-symbol-info-variables --type float
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="25",definition="static float global_f1;"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="19",definition="static float global_f1;"@}]@}]@}
+(gdb)
+-symbol-info-variables --include-nondebug
+^done,symbols=
+  @{debug=
+     [@{filename="gdb.mi/mi-sym-info-1.c",
+       fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c",
+       definitions=[@{line="25",definition="static float global_f1;"@},
+                    @{line="24",definition="static int global_i1;"@}]@},
+      @{filename="gdb.mi/mi-sym-info-2.c",
+       fullname="/project/gdb.mi/mi-sym-info-2.c",
+       definitions=[@{line="21",definition="int global_f2;"@},
+                    @{line="20",definition="int global_i2;"@},
+                    @{line="19",definition="static float global_f1;"@},
+                    @{line="18",definition="static int global_i1;"@}]@}],
+    nondebug=
+     [@{address="0x00000000004005d0",name="_IO_stdin_used"@},
+      @{address="0x00000000004005d8",name="__dso_handle"@}
+      ...
+     ]@}
+@end smallexample
+
+@ignore
 @subheading The @code{-symbol-info-line} Command
 @findex -symbol-info-line
 
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index 37eab01de9e..df9f25fcbd0 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -151,6 +151,9 @@  static struct mi_cmd mi_cmds[] =
   DEF_MI_CMD_MI_1 ("stack-select-frame", mi_cmd_stack_select_frame,
 		   &mi_suppress_notification.user_selected_context),
   DEF_MI_CMD_MI ("symbol-list-lines", mi_cmd_symbol_list_lines),
+  DEF_MI_CMD_MI ("symbol-info-functions", mi_cmd_symbol_info_functions),
+  DEF_MI_CMD_MI ("symbol-info-variables", mi_cmd_symbol_info_variables),
+  DEF_MI_CMD_MI ("symbol-info-types", mi_cmd_symbol_info_types),
   DEF_MI_CMD_CLI ("target-attach", "attach", 1),
   DEF_MI_CMD_MI ("target-detach", mi_cmd_target_detach),
   DEF_MI_CMD_CLI ("target-disconnect", "disconnect", 0),
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index 91ce4cd4070..5fa4fafbb05 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -94,6 +94,9 @@  extern mi_cmd_argv_ftype mi_cmd_stack_list_locals;
 extern mi_cmd_argv_ftype mi_cmd_stack_list_variables;
 extern mi_cmd_argv_ftype mi_cmd_stack_select_frame;
 extern mi_cmd_argv_ftype mi_cmd_symbol_list_lines;
+extern mi_cmd_argv_ftype mi_cmd_symbol_info_functions;
+extern mi_cmd_argv_ftype mi_cmd_symbol_info_variables;
+extern mi_cmd_argv_ftype mi_cmd_symbol_info_types;
 extern mi_cmd_argv_ftype mi_cmd_target_detach;
 extern mi_cmd_argv_ftype mi_cmd_target_file_get;
 extern mi_cmd_argv_ftype mi_cmd_target_file_put;
diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c
index 63142e8e7e9..6c0cefcf88c 100644
--- a/gdb/mi/mi-symbol-cmds.c
+++ b/gdb/mi/mi-symbol-cmds.c
@@ -21,6 +21,8 @@ 
 #include "symtab.h"
 #include "objfiles.h"
 #include "ui-out.h"
+#include "source.h"
+#include "mi-getopt.h"
 
 /* Print the list of all pc addresses and lines of code for the
    provided (full or base) source file name.  The entries are sorted
@@ -59,3 +61,196 @@  mi_cmd_symbol_list_lines (const char *command, char **argv, int argc)
       uiout->field_signed ("line", SYMTAB_LINETABLE (s)->item[i].line);
     }
 }
+
+/* This is the guts of the commands '-symbol-info-functions',
+   '-symbol-info-variables', and '-symbol-info-types'.  It calls
+   search_symbols to find all matches and then prints the matching
+   [m]symbols in an MI structured format.  This is similar to
+   symtab_symbol_info in symtab.c.  */
+
+static void
+mi_symbol_info (bool exclude_minsyms, const char *regexp,
+		enum search_domain kind, const char *t_regexp)
+{
+  struct ui_out *uiout = current_uiout;
+
+  /* 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);
+
+  /* The outer container for all the matched symbols.  */
+  ui_out_emit_tuple all_matching_symbols (uiout, "symbols");
+
+  /* The order of these optional emitters is critical as they will be
+     deleted in reverse order, which is important as these are popped from
+     the uiout stack as they are destroyed.  */
+  gdb::optional<ui_out_emit_list> debug_func_emitter_outer;
+  gdb::optional<ui_out_emit_tuple> debug_func_emitter_symtab;
+  gdb::optional<ui_out_emit_list> debug_func_emitter_symbols;
+  gdb::optional<ui_out_emit_list> nondebug_func_emitter;
+
+  const symtab *last_symtab = nullptr;
+
+  for (const symbol_search &p : symbols)
+    {
+      QUIT;
+
+      if (p.msymbol.minsym != NULL)
+	{
+	  if (debug_func_emitter_outer.has_value ())
+	    {
+	      gdb_assert (debug_func_emitter_symbols.has_value ());
+	      gdb_assert (debug_func_emitter_symtab.has_value ());
+	      debug_func_emitter_symbols.reset ();
+	      debug_func_emitter_symtab.reset ();
+	      debug_func_emitter_outer.reset ();
+	    }
+
+	  if (!nondebug_func_emitter.has_value ())
+	    nondebug_func_emitter.emplace (uiout, "nondebug");
+	  struct bound_minimal_symbol msymbol = p.msymbol;
+	  struct gdbarch *gdbarch = get_objfile_arch (msymbol.objfile);
+	  ui_out_emit_tuple tuple_emitter (uiout, NULL);
+	  uiout->field_core_addr ("address", gdbarch,
+				  BMSYMBOL_VALUE_ADDRESS (msymbol));
+	  uiout->field_string ("name", MSYMBOL_PRINT_NAME (msymbol.minsym));
+	}
+      else
+	{
+	  struct symbol *sym = p.symbol;
+	  struct symtab *s = symbol_symtab (sym);
+
+	  /* All debug symbols should appear in the list before all
+	     non-debug symbols.  */
+	  gdb_assert (!nondebug_func_emitter.has_value ());
+
+	  /* Start the list of debug symbols.  */
+	  if (!debug_func_emitter_outer.has_value ())
+	    debug_func_emitter_outer.emplace (uiout, "debug");
+
+	  if (s != last_symtab)
+	    {
+	      /* Reset a possible previous symbol list within a symtab.  */
+	      debug_func_emitter_symbols.reset ();
+	      debug_func_emitter_symtab.reset ();
+
+	      /* Start a new symtab and symbol list within the symtab.  */
+	      debug_func_emitter_symtab.emplace (uiout, nullptr);
+	      uiout->field_string ("filename",
+				   symtab_to_filename_for_display (s));
+	      uiout->field_string ("fullname", symtab_to_fullname (s));
+	      debug_func_emitter_symbols.emplace (uiout, "definitions");
+
+	      /* Record the current symtab.  */
+	      last_symtab = s;
+	    }
+
+	  ui_out_emit_tuple tuple_emitter (uiout, NULL);
+	  if (SYMBOL_LINE (sym) != 0)
+	    uiout->field_unsigned ("line", SYMBOL_LINE (sym));
+	  std::string str = symbol_to_info_string (sym, p.block, kind);
+	  uiout->field_string ("definition", str.c_str ());
+	}
+    }
+}
+
+/* Helper for mi_cmd_symbol_info_{functions,variables} - depending on KIND.
+   Processes command line options from ARGV and ARGC.  */
+
+static void
+mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc)
+{
+  const char *regexp = nullptr;
+  const char *t_regexp = nullptr;
+  bool exclude_minsyms = true;
+
+  enum opt
+    {
+     INCLUDE_NONDEBUG_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT
+    };
+  static const struct mi_opt opts[] =
+  {
+    {"-include-nondebug" , INCLUDE_NONDEBUG_OPT, 0},
+    {"-type", TYPE_REGEXP_OPT, 1},
+    {"-name", NAME_REGEXP_OPT, 1},
+    { 0, 0, 0 }
+  };
+
+  int oind = 0;
+  char *oarg = nullptr;
+
+  while (1)
+    {
+      const char *cmd_string
+	= ((kind == FUNCTIONS_DOMAIN)
+	   ? "-symbol-info-functions" : "-symbol-info-variables");
+      int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg);
+      if (opt < 0)
+	break;
+      switch ((enum opt) opt)
+	{
+	case INCLUDE_NONDEBUG_OPT:
+	  exclude_minsyms = false;
+	  break;
+	case TYPE_REGEXP_OPT:
+	  t_regexp = oarg;
+	  break;
+	case NAME_REGEXP_OPT:
+	  regexp = oarg;
+	  break;
+	}
+    }
+
+  mi_symbol_info (exclude_minsyms, regexp, kind, t_regexp);
+}
+
+/* Implement -symbol-info-functions command.  */
+void
+mi_cmd_symbol_info_functions (const char *command, char **argv, int argc)
+{
+  mi_info_functions_or_variables (FUNCTIONS_DOMAIN, argv, argc);
+}
+
+/* Implement -symbol-info-variables command.  */
+void
+mi_cmd_symbol_info_variables (const char *command, char **argv, int argc)
+{
+  mi_info_functions_or_variables (VARIABLES_DOMAIN, argv, argc);
+}
+
+/* Implement -symbol-info-types command.  */
+void
+mi_cmd_symbol_info_types (const char *command, char **argv, int argc)
+{
+  const char *regexp = nullptr;
+
+  enum opt
+    {
+     NAME_REGEXP_OPT
+    };
+  static const struct mi_opt opts[] =
+  {
+    {"-name", NAME_REGEXP_OPT, 1},
+    { 0, 0, 0 }
+  };
+
+  int oind = 0;
+  char *oarg = nullptr;
+
+  while (1)
+    {
+      int opt = mi_getopt ("-symbol-info-types", argc, argv, opts,
+			   &oind, &oarg);
+      if (opt < 0)
+	break;
+      switch ((enum opt) opt)
+	{
+	case NAME_REGEXP_OPT:
+	  regexp = oarg;
+	  break;
+	}
+    }
+
+  mi_symbol_info (true, regexp, TYPES_DOMAIN, nullptr);
+}
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info-1.c b/gdb/testsuite/gdb.mi/mi-sym-info-1.c
new file mode 100644
index 00000000000..9b6dc7396ad
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-sym-info-1.c
@@ -0,0 +1,48 @@ 
+/* Copyright 2019 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Function and variables declared in mi-sym-info-2.c.  */
+extern float f2 (float arg);
+extern int f3 (int arg);
+extern int global_i2;
+extern float global_f2;
+
+static int global_i1;
+static float global_f1;
+
+typedef int my_int_t;
+
+static my_int_t
+f1 (int arg1, int arg2)
+{
+  return arg1 + arg2;
+}
+
+void
+f4 (int *arg)
+{
+  (*arg)++;
+}
+
+int
+main ()
+{
+  int v = f3 (4);
+  f4 (&v);
+  float tmp = f2 (1.0);
+  return f1 (3, v) + ((int) tmp);
+}
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info-2.c b/gdb/testsuite/gdb.mi/mi-sym-info-2.c
new file mode 100644
index 00000000000..c80877d8e7b
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-sym-info-2.c
@@ -0,0 +1,43 @@ 
+/* Copyright 2019 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+static int global_i1;
+static float global_f1;
+int global_i2;
+int global_f2;
+
+typedef int another_int_t;
+typedef float another_float_t;
+
+static another_float_t
+f1 (int arg)
+{
+  return (float) arg;
+}
+
+float
+f2 (another_float_t arg)
+{
+  return arg + f1 (1);
+}
+
+int
+f3 (another_int_t arg)
+{
+  return arg + 2;
+}
+
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info.exp b/gdb/testsuite/gdb.mi/mi-sym-info.exp
new file mode 100644
index 00000000000..ce7216be7fa
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-sym-info.exp
@@ -0,0 +1,179 @@ 
+# Copyright 2019 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test -symbol-info-functions, -symbol-info-variables, and
+# -symbol-info-types.
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+standard_testfile mi-sym-info-1.c mi-sym-info-2.c
+
+if {[prepare_for_testing "failed to prepare" ${testfile} \
+	 [list $srcfile $srcfile2] {debug}]} {
+    return -1
+}
+
+gdb_exit
+if {[mi_gdb_start]} {
+    continue
+}
+
+mi_run_to_main
+
+set qstr "\"\[^\"\]+\""
+set fun_re "\{line=\"$decimal\",definition=${qstr}\}"
+set type_re "\{(?:line=\"$decimal\",)*definition=${qstr}\}"
+set def_list "\\\[${fun_re}(?:,$fun_re)*\\\]"
+set type_def_list "\\\[${type_re}(?:,$type_re)*\\\]"
+set symtab_re \
+    "\{filename=${qstr},fullname=${qstr},definitions=${def_list}\}"
+set symtab_type_re \
+    "\{filename=${qstr},fullname=${qstr},definitions=${type_def_list}\}"
+set debug_only_syms \
+    "symbols=\{debug=\\\[${symtab_re}(?:,${symtab_re})*\\\]\}"
+set all_syms \
+    "symbols=\{debug=\\\[${symtab_re}(?:,${symtab_re})*\\\],nondebug=\\\[.*\\\]\}"
+set type_syms \
+    "symbols=\{debug=\\\[${symtab_type_re}(?:,${symtab_type_re})*\\\]\}"
+
+# Fetch all functions, variables and types without any non-debug
+# symbols.
+mi_gdb_test "111-symbol-info-functions" \
+    "111\\^done,${debug_only_syms}" \
+    "List all functions from debug information only"
+
+mi_gdb_test "112-symbol-info-variables" \
+    "112\\^done,${debug_only_syms}" \
+    "List all variables from debug information only"
+
+mi_gdb_test "113-symbol-info-types" \
+    "113\\^done,${type_syms}" \
+    "List all types"
+
+# Fetch functions and variables but also grab the non-debug symbols
+# (from the symbol table).  There's often so much output output from
+# this command that we overflow expect's buffers, avoid this by
+# fetching the output piece by piece.
+set testname "List all functions"
+gdb_test_multiple "114-symbol-info-functions --include-nondebug" ${testname} {
+    -re "114\\^done,symbols=\{debug=\\\[${symtab_re}(?:,${symtab_re})*\\\],nondebug=\\\[" {
+	exp_continue
+    }
+
+    -re "\{address=${qstr},name=${qstr}\}," {
+	exp_continue
+    }
+
+    -re "\{address=${qstr},name=${qstr}\}\\\]\}\r\n${mi_gdb_prompt}$" {
+	pass ${testname}
+    }
+}
+
+set testname "List all variables"
+gdb_test_multiple "115-symbol-info-variables --include-nondebug" ${testname} {
+    -re "115\\^done,symbols=\{debug=\\\[${symtab_re}(?:,${symtab_re})*\\\],nondebug=\\\[" {
+	verbose -log "Got the first part of the input"
+	exp_continue
+    }
+
+    -re "\{address=${qstr},name=${qstr}\}," {
+	exp_continue
+    }
+
+    -re "\{address=${qstr},name=${qstr}\}\\\]\}\r\n${mi_gdb_prompt}$" {
+	pass ${testname}
+    }
+}
+
+# Filter functions by name and type.
+set lineno [gdb_get_line_number "f3 (another_int_t arg)" ${srcfile2}]
+mi_gdb_test "116-symbol-info-functions --name f3" \
+    [join \
+	 [list \
+	      "116\\^done,symbols=\{debug=\\\[" \
+	      "\{filename=\"\[^\"\]+${srcfile2}\"," \
+	      "fullname=\"\[^\"\]+${srcfile2}\"," \
+	      "definitions=\\\[" \
+	      "\{line=\"${lineno}\"," \
+	      "definition=\"int f3\\(another_int_t\\);\"\}" \
+	      "\\\]\}\\\]\}" ] "" ] \
+    "List all functions matching pattern f3"
+
+set lineno [gdb_get_line_number "f4 (int *arg)" ${srcfile}]
+mi_gdb_test "117-symbol-info-functions --type void" \
+    [join \
+	 [list \
+	      "117\\^done,symbols=\{debug=\\\[" \
+	      "\{filename=\"\[^\"\]+${srcfile}\"," \
+	      "fullname=\"\[^\"\]+${srcfile}\"," \
+	      "definitions=\\\[\{line=\"${lineno}\"," \
+	      "definition=\"void f4\\(int \\*\\);\"\}" \
+	      "\\\]\}\\\]\}" ] "" ] \
+    "List all functions matching type void"
+
+# Filter variables by name and type.
+set lineno [gdb_get_line_number "int global_f2;" ${srcfile2}]
+mi_gdb_test "118-symbol-info-variables --name global_f2" \
+    [join \
+	 [list \
+	      "118\\^done,symbols=\{debug=\\\[" \
+	      "\{filename=\"\[^\"\]+${srcfile2}\"," \
+	      "fullname=\"\[^\"\]+${srcfile2}\"," \
+	      "definitions=\\\[" \
+	      "\{line=\"${lineno}\"," \
+	      "definition=\"int global_f2;\"\}\\\]\}\\\]\}" ] ""] \
+    "List all variables matching pattern global_f2"
+
+set lineno1 [gdb_get_line_number "static float global_f1;" ${srcfile}]
+set lineno2 [gdb_get_line_number "static float global_f1;" ${srcfile2}]
+mi_gdb_test "119-symbol-info-variables --type float" \
+    [join \
+	 [list \
+	      "119\\^done,symbols=" \
+	      "\{debug=\\\[" \
+	      "\{filename=\"\[^\"\]+${srcfile}\"," \
+	      "fullname=\"\[^\"\]+${srcfile}\"," \
+	      "definitions=\\\[" \
+	      "\{line=\"${lineno1}\"," \
+	      "definition=\"static float global_f1;\"\}\\\]\}," \
+	      "\{filename=\"\[^\"\]+${srcfile2}\"," \
+	      "fullname=\"\[^\"\]+${srcfile2}\"," \
+	      "definitions=\\\[" \
+	      "\{line=\"${lineno2}\"," \
+	      "definition=\"static float global_f1;\"\}" \
+	      "\\\]\}\\\]\}"] "" ] \
+    "List all variables matching type float"
+
+# Fetch types, filtering by name.
+set lineno1 [gdb_get_line_number "typedef int my_int_t;" ${srcfile}]
+set lineno2 [gdb_get_line_number "typedef int another_int_t;" ${srcfile2}]
+mi_gdb_test "120-symbol-info-types --name _int_" \
+    [join \
+	 [list \
+	      "120\\^done,symbols=" \
+	      "\{debug=\\\[" \
+	      "\{filename=\"\[^\"\]+${srcfile}\"," \
+	      "fullname=\"\[^\"\]+${srcfile}\"," \
+	      "definitions=\\\[" \
+	      "\{line=\"${lineno1}\"," \
+	      "definition=\"typedef int my_int_t;\"\}\\\]\}," \
+	      "\{filename=\"\[^\"\]+${srcfile2}\"," \
+	      "fullname=\"\[^\"\]+${srcfile2}\"," \
+	      "definitions=\\\[" \
+	      "\{line=\"${lineno2}\"," \
+	      "definition=\"typedef int another_int_t;\"\}" \
+	      "\\\]\}\\\]\}"] "" ] \
+    "List all types matching _int_"