From patchwork Fri Nov 1 01:27:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Simon Marchi (Code Review)" X-Patchwork-Id: 35559 Received: (qmail 49746 invoked by alias); 1 Nov 2019 01:28:11 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 49662 invoked by uid 89); 1 Nov 2019 01:28:11 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, KAM_STOCKGEN autolearn=ham version=3.3.1 spammy=msymbol, 20name X-HELO: mx1.osci.io Received: from polly.osci.io (HELO mx1.osci.io) (8.43.85.229) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 01 Nov 2019 01:28:03 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id C3E9A20339; Thu, 31 Oct 2019 21:28:01 -0400 (EDT) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [IPv6:2620:52:3:1:5054:ff:fe06:16ca]) by mx1.osci.io (Postfix) with ESMTP id 6B3D520555; Thu, 31 Oct 2019 21:27:56 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id D30BA20AF6; Thu, 31 Oct 2019 21:27:55 -0400 (EDT) X-Gerrit-PatchSet: 2 Date: Thu, 31 Oct 2019 21:27:51 -0400 From: "Andrew Burgess (Code Review)" To: Tom Tromey , gdb-patches@sourceware.org Auto-Submitted: auto-generated X-Gerrit-MessageType: newpatchset Subject: [review v2] gdb/mi: Add new commands -symbol-info-{functions, variables, types} X-Gerrit-Change-Id: Ic2fc6a6750bbce91cdde2344791014e5ef45642d X-Gerrit-Change-Number: 266 X-Gerrit-ChangeURL: X-Gerrit-Commit: c5398a7703e279a8cd2e5ace2a425673b660fa46 In-Reply-To: References: Reply-To: andrew.burgess@embecosm.com, tromey@sourceware.org, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3-75-g9005159e5d Message-Id: <20191101012755.D30BA20AF6@gnutoolchain-gerrit.osci.io> Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/266 ...................................................................... gdb/mi: Add new commands -symbol-info-{functions,variables,types} 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 (mi_cmds): 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_info_one_symbol_details): New function. (class mi_symbol_info_emitter): New class. (mi_symbol_info): New function. (mi_info_functions_or_variables): New function. (mi_cmd_symbol_info_functions): New function. (mi_cmd_symbol_info_types): New function. (mi_cmd_symbol_info_variables): 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. Change-Id: Ic2fc6a6750bbce91cdde2344791014e5ef45642d --- M gdb/ChangeLog M gdb/NEWS M gdb/doc/ChangeLog M gdb/doc/gdb.texinfo M gdb/mi/mi-cmds.c M gdb/mi/mi-cmds.h M gdb/mi/mi-symbol-cmds.c M gdb/testsuite/ChangeLog A gdb/testsuite/gdb.mi/mi-sym-info-1.c A gdb/testsuite/gdb.mi/mi-sym-info-2.c A gdb/testsuite/gdb.mi/mi-sym-info.exp 11 files changed, 828 insertions(+), 7 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7a66b62..5fce47c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,22 @@ 2019-11-01 Andrew Burgess + * mi/mi-cmds.c (mi_cmds): 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_info_one_symbol_details): New function. + (class mi_symbol_info_emitter): New class. + (mi_symbol_info): New function. + (mi_info_functions_or_variables): New function. + (mi_cmd_symbol_info_functions): New function. + (mi_cmd_symbol_info_types): New function. + (mi_cmd_symbol_info_variables): New function. + * NEWS: Mention new commands. + +2019-11-01 Andrew Burgess + * 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 diff --git a/gdb/NEWS b/gdb/NEWS index 59895bd..6855d35 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -344,6 +344,10 @@ 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/ChangeLog b/gdb/doc/ChangeLog index ce89ee4..af0478e 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2019-11-01 Andrew Burgess + + * doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command + -symbol-info-functions, -symbol-info-types, and + -symbol-info-variables. + 2019-10-31 Andrew Burgess * gdb.texinfo (Symbols): Document new 'info module variables' and diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 70e4be1..66dbb22 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33852,27 +33852,283 @@ @subsubheading Example N.A. +@end ignore - -@subheading The @code{-symbol-info-function} Command -@findex -symbol-info-function +@subheading The @code{-symbol-info-functions} Command +@findex -symbol-info-functions +@anchor{-symbol-info-functions} @subsubheading Synopsis @smallexample - -symbol-info-function + -symbol-info-functions [--include-nondebug] + [--type @var{type_regexp}] + [--name @var{name_regexp}] @end smallexample -Show which function the symbol lives in. +@noindent +Return a list containing the names and types for all global functions +taken from the debug information. The functions are grouped by source +file, and shown with the line number on which each function is +defined. + +The @code{--include-nondebug} option causes the output to include +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 -@samp{gdb_get_function} in @code{gdbtk}. +The corresponding @value{GDBN} command is @samp{info functions}. @subsubheading Example -N.A. +@smallexample +@group +(gdb) +-symbol-info-functions +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="36", name="f4", type="void (int *)", + description="void f4(int *);"@}, + @{line="42", name="main", type="int ()", + description="int main();"@}, + @{line="30", name="f1", type="my_int_t (int, int)", + description="static my_int_t f1(int, int);"@}]@}, + @{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + 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);"@}, + @{line="27", name="f1", type="another_float_t (int)", + description="static another_float_t f1(int);"@}]@}]@} +@end group +@group +(gdb) +-symbol-info-functions --name f1 +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="30", name="f1", type="my_int_t (int, int)", + description="static my_int_t f1(int, int);"@}]@}, + @{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + symbols=[@{line="27", name="f1", type="another_float_t (int)", + description="static another_float_t f1(int);"@}]@}]@} +@end group +@group +(gdb) +-symbol-info-functions --type void +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="36", name="f4", type="void (int *)", + description="void f4(int *);"@}]@}]@} +@end group +@group +(gdb) +-symbol-info-functions --include-nondebug +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="36", name="f4", type="void (int *)", + description="void f4(int *);"@}, + @{line="42", name="main", type="int ()", + description="int main();"@}, + @{line="30", name="f1", type="my_int_t (int, int)", + description="static my_int_t f1(int, int);"@}]@}, + @{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + 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);"@}, + @{line="27", name="f1", type="another_float_t (int)", + description="static another_float_t f1(int);"@}]@}], + nondebug= + [@{address="0x0000000000400398",name="_init"@}, + @{address="0x00000000004003b0",name="_start"@}, + ... + ]@} +@end group +@end smallexample +@subheading The @code{-symbol-info-types} Command +@findex -symbol-info-types +@anchor{-symbol-info-types} +@subsubheading Synopsis + +@smallexample + -symbol-info-types [--name @var{name_regexp}] +@end smallexample + +@noindent +Return a list of all defined types. The types are grouped by source +file, and shown with 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 option @code{--name} allows the list of types returned to be +filtered by name. + +@subsubheading @value{GDBN} Command + +The corresponding @value{GDBN} command is @samp{info types}. + +@subsubheading Example +@smallexample +@group +(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", + symbols=[@{name="float"@}, + @{name="int"@}, + @{line="27",name="typedef int my_int_t;"@}]@}, + @{filename="gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb.mi/mi-sym-info-2.c", + symbols=[@{line="24",name="typedef float another_float_t;"@}, + @{line="23",name="typedef int another_int_t;"@}, + @{name="float"@}, + @{name="int"@}]@}]@} +@end group +@group +(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", + symbols=[@{line="27",name="typedef int my_int_t;"@}]@}, + @{filename="gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb.mi/mi-sym-info-2.c", + symbols=[@{line="23",name="typedef int another_int_t;"@}]@}]@} +@end group +@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 +Return a list containing the names and types for all global variables +taken from the debug information. The variables are grouped by source +file, and shown with the line number on which each variable is +defined. + +The @code{--include-nondebug} option causes the output to include +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 +@group +(gdb) +-symbol-info-variables +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="25",name="global_f1",type="float", + description="static float global_f1;"@}, + @{line="24",name="global_i1",type="int", + description="static int global_i1;"@}]@}, + @{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + 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;"@}, + @{line="18",name="global_i1",type="int", + description="static int global_i1;"@}]@}]@} +@end group +@group +(gdb) +-symbol-info-variables --name f1 +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="25",name="global_f1",type="float", + description="static float global_f1;"@}]@}, + @{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + symbols=[@{line="19",name="global_f1",type="float", + description="static float global_f1;"@}]@}]@} +@end group +@group +(gdb) +-symbol-info-variables --type float +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="25",name="global_f1",type="float", + description="static float global_f1;"@}]@}, + @{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + symbols=[@{line="19",name="global_f1",type="float", + description="static float global_f1;"@}]@}]@} +@end group +@group +(gdb) +-symbol-info-variables --include-nondebug +^done,symbols= + @{debug= + [@{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-1.c", + symbols=[@{line="25",name="global_f1",type="float", + description="static float global_f1;"@}, + @{line="24",name="global_i1",type="int", + description="static int global_i1;"@}]@}, + @{filename="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + fullname="/project/gdb/testsuite/gdb.mi/mi-sym-info-2.c", + 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;"@}, + @{line="18",name="global_i1",type="int", + description="static int global_i1;"@}]@}], + nondebug= + [@{address="0x00000000004005d0",name="_IO_stdin_used"@}, + @{address="0x00000000004005d8",name="__dso_handle"@} + ... + ]@} +@end group +@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 37eab01..df9f25f 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -151,6 +151,9 @@ 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 91ce4cd..c2fd7d3 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_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_types; +extern mi_cmd_argv_ftype mi_cmd_symbol_info_variables; 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 63142e8..840cc00 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,307 @@ uiout->field_signed ("line", SYMTAB_LINETABLE (s)->item[i].line); } } + +/* Used by the -symbol-info-* and -symbol-info-module-* commands to print + information about the symbol SYM in a block of index BLOCK (either + GLOBAL_BLOCK or STATIC_BLOCK). KIND is the kind of symbol we searched + for in order to find SYM, which impact which fields are displayed in the + results. */ + +static void +mi_info_one_symbol_details (enum search_domain kind, + struct symbol *sym, int block) +{ + struct ui_out *uiout = current_uiout; + + ui_out_emit_tuple tuple_emitter (uiout, NULL); + if (SYMBOL_LINE (sym) != 0) + uiout->field_unsigned ("line", SYMBOL_LINE (sym)); + uiout->field_string ("name", SYMBOL_PRINT_NAME (sym)); + + if (kind == FUNCTIONS_DOMAIN || kind == VARIABLES_DOMAIN) + { + string_file tmp_stream; + type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1); + uiout->field_string ("type", tmp_stream.string ()); + + std::string str = symbol_to_info_string (sym, block, kind); + uiout->field_string ("description", str.c_str ()); + } +} + +/* This class is used to produce the nested structure of tuples and lists + required to present the results of the MI_SYMBOL_INFO function. */ +class mi_symbol_info_emitter +{ + /* When printing debug symbols we need to track the last symtab so we can + spot when we have entered a new one. */ + const symtab *m_last_symtab; + + /* The ui_out to which output will be sent. */ + struct ui_out *m_uiout; + + /* The outer container for all the matched symbols. */ + ui_out_emit_tuple m_outer_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 m_debug_emitter; + gdb::optional m_symtab_emitter; + gdb::optional m_symbols_emitter; + gdb::optional m_nondebug_emitter; + + /* Called when we might want to print our first nondebug symbol in order + to shutdown any debug symbol printing that might be in progress. */ + void maybe_finish_debug_output () + { + /* If the debug emitter is in use. */ + if (m_debug_emitter.has_value ()) + { + /* Then we should have a symbols list inside a symtab tuple also + currently in use. */ + gdb_assert (m_symbols_emitter.has_value ()); + gdb_assert (m_symtab_emitter.has_value ()); + + /* Shut down the symbols list, symtab tuple, and debug list + emitters (in that order). We are now back to the level of the + outer_symbols tuple ready to (possibly) start a nondebug list, + though that is not done here. */ + m_symbols_emitter.reset (); + m_symtab_emitter.reset (); + m_debug_emitter.reset (); + } + } + + /* Return true if the nondebug emitter has been put in place. */ + bool have_started_nondebug_symbol_output () const + { + return m_nondebug_emitter.has_value (); + } + + /* Called before we print every nondebug symbol. If this is the first + nondebug symbol to be printed then it will setup the emitters required + to print nondebug symbols. */ + void maybe_start_nondebug_symbol_output () + { + if (!have_started_nondebug_symbol_output ()) + m_nondebug_emitter.emplace (m_uiout, "nondebug"); + } + + /* Actually output one nondebug symbol, puts a tuple emitter in place + and then outputs the fields for this msymbol. */ + void output_nondebug_symbol (const struct bound_minimal_symbol &msymbol) + { + struct gdbarch *gdbarch = get_objfile_arch (msymbol.objfile); + ui_out_emit_tuple tuple_emitter (m_uiout, NULL); + m_uiout->field_core_addr ("address", gdbarch, + BMSYMBOL_VALUE_ADDRESS (msymbol)); + m_uiout->field_string ("name", MSYMBOL_PRINT_NAME (msymbol.minsym)); + } + + /* Called before we print every debug symbol. If this is the first debug + symbol to be printed then it will setup the top level of emitters + required to print debug symbols. */ + void maybe_start_debug_symbol_output () + { + if (!m_debug_emitter.has_value ()) + m_debug_emitter.emplace (m_uiout, "debug"); + } + + /* Called before we print every debug symbol, S is the symtab for the + symbol to be printed. If S is different to the last symtab we printed + for then we close down the emitters for the last symtab, and create + new emitters for this new symtab. */ + void setup_emitters_for_symtab (symtab *s) + { + if (s != m_last_symtab) + { + /* Reset a possible previous symbol list within a symtab. */ + m_symbols_emitter.reset (); + m_symtab_emitter.reset (); + + /* Start a new symtab and symbol list within the symtab. */ + m_symtab_emitter.emplace (m_uiout, nullptr); + m_uiout->field_string ("filename", + symtab_to_filename_for_display (s)); + m_uiout->field_string ("fullname", symtab_to_fullname (s)); + m_symbols_emitter.emplace (m_uiout, "symbols"); + + /* Record the current symtab. */ + m_last_symtab = s; + } + } + +public: + /* Constructor. */ + mi_symbol_info_emitter (struct ui_out *uiout) + : m_last_symtab (nullptr), + m_uiout (uiout), + m_outer_symbols (uiout, "symbols") + { /* Nothing. */ } + + /* Output P a symbol found by searching for symbols of type KIND. */ + void output (const symbol_search &p, enum search_domain kind) + { + if (p.msymbol.minsym != NULL) + { + /* If this is the first nondebug symbol, and we have previous + outputted a debug symbol then we need to close down all of the + emitters related to printing debug symbols. */ + maybe_finish_debug_output (); + + /* If this is the first nondebug symbol then we need to create the + emitters related to printing nondebug symbols. */ + maybe_start_nondebug_symbol_output (); + + /* We are no safe to emit the nondebug symbol. */ + output_nondebug_symbol (p.msymbol); + } + else + { + /* All debug symbols should appear in the list before all + non-debug symbols. */ + gdb_assert (!have_started_nondebug_symbol_output ()); + + /* If this is the first debug symbol then we need to create the + outer level of emitters related to printing debug symbols. */ + maybe_start_debug_symbol_output (); + + /* Ensure the correct emitters are in place to emit this debug + symbol. */ + setup_emitters_for_symtab (symbol_symtab (p.symbol)); + + /* Emit information for this debug symbol. */ + mi_info_one_symbol_details (kind, p.symbol, p.block); + } + } +}; + +/* 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. All the arguments are used to + initialise a SEARCH_SYMBOLS_SPEC, see symtab.h for a description of + their meaning. */ + +static void +mi_symbol_info (enum search_domain kind, const char *regexp, + const char *t_regexp, bool exclude_minsyms) +{ + /* Must make sure that if we're interrupted, symbols gets freed. */ + search_symbols_spec spec (kind, regexp, t_regexp, exclude_minsyms); + std::vector symbols = spec.search_symbols (); + + mi_symbol_info_emitter emitter (current_uiout); + for (const symbol_search &p : symbols) + { + QUIT; + emitter.output (p, kind); + } +} + +/* 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 (kind, regexp, t_regexp, exclude_minsyms); +} + +/* 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-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 (TYPES_DOMAIN, regexp, nullptr, true); +} + +/* 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); +} + diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 4d1eecd..7744e6c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-11-01 Andrew Burgess + + * 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. + 2019-10-31 Andrew Burgess * gdb.fortran/info-modules.exp: Update expected results, and add 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 0000000..9b6dc73 --- /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 . */ + +/* 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 0000000..c80877d --- /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 . */ + +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 0000000..33fe865 --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-sym-info.exp @@ -0,0 +1,129 @@ +# 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 . + +# 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\",name=${qstr},type=${qstr},description=${qstr}\}" +set type_re "\{(?:line=\"$decimal\",)*name=${qstr}\}" +set sym_list "\\\[${fun_re}(?:,$fun_re)*\\\]" +set type_sym_list "\\\[${type_re}(?:,$type_re)*\\\]" +set symtab_re \ + "\{filename=${qstr},fullname=${qstr},symbols=${sym_list}\}" +set symtab_type_re \ + "\{filename=${qstr},fullname=${qstr},symbols=${type_sym_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" \ + "116\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"39\",name=\"f3\",type=\"int \\(another_int_t\\)\",description=\"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" \ + "117\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"36\",name=\"f4\",type=\"void \\(int \\*\\)\",description=\"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" \ + "118\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"global_f2\",type=\"int\",description=\"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" \ + "119\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"25\",name=\"global_f1\",type=\"float\",description=\"static float global_f1;\"\}\\\]\},\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"19\",name=\"global_f1\",type=\"float\",description=\"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_" \ + "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_"