From patchwork Thu Jul 5 21:37:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philippe Waroquiers X-Patchwork-Id: 28251 Received: (qmail 126929 invoked by alias); 5 Jul 2018 21:37:41 -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 126801 invoked by uid 89); 5 Jul 2018 21:37:40 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=UD:stream, temporarily, regulation, symfile.c X-HELO: mailsec101.isp.belgacom.be Received: from mailsec101.isp.belgacom.be (HELO mailsec101.isp.belgacom.be) (195.238.20.97) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 05 Jul 2018 21:37:35 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skynet.be; i=@skynet.be; q=dns/txt; s=securemail; t=1530826655; x=1562362655; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=sj6jG2AXKZaO42QZhx9M6uAghVn5xPO4SGRM5wXJjz4=; b=GzPr7vXbArTqRtMMINlbnV937NbTaheNdLtWy2RgKjeANQaKw/0QCzQN YCFN7ZfL41lngnXJBxWh+HFEciKK1g==; Received: from 224.41-64-87.adsl-dyn.isp.belgacom.be (HELO md.home) ([87.64.41.224]) by relay.skynet.be with ESMTP/TLS/DHE-RSA-AES128-GCM-SHA256; 05 Jul 2018 23:37:24 +0200 From: Philippe Waroquiers To: gdb-patches@sourceware.org Cc: Philippe Waroquiers Subject: [RFA 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Date: Thu, 5 Jul 2018 23:37:14 +0200 Message-Id: <20180705213717.302-4-philippe.waroquiers@skynet.be> In-Reply-To: <20180705213717.302-1-philippe.waroquiers@skynet.be> References: <20180705213717.302-1-philippe.waroquiers@skynet.be> X-IsSubscribed: yes Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Main changes are: * stack.h: add two regexp args to iterate_over_block_arg_vars and iterate_over_block_local_vars, and update all impacted files/callers. As stack.h now uses a type from gdb_regex.h, all files including stack.h need to include gdb_regex.h. * symtab.h: add a new function bool treg_matches_sym_type_name, that factorises type matching logic. * symbtab.c: add type/name matching logic to 'info functions|variables'. * stack.c : add type/name matching logic to 'info args|locals'. gdb/ChangeLog 2018-07-05 Philippe Waroquiers * linespec.c: Include gdb_exex.h. * mi/mi-cmd-stack.c: Likewise. * python/py-frame.c: Likewise. * python/python.c: Likewise. * skip.c: Likewise. * symfile.c: Likewise. * tracepoint.c: Likewise. * stack.h (iterate_over_block_arg_vars): Add preg and treg arguments. (iterate_over_block_local_vars): Likewise. * stack.c (iterate_over_block_arg_vars): Add preg and treg arguments, and update callers. (iterate_over_block_local_vars): Likewise. (print_frame_local_vars): Add quiet, regexp and t_regexp arguments, and update callers. (print_frame_arg_vars): Likewise. (prepare_reg): New function. (info_locals_command): Extract info print args and use them. (info_args_command): Likewise. (_initialize_stack): Modify on-line help. * symtab.c (treg_matches_sym_type_name): New function. (search_symbols): New arg t_regexp. (symtab_symbol_info): New args quiet, regexp, t_regexp. (info_variables_command): Extract info print args and use them. (info_functions_command): Likewise. (info_types_command): Update call to symtab_symbol_info. (_initialize_symtab): Modify on-line help. * symtab.h (treg_matches_sym_type_name): New function. (search_symbols): New t_regexp arg. --- gdb/linespec.c | 1 + gdb/mi/mi-cmd-stack.c | 1 + gdb/python/py-frame.c | 1 + gdb/python/python.c | 4 +- gdb/skip.c | 1 + gdb/stack.c | 162 ++++++++++++++++++++++++++++++++++------- gdb/stack.h | 4 + gdb/symfile.c | 1 + gdb/symtab.c | 165 ++++++++++++++++++++++++++++++++++++------ gdb/symtab.h | 8 +- gdb/tracepoint.c | 8 +- 11 files changed, 300 insertions(+), 56 deletions(-) diff --git a/gdb/linespec.c b/gdb/linespec.c index 2a4189278e..2503ec77ab 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -42,6 +42,7 @@ #include "cli/cli-utils.h" #include "filenames.h" #include "ada-lang.h" +#include "gdb_regex.h" #include "stack.h" #include "location.h" #include "common/function-view.h" diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 52660bdd49..f109353a34 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -25,6 +25,7 @@ #include "ui-out.h" #include "symtab.h" #include "block.h" +#include "gdb_regex.h" #include "stack.h" #include "dictionary.h" #include "language.h" diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index ec456e9e77..b566149f76 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -22,6 +22,7 @@ #include "block.h" #include "frame.h" #include "symtab.h" +#include "gdb_regex.h" #include "stack.h" #include "value.h" #include "python-internal.h" diff --git a/gdb/python/python.c b/gdb/python/python.c index 20fc674f20..b80c874c47 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -766,11 +766,11 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) { const char **files = symtab_paths.vec.data (); - symbols = search_symbols (regex, FUNCTIONS_DOMAIN, + symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL, symtab_paths.vec.size (), files); } else - symbols = search_symbols (regex, FUNCTIONS_DOMAIN, 0, NULL); + symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL, 0, NULL); /* Count the number of symbols (both symbols and optionally minimal symbols) so we can correctly check the throttle limit. */ diff --git a/gdb/skip.c b/gdb/skip.c index 7a6f2e712b..b7f7b10167 100644 --- a/gdb/skip.c +++ b/gdb/skip.c @@ -24,6 +24,7 @@ #include "gdbcmd.h" #include "command.h" #include "completer.h" +#include "gdb_regex.h" #include "stack.h" #include "cli/cli-utils.h" #include "arch-utils.h" diff --git a/gdb/stack.c b/gdb/stack.c index 13d8cf22b5..ed34b98fa1 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -25,6 +25,7 @@ #include "language.h" #include "frame.h" #include "gdbcmd.h" +#include "gdb_regex.h" #include "gdbcore.h" #include "target.h" #include "source.h" @@ -89,8 +90,10 @@ const char *print_entry_values = print_entry_values_default; /* Prototypes for local functions. */ -static void print_frame_local_vars (struct frame_info *, int, - struct ui_file *); +static void print_frame_local_vars (struct frame_info *frame, + bool quiet, + const char *regexp, const char *t_regexp, + int num_tabs, struct ui_file *stream); static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, @@ -1792,7 +1795,7 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, { struct frame_id frame_id = get_frame_id (fi); - print_frame_local_vars (fi, 1, gdb_stdout); + print_frame_local_vars (fi, false, NULL, NULL, 1, gdb_stdout); /* print_frame_local_vars invalidates FI. */ fi = frame_find_by_id (frame_id); @@ -1866,10 +1869,14 @@ backtrace_command (const char *arg, int from_tty) } /* Iterate over the local variables of a block B, calling CB with - CB_DATA. */ + CB_DATA. + Only local variables with name/type matching PREG/TREG are iterated + on. */ static void iterate_over_block_locals (const struct block *b, + const gdb::optional &preg, + const gdb::optional &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data) { @@ -1889,6 +1896,13 @@ iterate_over_block_locals (const struct block *b, break; if (SYMBOL_DOMAIN (sym) == COMMON_BLOCK_DOMAIN) break; + if (preg + && preg->exec (SYMBOL_NATURAL_NAME (sym), 0, + NULL, 0) != 0) + break; + if (treg + && !treg_matches_sym_type_name (*treg, sym)) + break; (*cb) (SYMBOL_PRINT_NAME (sym), sym, cb_data); break; @@ -1950,16 +1964,20 @@ print_block_frame_labels (struct gdbarch *gdbarch, struct block *b, #endif /* Iterate over all the local variables in block B, including all its - superblocks, stopping when the top-level block is reached. */ + superblocks, stopping when the top-level block is reached. + Only local variables with name/type matching PREG/TREG are iterated + on. */ void iterate_over_block_local_vars (const struct block *block, + const gdb::optional &preg, + const gdb::optional &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data) { while (block) { - iterate_over_block_locals (block, cb, cb_data); + iterate_over_block_locals (block, preg, treg, cb, cb_data); /* After handling the function's top-level block, stop. Don't continue to its superblock, the block of per-file symbols. */ @@ -2006,30 +2024,57 @@ do_print_variable_and_value (const char *print_name, p->values_printed = 1; } +/* Prepares the regular expression REG from REGEXP. + If REGEXP is NULL, it results in an empty regular expression. */ +static void +prepare_reg (const char *regexp, gdb::optional ®) +{ + if (regexp != NULL) + { + int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off + ? REG_ICASE : 0); + reg.emplace (regexp, cflags, _("Invalid regexp")); + } + else + reg.reset (); +} + /* Print all variables from the innermost up to the function block of FRAME. Print them with values to STREAM indented by NUM_TABS. + If REGEXP is not NULL, only print local variables whose name + matches REGEXP. + If T_REGEXP is not NULL, only print local variables whose type + matches T_REGEXP. + If no local variables have been printed and !QUIET, prints a message + explaining why no local variables could be printed. This function will invalidate FRAME. */ static void -print_frame_local_vars (struct frame_info *frame, int num_tabs, - struct ui_file *stream) +print_frame_local_vars (struct frame_info *frame, + bool quiet, + const char *regexp, const char *t_regexp, + int num_tabs, struct ui_file *stream) { struct print_variable_and_value_data cb_data; const struct block *block; CORE_ADDR pc; + gdb::optional preg; + gdb::optional treg; if (!get_frame_pc_if_available (frame, &pc)) { - fprintf_filtered (stream, - _("PC unavailable, cannot determine locals.\n")); + if (!quiet) + fprintf_filtered (stream, + _("PC unavailable, cannot determine locals.\n")); return; } block = get_frame_block (frame, 0); if (block == 0) { - fprintf_filtered (stream, "No symbol table info available.\n"); + if (!quiet) + fprintf_filtered (stream, "No symbol table info available.\n"); return; } @@ -2038,31 +2083,53 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs, cb_data.stream = stream; cb_data.values_printed = 0; + prepare_reg (regexp, preg); + prepare_reg (t_regexp, treg); + /* Temporarily change the selected frame to the given FRAME. This allows routines that rely on the selected frame instead of being given a frame as parameter to use the correct frame. */ scoped_restore_selected_frame restore_selected_frame; select_frame (frame); - iterate_over_block_local_vars (block, + iterate_over_block_local_vars (block, preg, treg, do_print_variable_and_value, &cb_data); - if (!cb_data.values_printed) - fprintf_filtered (stream, _("No locals.\n")); + if (!cb_data.values_printed && !quiet) + { + if (regexp == NULL && t_regexp == NULL) + fprintf_filtered (stream, _("No locals.\n")); + else + fprintf_filtered (stream, _("No matching locals.\n")); + } } void info_locals_command (const char *args, int from_tty) { + std::string regexp; + std::string t_regexp; + bool quiet; + + extract_info_print_args ("info locals", &args, &quiet, ®exp, &t_regexp); print_frame_local_vars (get_selected_frame (_("No frame selected.")), + quiet, + regexp.empty () ? NULL : regexp.c_str (), + t_regexp.empty () ? NULL : t_regexp.c_str (), 0, gdb_stdout); } -/* Iterate over all the argument variables in block B. */ +/* Iterate over all the argument variables in block B. + If PREG has a value, only prints the argument variables + with name matching PREG. + If TREG has a value, only prints the argument variables + with type matching TREG. */ void iterate_over_block_arg_vars (const struct block *b, + const gdb::optional &preg, + const gdb::optional &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data) { @@ -2072,7 +2139,12 @@ iterate_over_block_arg_vars (const struct block *b, ALL_BLOCK_SYMBOLS (b, iter, sym) { /* Don't worry about things which aren't arguments. */ - if (SYMBOL_IS_ARGUMENT (sym)) + if (SYMBOL_IS_ARGUMENT (sym) + && (!preg + || preg->exec (SYMBOL_NATURAL_NAME (sym), 0, + NULL, 0) == 0) + && (!treg + || treg_matches_sym_type_name (*treg, sym))) { /* We have to look up the symbol because arguments can have two entries (one a parameter, one a local) and the one we @@ -2084,7 +2156,6 @@ iterate_over_block_arg_vars (const struct block *b, symbol is double and the type of the LOC_LOCAL symbol is float). There are also LOC_ARG/LOC_REGISTER pairs which are not combined in symbol-reading. */ - sym2 = lookup_symbol_search_name (SYMBOL_SEARCH_NAME (sym), b, VAR_DOMAIN).symbol; (*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data); @@ -2094,26 +2165,40 @@ iterate_over_block_arg_vars (const struct block *b, /* Print all argument variables of the function of FRAME. Print them with values to STREAM. + If REGEXP is not NULL, only print argument variables whose name + matches REGEXP. + If T_REGEXP is not NULL, only print argument variables whose type + matches T_REGEXP. + If no argument variables have been printed and !QUIET, prints a message + explaining why no argument variables could be printed. This function will invalidate FRAME. */ static void -print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream) +print_frame_arg_vars (struct frame_info *frame, + bool quiet, + const char *regexp, const char *t_regexp, + struct ui_file *stream) { struct print_variable_and_value_data cb_data; struct symbol *func; CORE_ADDR pc; + gdb::optional preg; + gdb::optional treg; if (!get_frame_pc_if_available (frame, &pc)) { - fprintf_filtered (stream, _("PC unavailable, cannot determine args.\n")); + if (!quiet) + fprintf_filtered (stream, + _("PC unavailable, cannot determine args.\n")); return; } func = get_frame_function (frame); if (func == NULL) { - fprintf_filtered (stream, _("No symbol table info available.\n")); + if (!quiet) + fprintf_filtered (stream, _("No symbol table info available.\n")); return; } @@ -2122,20 +2207,37 @@ print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream) cb_data.stream = stream; cb_data.values_printed = 0; + prepare_reg (regexp, preg); + prepare_reg (t_regexp, treg); + iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func), + preg, treg, do_print_variable_and_value, &cb_data); /* do_print_variable_and_value invalidates FRAME. */ frame = NULL; - if (!cb_data.values_printed) - fprintf_filtered (stream, _("No arguments.\n")); + if (!cb_data.values_printed && !quiet) + { + if (regexp == NULL && t_regexp == NULL) + fprintf_filtered (stream, _("No arguments.\n")); + else + fprintf_filtered (stream, _("No matching arguments.\n")); + } } void -info_args_command (const char *ignore, int from_tty) +info_args_command (const char *args, int from_tty) { + std::string regexp; + std::string t_regexp; + bool quiet; + + extract_info_print_args ("info args", &args, &quiet, ®exp, &t_regexp); print_frame_arg_vars (get_selected_frame (_("No frame selected.")), + quiet, + regexp.empty () ? NULL : regexp.c_str (), + t_regexp.empty () ? NULL : t_regexp.c_str (), gdb_stdout); } @@ -2549,10 +2651,16 @@ on this backtrace.")); add_info ("frame", info_frame_command, _("All about selected stack frame, or frame at ADDR.")); add_info_alias ("f", "frame", 1); - add_info ("locals", info_locals_command, - _("Local variables of current stack frame.")); - add_info ("args", info_args_command, - _("Argument variables of current stack frame.")); + add_info ("locals", info_locals_command, _("\ +All local variables of current stack frame or those matching REGEXPs.\n\ +Usage: info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ +Prints the local variables of the current stack frame.\n" +INFO_PRINT_ARGS_HELP ("local variables"))); + add_info ("args", info_args_command, _("\ +All argument variables of current stack frame or those matching REGEXPs.\n\ +Usage: info args [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ +Prints the argument variables of the current stack frame.\n" +INFO_PRINT_ARGS_HELP ("argument variables"))); if (dbx_commands) add_com ("func", class_stack, func_command, _("\ diff --git a/gdb/stack.h b/gdb/stack.h index ca190efa9c..c6924d5237 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -31,10 +31,14 @@ typedef void (*iterate_over_block_arg_local_vars_cb) (const char *print_name, void *cb_data); void iterate_over_block_arg_vars (const struct block *block, + const gdb::optional &preg, + const gdb::optional &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data); void iterate_over_block_local_vars (const struct block *block, + const gdb::optional &preg, + const gdb::optional &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data); diff --git a/gdb/symfile.c b/gdb/symfile.c index 48eca5cc0e..cf200ec164 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -53,6 +53,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "gdb_regex.h" #include "stack.h" #include "gdb_bfd.h" #include "cli/cli-utils.h" diff --git a/gdb/symtab.c b/gdb/symtab.c index d8a7a16e07..e998597135 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -43,6 +43,7 @@ #include "cli/cli-utils.h" #include "fnmatch.h" #include "hashtab.h" +#include "typeprint.h" #include "gdb_obstack.h" #include "block.h" @@ -4265,6 +4266,51 @@ symbol_search::compare_search_syms (const symbol_search &sym_a, SYMBOL_PRINT_NAME (sym_b.symbol)); } +/* Returns true if the type_name of symbol_type of SYM matches TREG. + If SYM has no symbol_type or symbol_name, returns false. */ + +bool +treg_matches_sym_type_name (const compiled_regex &treg, + const struct symbol *sym) +{ + struct type *sym_type; + const char *sym_type_name; + string_file printed_sym_type_name; + + if (symbol_lookup_debug > 1) + { + fprintf_unfiltered (gdb_stdlog, + "treg_matches_sym_type_name\n sym %s\n", + SYMBOL_NATURAL_NAME (sym)); + } + + sym_type = SYMBOL_TYPE (sym); + if (sym_type == NULL) + return false; + + if (language_mode == language_mode_auto) + language_def (SYMBOL_LANGUAGE (sym))->la_print_type + (sym_type, "", &printed_sym_type_name, + -1, 0, &default_ptype_flags); + else + LA_PRINT_TYPE (sym_type, "", &printed_sym_type_name, + -1, 0, &default_ptype_flags); + + if (symbol_lookup_debug > 1) + { + fprintf_unfiltered (gdb_stdlog, + " sym_type_name %s\n", + printed_sym_type_name.c_str ()); + } + + + if (printed_sym_type_name.empty ()) + return false; + + return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0; +} + + /* Sort the symbols in RESULT and remove duplicates. */ static void @@ -4280,7 +4326,9 @@ sort_search_symbols_remove_dups (std::vector *result) Only symbols of KIND are searched: VARIABLES_DOMAIN - search all symbols, excluding functions, type names, - and constants (enums) + and constants (enums). + if T_REGEXP is not NULL, only returns var that have + a type matching regular expression T_REGEXP. FUNCTIONS_DOMAIN - search all functions TYPES_DOMAIN - search all type names ALL_DOMAIN - an internal error for this function @@ -4291,6 +4339,7 @@ sort_search_symbols_remove_dups (std::vector *result) std::vector search_symbols (const char *regexp, enum search_domain kind, + const char *t_regexp, int nfiles, const char *files[]) { struct compunit_symtab *cust; @@ -4316,6 +4365,7 @@ search_symbols (const char *regexp, enum search_domain kind, enum minimal_symbol_type ourtype4; std::vector result; gdb::optional preg; + gdb::optional treg; gdb_assert (kind <= TYPES_DOMAIN); @@ -4365,6 +4415,13 @@ search_symbols (const char *regexp, enum search_domain kind, preg.emplace (regexp, cflags, _("Invalid regexp")); } + if (t_regexp != NULL) + { + int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off + ? REG_ICASE : 0); + treg.emplace (t_regexp, cflags, _("Invalid regexp")); + } + /* Search through the partial symtabs *first* for all symbols matching the regexp. That way we don't have to reproduce all of the machinery below. */ @@ -4463,9 +4520,13 @@ search_symbols (const char *regexp, enum search_domain kind, We only want to skip enums here. */ && !(SYMBOL_CLASS (sym) == LOC_CONST && (TYPE_CODE (SYMBOL_TYPE (sym)) - == TYPE_CODE_ENUM))) - || (kind == FUNCTIONS_DOMAIN - && SYMBOL_CLASS (sym) == LOC_BLOCK) + == TYPE_CODE_ENUM)) + && (!treg + || treg_matches_sym_type_name (*treg, sym))) + || (kind == FUNCTIONS_DOMAIN + && SYMBOL_CLASS (sym) == LOC_BLOCK + && (!treg + || treg_matches_sym_type_name (*treg, sym))) || (kind == TYPES_DOMAIN && SYMBOL_CLASS (sym) == LOC_TYPEDEF)))) { @@ -4496,8 +4557,12 @@ search_symbols (const char *regexp, enum search_domain kind, || MSYMBOL_TYPE (msymbol) == ourtype3 || MSYMBOL_TYPE (msymbol) == ourtype4) { - if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0, - NULL, 0) == 0) + /* If the user wants to see var matching a type regexp, + then never give a minimal symbol. */ + if (kind != VARIABLES_DOMAIN + && !treg /* a minimal symbol has never a type ???? */ + && (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0, + NULL, 0) == 0)) { /* For functions we can do a quick check of whether the symbol might be found via find_pc_symtab. */ @@ -4598,7 +4663,9 @@ print_msymbol_info (struct bound_minimal_symbol msymbol) matches. */ static void -symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty) +symtab_symbol_info (bool quiet, + const char *regexp, enum search_domain kind, + const char *t_regexp, int from_tty) { static const char * const classnames[] = {"variable", "function", "type"}; @@ -4608,13 +4675,33 @@ symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty) gdb_assert (kind <= TYPES_DOMAIN); /* Must make sure that if we're interrupted, symbols gets freed. */ - std::vector symbols = search_symbols (regexp, kind, 0, NULL); + std::vector symbols = search_symbols (regexp, kind, + t_regexp, 0, NULL); - if (regexp != NULL) - printf_filtered (_("All %ss matching regular expression \"%s\":\n"), - classnames[kind], regexp); - else - printf_filtered (_("All defined %ss:\n"), classnames[kind]); + if (!quiet) + { + if (regexp != NULL) + { + if (t_regexp != NULL) + printf_filtered + (_("All %ss matching regular expression \"%s\"" + " with type matching regulation expression \"%s\" :\n"), + classnames[kind], regexp, t_regexp); + else + printf_filtered (_("All %ss matching regular expression \"%s\":\n"), + classnames[kind], regexp); + } + else + { + if (t_regexp != NULL) + printf_filtered + (_("All defined %ss" + " with type matching regulation expression \"%s\" :\n"), + classnames[kind], t_regexp); + else + printf_filtered (_("All defined %ss:\n"), classnames[kind]); + } + } for (const symbol_search &p : symbols) { @@ -4624,7 +4711,8 @@ symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty) { if (first) { - printf_filtered (_("\nNon-debugging symbols:\n")); + if (!quiet) + printf_filtered (_("\nNon-debugging symbols:\n")); first = 0; } print_msymbol_info (p.msymbol); @@ -4642,22 +4730,41 @@ symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty) } static void -info_variables_command (const char *regexp, int from_tty) +info_variables_command (const char *args, int from_tty) { - symtab_symbol_info (regexp, VARIABLES_DOMAIN, from_tty); + std::string regexp; + std::string t_regexp; + bool quiet; + + extract_info_print_args ("info variables", &args, &quiet, ®exp, &t_regexp); + symtab_symbol_info (quiet, + regexp.empty () ? NULL : regexp.c_str (), + VARIABLES_DOMAIN, + t_regexp.empty () ? NULL : t_regexp.c_str (), + from_tty); } + static void -info_functions_command (const char *regexp, int from_tty) +info_functions_command (const char *args, int from_tty) { - symtab_symbol_info (regexp, FUNCTIONS_DOMAIN, from_tty); + std::string regexp; + std::string t_regexp; + bool quiet; + + extract_info_print_args ("info functions", &args, &quiet, ®exp, &t_regexp); + symtab_symbol_info (quiet, + regexp.empty () ? NULL : regexp.c_str (), + FUNCTIONS_DOMAIN, + t_regexp.empty () ? NULL : t_regexp.c_str (), + from_tty); } static void info_types_command (const char *regexp, int from_tty) { - symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty); + symtab_symbol_info (false, regexp, TYPES_DOMAIN, NULL, from_tty); } /* Breakpoint all functions matching regular expression. */ @@ -4700,6 +4807,7 @@ rbreak_command (const char *regexp, int from_tty) std::vector symbols = search_symbols (regexp, FUNCTIONS_DOMAIN, + NULL, nfiles, files); scoped_rbreak_breakpoints finalize; @@ -5902,13 +6010,22 @@ _initialize_symtab (void) = register_program_space_data_with_cleanup (NULL, symbol_cache_cleanup); add_info ("variables", info_variables_command, _("\ -All global and static variable names, or those matching REGEXP.")); +All global and static variable names or those matching REGEXPs.\n\ +Usage: info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ +Prints the global and static variables.\n" +INFO_PRINT_ARGS_HELP ("global and static variables"))); if (dbx_commands) add_com ("whereis", class_info, info_variables_command, _("\ -All global and static variable names, or those matching REGEXP.")); - - add_info ("functions", info_functions_command, - _("All function names, or those matching REGEXP.")); +All global and static variable names, or those matching REGEXPs.\n\ +Usage: whereis [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ +Prints the global and static variables.\n" +INFO_PRINT_ARGS_HELP ("global and static variables"))); + + add_info ("functions", info_functions_command, _("\ +All function names or those matching REGEXPs.\n\ +Usage: info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ +Prints the functions.\n" +INFO_PRINT_ARGS_HELP ("functions"))); /* FIXME: This command has at least the following problems: 1. It prints builtin types (in a very strange and confusing fashion). diff --git a/gdb/symtab.h b/gdb/symtab.h index 0b155d0659..b7ead5b5c4 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -25,6 +25,7 @@ #include #include "gdb_vecs.h" #include "gdbtypes.h" +#include "gdb_regex.h" #include "common/enum-flags.h" #include "common/function-view.h" #include "common/gdb_optional.h" @@ -2012,8 +2013,13 @@ private: }; extern std::vector search_symbols (const char *, - enum search_domain, int, + enum search_domain, + const char *, + int, const char **); +extern bool +treg_matches_sym_type_name (const compiled_regex &treg, + const struct symbol *sym); /* The name of the ``main'' function. FIXME: cagney/2001-03-20: Can't make main_name() const since some diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index ab80b10ea1..b59487f3cb 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -43,6 +43,7 @@ #include "objfiles.h" #include "filenames.h" #include "gdbthread.h" +#include "gdb_regex.h" #include "stack.h" #include "remote.h" #include "source.h" @@ -1038,6 +1039,7 @@ collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc, { const struct block *block; struct add_local_symbols_data cb_data; + const gdb::optional nullreg; cb_data.collect = this; cb_data.gdbarch = gdbarch; @@ -1057,7 +1059,8 @@ collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc, return; } - iterate_over_block_local_vars (block, do_collect_symbol, &cb_data); + iterate_over_block_local_vars (block, nullreg, nullreg, + do_collect_symbol, &cb_data); if (cb_data.count == 0) warning (_("No locals found in scope.")); } @@ -1071,7 +1074,8 @@ collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc, return; } - iterate_over_block_arg_vars (block, do_collect_symbol, &cb_data); + iterate_over_block_arg_vars (block, nullreg, nullreg, + do_collect_symbol, &cb_data); if (cb_data.count == 0) warning (_("No args found in scope.")); }