* [PATCH 2/3] gdb: Split print_symbol_info into two parts
2019-09-26 23:09 [PATCH 0/3] New MI commands for info functions/types/variables Andrew Burgess
@ 2019-09-26 23:09 ` Andrew Burgess
2019-10-04 1:50 ` Simon Marchi
2019-09-26 23:09 ` [PATCH 3/3] gdb/mi: Add new commands -symbol-info-{functions,variables,types} Andrew Burgess
2019-09-26 23:09 ` [PATCH 1/3] gdb: Don't print a newline in language la_print_typedef methods Andrew Burgess
2 siblings, 1 reply; 9+ messages in thread
From: Andrew Burgess @ 2019-09-26 23:09 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
Split the function print_symbol_info into two parts, the new worker
core returns a string, which print_symbol_info then prints. This will
be useful in a later commit when some new MI commands will be added
which will use the worker core to fill some MI output fields.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* symtab.c (symbol_to_info_string): New function, most content
moved from print_symbol_info, but updated to return a std::string.
(print_symbol_info): Update to use symbol_to_info_string and print
returned string.
* symtab.h (symbol_to_info_string): Declare new function.
---
gdb/ChangeLog | 8 ++++++
gdb/symtab.c | 87 ++++++++++++++++++++++++++++++++++++-----------------------
gdb/symtab.h | 8 ++++++
3 files changed, 70 insertions(+), 33 deletions(-)
diff --git a/gdb/symtab.c b/gdb/symtab.c
index b4316479f53..5f5bbbb33cb 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4728,44 +4728,25 @@ search_symbols (const char *regexp, enum search_domain kind,
return result;
}
-/* Helper function for symtab_symbol_info, this function uses
- the data returned from search_symbols() to print information
- regarding the match to gdb_stdout. If LAST is not NULL,
- print file and line number information for the symbol as
- well. Skip printing the filename if it matches LAST. */
+/* See symtab.h. */
-static void
-print_symbol_info (enum search_domain kind,
- struct symbol *sym,
- int block, const char *last)
+std::string
+symbol_to_info_string (struct symbol *sym, int block,
+ enum search_domain kind)
{
- scoped_switch_to_sym_language_if_auto l (sym);
- struct symtab *s = symbol_symtab (sym);
-
- if (last != NULL)
- {
- const char *s_filename = symtab_to_filename_for_display (s);
+ std::string str;
- if (filename_cmp (last, s_filename) != 0)
- {
- fputs_filtered ("\nFile ", gdb_stdout);
- fputs_styled (s_filename, file_name_style.style (), gdb_stdout);
- fputs_filtered (":\n", gdb_stdout);
- }
-
- if (SYMBOL_LINE (sym) != 0)
- printf_filtered ("%d:\t", SYMBOL_LINE (sym));
- else
- puts_filtered ("\t");
- }
+ gdb_assert (block == GLOBAL_BLOCK || block == STATIC_BLOCK);
if (kind != TYPES_DOMAIN && block == STATIC_BLOCK)
- printf_filtered ("static ");
+ str += "static ";
/* Typedef that is not a C++ class. */
if (kind == TYPES_DOMAIN
&& SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN)
{
+ string_file tmp_stream;
+
/* FIXME: For C (and C++) we end up with a difference in output here
between how a typedef is printed, and non-typedefs are printed.
The TYPEDEF_PRINT code places a ";" at the end in an attempt to
@@ -4775,23 +4756,63 @@ print_symbol_info (enum search_domain kind,
printing of the ";" in this function, which is going to be wrong
for languages that don't require a ";" between statements. */
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_TYPEDEF)
- typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
+ typedef_print (SYMBOL_TYPE (sym), sym, &tmp_stream);
else
- type_print (SYMBOL_TYPE (sym), "", gdb_stdout, -1);
- printf_filtered ("\n");
+ type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1);
+ str += tmp_stream.string ();
}
/* variable, func, or typedef-that-is-c++-class. */
else if (kind < TYPES_DOMAIN
|| (kind == TYPES_DOMAIN
&& SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
{
+ string_file tmp_stream;
+
type_print (SYMBOL_TYPE (sym),
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
? "" : SYMBOL_PRINT_NAME (sym)),
- gdb_stdout, 0);
+ &tmp_stream, 0);
+
+ str += tmp_stream.string ();
+ str += ";";
+ }
- printf_filtered (";\n");
+ return str;
+}
+
+/* Helper function for symtab_symbol_info, this function uses
+ the data returned from search_symbols() to print information
+ regarding the match to gdb_stdout. If LAST is not NULL,
+ print file and line number information for the symbol as
+ well. Skip printing the filename if it matches LAST. */
+
+static void
+print_symbol_info (enum search_domain kind,
+ struct symbol *sym,
+ int block, const char *last)
+{
+ scoped_switch_to_sym_language_if_auto l (sym);
+ struct symtab *s = symbol_symtab (sym);
+
+ if (last != NULL)
+ {
+ const char *s_filename = symtab_to_filename_for_display (s);
+
+ if (filename_cmp (last, s_filename) != 0)
+ {
+ fputs_filtered ("\nFile ", gdb_stdout);
+ fputs_styled (s_filename, file_name_style.style (), gdb_stdout);
+ fputs_filtered (":\n", gdb_stdout);
+ }
+
+ if (SYMBOL_LINE (sym) != 0)
+ printf_filtered ("%d:\t", SYMBOL_LINE (sym));
+ else
+ puts_filtered ("\t");
}
+
+ std::string str = symbol_to_info_string (sym, block, kind);
+ printf_filtered ("%s\n", str.c_str ());
}
/* This help function for symtab_symbol_info() prints information
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 1f0fc62a657..f5da8229f2f 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2029,6 +2029,14 @@ extern std::vector<symbol_search> search_symbols (const char *,
int,
const char **,
bool);
+
+/* Helper for print_symbol_info, return a string that describes SYM.
+ BLOCK is either GLOBAL_BLOCK or STATIC_BLOCK, and KIND is the type of
+ symbol that was searched for. */
+
+extern std::string symbol_to_info_string (struct symbol *sym, int block,
+ enum search_domain kind);
+
extern bool treg_matches_sym_type_name (const compiled_regex &treg,
const struct symbol *sym);
--
2.14.5
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/3] gdb/mi: Add new commands -symbol-info-{functions,variables,types}
2019-09-26 23:09 [PATCH 0/3] New MI commands for info functions/types/variables Andrew Burgess
2019-09-26 23:09 ` [PATCH 2/3] gdb: Split print_symbol_info into two parts Andrew Burgess
@ 2019-09-26 23:09 ` Andrew Burgess
2019-09-27 5:43 ` Eli Zaretskii
2019-10-04 3:01 ` Simon Marchi
2019-09-26 23:09 ` [PATCH 1/3] gdb: Don't print a newline in language la_print_typedef methods Andrew Burgess
2 siblings, 2 replies; 9+ messages in thread
From: Andrew Burgess @ 2019-09-26 23:09 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
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
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_"
--
2.14.5
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/3] gdb: Don't print a newline in language la_print_typedef methods
2019-09-26 23:09 [PATCH 0/3] New MI commands for info functions/types/variables Andrew Burgess
2019-09-26 23:09 ` [PATCH 2/3] gdb: Split print_symbol_info into two parts Andrew Burgess
2019-09-26 23:09 ` [PATCH 3/3] gdb/mi: Add new commands -symbol-info-{functions,variables,types} Andrew Burgess
@ 2019-09-26 23:09 ` Andrew Burgess
2 siblings, 0 replies; 9+ messages in thread
From: Andrew Burgess @ 2019-09-26 23:09 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
When calling the language la_print_typedef method, don't include a
newline at the end, instead print the newline from the users of
la_print_typedef.
This change will be useful in a later commit when the output from
la_print_typedef will be placed into an MI output field, in which case
the trailing newline is not required.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* ada-typeprint.c (ada_print_typedef): Don't print newline at the
end.
* c-typeprint.c (c_print_typedef): Likewise.
* f-typeprint.c (f_print_typedef): Likewise.
* m2-typeprint.c (m2_print_typedef): Likewise.
* p-typeprint.c (pascal_print_typedef): Likewise.
* rust-lang.c (rust_print_typedef): Likewise.
* symtab.c (print_symbol_info): Print a newline after calling
typedef_print.
---
gdb/ChangeLog | 12 ++++++++++++
gdb/ada-typeprint.c | 1 -
gdb/c-typeprint.c | 2 +-
gdb/f-typeprint.c | 1 -
gdb/m2-typeprint.c | 2 +-
gdb/p-typeprint.c | 2 +-
gdb/rust-lang.c | 2 +-
gdb/symtab.c | 6 ++----
8 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 89a69e9bd44..f14a41fe835 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -951,5 +951,4 @@ ada_print_typedef (struct type *type, struct symbol *new_symbol,
{
type = ada_check_typedef (type);
ada_print_type (type, "", stream, 0, 0, &type_print_raw_options);
- fprintf_filtered (stream, "\n");
}
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 43ad3b3e0e6..c89acd4a7cd 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -211,7 +211,7 @@ c_print_typedef (struct type *type,
SYMBOL_LINKAGE_NAME (new_symbol)) != 0
|| TYPE_CODE (SYMBOL_TYPE (new_symbol)) == TYPE_CODE_TYPEDEF)
fprintf_filtered (stream, " %s", SYMBOL_PRINT_NAME (new_symbol));
- fprintf_filtered (stream, ";\n");
+ fprintf_filtered (stream, ";");
}
/* If TYPE is a derived type, then print out derivation information.
diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c
index 92b50938740..f7813d660ca 100644
--- a/gdb/f-typeprint.c
+++ b/gdb/f-typeprint.c
@@ -53,7 +53,6 @@ f_print_typedef (struct type *type, struct symbol *new_symbol,
{
type = check_typedef (type);
f_print_type (type, "", stream, 0, 0, &type_print_raw_options);
- fprintf_filtered (stream, "\n");
}
/* LEVEL is the depth to indent lines by. */
diff --git a/gdb/m2-typeprint.c b/gdb/m2-typeprint.c
index dae07d1c531..968d02a76a1 100644
--- a/gdb/m2-typeprint.c
+++ b/gdb/m2-typeprint.c
@@ -169,7 +169,7 @@ m2_print_typedef (struct type *type, struct symbol *new_symbol,
else
fprintf_filtered (stream, "<builtin> = ");
type_print (type, "", stream, 0);
- fprintf_filtered (stream, ";\n");
+ fprintf_filtered (stream, ";");
}
/* m2_type_name - if a, type, has a name then print it. */
diff --git a/gdb/p-typeprint.c b/gdb/p-typeprint.c
index d90b8ceb6ea..504ba477f91 100644
--- a/gdb/p-typeprint.c
+++ b/gdb/p-typeprint.c
@@ -100,7 +100,7 @@ pascal_print_typedef (struct type *type, struct symbol *new_symbol,
fprintf_filtered (stream, "type ");
fprintf_filtered (stream, "%s = ", SYMBOL_PRINT_NAME (new_symbol));
type_print (type, "", stream, 0);
- fprintf_filtered (stream, ";\n");
+ fprintf_filtered (stream, ";");
}
/* If TYPE is a derived type, then print out derivation information.
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 79f13311cd8..518c667345a 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -828,7 +828,7 @@ rust_print_typedef (struct type *type,
type = check_typedef (type);
fprintf_filtered (stream, "type %s = ", SYMBOL_PRINT_NAME (new_symbol));
type_print (type, "", stream, 0);
- fprintf_filtered (stream, ";\n");
+ fprintf_filtered (stream, ";");
}
/* la_print_type implementation for Rust. */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 6ea9fc6971e..b4316479f53 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4777,10 +4777,8 @@ print_symbol_info (enum search_domain kind,
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_TYPEDEF)
typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
else
- {
- type_print (SYMBOL_TYPE (sym), "", gdb_stdout, -1);
- printf_filtered ("\n");
- }
+ type_print (SYMBOL_TYPE (sym), "", gdb_stdout, -1);
+ printf_filtered ("\n");
}
/* variable, func, or typedef-that-is-c++-class. */
else if (kind < TYPES_DOMAIN
--
2.14.5
^ permalink raw reply [flat|nested] 9+ messages in thread