From patchwork Wed Oct 16 23:28:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 35073 Received: (qmail 99161 invoked by alias); 16 Oct 2019 23:28:27 -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 99086 invoked by uid 89); 16 Oct 2019 23:28:26 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=uiout, 20name X-HELO: mail-wr1-f50.google.com Received: from mail-wr1-f50.google.com (HELO mail-wr1-f50.google.com) (209.85.221.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 16 Oct 2019 23:28:20 +0000 Received: by mail-wr1-f50.google.com with SMTP id r3so168873wrj.6 for ; Wed, 16 Oct 2019 16:28:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=YEJjz+XIn1u3vp+VvIz2uVtxDASzqqx2iGMLngt4Xsw=; b=gDH4gCvdGWO3Dk5Iu2PX35wIKJWQkwQ2ghqmFUqomsFPcoDQoBkF2vJzlQJ3wNU97D WqrKr54M4uVylh2dyexRGPyKBNrBdGkOofnih+JVmsP1hVHBs34wW4NYrUgM1WRR/PkO 3mFz2iRmFMXXW7IDWwOmxA4TD0v2O0qXitNUgurgdPvqPxy9L5cVWBdU2hPe1jmvGAZT vY3j45S2fkl7SkZa3F91KVz/arP4P7dnNsThihW2coq1HtlJzrVlL83t0mNHOK9Wya9b rm9i86EeZOgBzT1emL/+uoyuBD7bPoc1UXUYQWpX031apoYvFfumw2rFRGVdszt4hz/s /ZiQ== Return-Path: Received: from localhost (host86-128-12-122.range86-128.btcentralplus.com. [86.128.12.122]) by smtp.gmail.com with ESMTPSA id l18sm327403wrc.18.2019.10.16.16.28.15 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 16 Oct 2019 16:28:15 -0700 (PDT) From: Andrew Burgess To: gdb-patches Cc: Andrew Burgess Subject: [PATCHv3 6/9] gdb/mi: Add new commands -symbol-info-{functions, variables, types} Date: Thu, 17 Oct 2019 00:28:01 +0100 Message-Id: <2d19cda897073e5dbf709cdaa3d69a13bbde4015.1571268432.git.andrew.burgess@embecosm.com> In-Reply-To: References: In-Reply-To: References: X-IsSubscribed: yes 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_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. Change-Id: Ic2fc6a6750bbce91cdde2344791014e5ef45642d --- gdb/ChangeLog | 15 ++ gdb/NEWS | 4 + gdb/doc/ChangeLog | 6 + gdb/doc/gdb.texinfo | 268 ++++++++++++++++++++++++++++++++++- gdb/mi/mi-cmds.c | 3 + gdb/mi/mi-cmds.h | 3 + gdb/mi/mi-symbol-cmds.c | 224 +++++++++++++++++++++++++++++ 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 | 129 +++++++++++++++++ 11 files changed, 743 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 276e9618afa..81ad7f26bfb 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -332,6 +332,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 c05955cbb68..57bcde19894 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33743,27 +33743,283 @@ @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 + +@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 + +The corresponding @value{GDBN} command is @samp{info functions}. + +@subsubheading Example +@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-function} Command -@findex -symbol-info-function +@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 +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 -@samp{gdb_get_function} in @code{gdbtk}. +The corresponding @value{GDBN} command is @samp{info types}. @subsubheading Example -N.A. +@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 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..c2fd7d30d63 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_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 63142e8e7e9..6b0aa9538f5 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,225 @@ mi_cmd_symbol_list_lines (const char *command, char **argv, int argc) 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 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) +{ + struct ui_out *uiout = current_uiout; + + /* Must make sure that if we're interrupted, symbols gets freed. */ + search_symbols_spec spec (kind, regexp, t_regexp, exclude_minsyms); + std::vector symbols = search_symbols (spec); + + /* 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 debug_func_emitter_outer; + gdb::optional debug_func_emitter_symtab; + gdb::optional debug_func_emitter_symbols; + gdb::optional 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, "symbols"); + + /* Record the current symtab. */ + last_symtab = s; + } + + mi_info_one_symbol_details (kind, sym, p.block); + } + } +} + +/* 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/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 . */ + +/* 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 . */ + +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..33fe8657811 --- /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_"