* [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]
@ 2018-08-26 16:54 Philippe Waroquiers
2018-08-26 16:54 ` [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers
` (7 more replies)
0 siblings, 8 replies; 19+ messages in thread
From: Philippe Waroquiers @ 2018-08-26 16:54 UTC (permalink / raw)
To: gdb-patches
[RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]
This is a follow up to the first RFA.
The documentation parts were already reviewed by Eli, other parts
were not reviewed yet.
Compared to the first RFA, the changes are a rebase to the last trunk version,
the removal of an unused local variable, and some updates to the new
info_qt.exp test to ensure unicity of test names.
Thanks.
This patch series adds flags and/or arguments
[-q] [-t TYPEREGEXP] [NAMEREGEXP] to the commands
info [args|functions|locals|variables]
The additional arguments allow to more precisely specify what to print.
As these new features can usefully be combined with frame apply and thread
apply, the documentation gives examples combining the above
and the 'thread apply' and 'frame apply' commands.
Some examples:
* print functions returning an int:
info functions -t '^int ('
* print local variables having pthread_t type
info locals -t pthread_t
* print global variables having type 'struct addrinfo'
info var -t 'struct addrinfo'
* print args that are likely file descriptors
info arg -t int .*fd.*
Below examples are combined with the 'thread/frame apply' commands:
* Assuming lock_something_t is an RAII type, show all locks:
thread apply all -s frame apply all -s info locals -q -t lock_something_t
or shorter equivalent:
tfaas i lo -q -t lock_something_t
* show frames and args having an arg with type matchin std::.*map
so likely std::map or std::unordered_map
frame apply all -s info args -q std::.*map
The code, documentation, NEWS, test and ChangeLog are (supposed to be) complete.
The changes in RFA v2 are:
* Removal of an unused local variable.
* Updates to the test info_qt.exp, to ensure no duplicate in test names.
Compared to the RFC, the changes in RFA v1 are:
* All comments of Eli on the documentation have been handled.
* ChangeLog entries added in commit messages
* Test added.
^ permalink raw reply [flat|nested] 19+ messages in thread* [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers @ 2018-08-26 16:54 ` Philippe Waroquiers 2018-08-26 18:21 ` Eli Zaretskii 2018-08-26 16:54 ` [RFAv2 4/6] Document changes " Philippe Waroquiers ` (6 subsequent siblings) 7 siblings, 1 reply; 19+ messages in thread From: Philippe Waroquiers @ 2018-08-26 16:54 UTC (permalink / raw) To: gdb-patches; +Cc: Philippe Waroquiers Announce changes in NEWS to info [args|functions|locals|variables] gdb/ChangeLog 2018-08-26 Philippe Waroquiers <philippe.waroquiers@skynet.be> * NEWS: Mention changes to 'info [args|functions|locals|variables]' --- gdb/NEWS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gdb/NEWS b/gdb/NEWS index a7a3674375..d2ff55db2c 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -36,6 +36,15 @@ maint show dwarf unwinders * Changed commands +info args [-q] [-t TYPEREGEXP] [NAMEREGEXP] +info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP] +info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP] +info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] + These commands can now print only the searched entities + matching the provided regexp(s), giving a condition + on the entity names or entity types. The flag -q + disables printing headers or informations messages. + thread apply [all | COUNT | -COUNT] [FLAG]... COMMAND The 'thread apply' command accepts new FLAG arguments. FLAG arguments allow to control what output to produce and how to handle -- 2.18.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] 2018-08-26 16:54 ` [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers @ 2018-08-26 18:21 ` Eli Zaretskii 2018-08-27 4:39 ` Philippe Waroquiers 0 siblings, 1 reply; 19+ messages in thread From: Eli Zaretskii @ 2018-08-26 18:21 UTC (permalink / raw) To: Philippe Waroquiers; +Cc: gdb-patches > From: Philippe Waroquiers <philippe.waroquiers@skynet.be> > Cc: Philippe Waroquiers <philippe.waroquiers@skynet.be> > Date: Sun, 26 Aug 2018 18:53:58 +0200 > > +info args [-q] [-t TYPEREGEXP] [NAMEREGEXP] > +info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP] > +info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP] > +info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] > + These commands can now print only the searched entities > + matching the provided regexp(s), giving a condition > + on the entity names or entity types. I'd lose "searched". How about the following? These commands can now print only the entities whose names and/or types match the specified regular expressions. > + The flag -q > + disables printing headers or informations messages. "informative messages", I guess? Thanks. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] 2018-08-26 18:21 ` Eli Zaretskii @ 2018-08-27 4:39 ` Philippe Waroquiers 2018-08-27 14:59 ` Eli Zaretskii 0 siblings, 1 reply; 19+ messages in thread From: Philippe Waroquiers @ 2018-08-27 4:39 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Thanks for the review, I will do the updates as suggested in this and the other mail. One question below. Philippe On Sun, 2018-08-26 at 21:21 +0300, Eli Zaretskii wrote: > > From: Philippe Waroquiers <philippe.waroquiers@skynet.be> > > Cc: Philippe Waroquiers <philippe.waroquiers@skynet.be> > > Date: Sun, 26 Aug 2018 18:53:58 +0200 > > > > +info args [-q] [-t TYPEREGEXP] [NAMEREGEXP] > > +info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP] > > +info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP] > > +info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] > > + These commands can now print only the searched entities > > + matching the provided regexp(s), giving a condition > > + on the entity names or entity types. > > I'd lose "searched". How about the following? > > These commands can now print only the entities whose names and/or > types match the specified regular expressions. > > > + The flag -q > > + disables printing headers or informations messages. > > "informative messages", I guess? These are the messages explaining why no entity was printed, e.g (gdb) info arg -t xxxx yyyy No matching arguments. (gdb) info arg -q -t xxxx yyyy (gdb) (gdb) info arg -t xxxx yyyy   No symbol table info available. (gdb) info arg -q -t xxxx yyyy (gdb) So, what about (like in the texinfo doc): The flag -q disables printing headers or messages explaining why no entities have been printed. ? Philippe ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] 2018-08-27 4:39 ` Philippe Waroquiers @ 2018-08-27 14:59 ` Eli Zaretskii 0 siblings, 0 replies; 19+ messages in thread From: Eli Zaretskii @ 2018-08-27 14:59 UTC (permalink / raw) To: Philippe Waroquiers; +Cc: gdb-patches > From: Philippe Waroquiers <philippe.waroquiers@skynet.be> > Cc: gdb-patches@sourceware.org > Date: Mon, 27 Aug 2018 06:39:20 +0200 > > > > + disables printing headers or informations messages. > > > > "informative messages", I guess? > These are the messages explaining why no entity was printed, e.g > (gdb) info arg -t xxxx yyyy > No matching arguments. > (gdb) info arg -q -t xxxx yyyy > (gdb) > > (gdb) info arg -t xxxx yyyy   > No symbol table info available. > (gdb) info arg -q -t xxxx yyyy > (gdb) > > So, what about (like in the texinfo doc): The flag -q > disables printing headers or messages explaining why no entities > have been printed. > ? Fine with me, thanks. ^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFAv2 4/6] Document changes to info [args|functions|locals|variables] 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers @ 2018-08-26 16:54 ` Philippe Waroquiers 2018-08-26 18:19 ` Eli Zaretskii 2018-08-26 16:54 ` [RFAv2 2/6] Make struct type_print_options default_ptype_flags non static Philippe Waroquiers ` (5 subsequent siblings) 7 siblings, 1 reply; 19+ messages in thread From: Philippe Waroquiers @ 2018-08-26 16:54 UTC (permalink / raw) To: gdb-patches; +Cc: Philippe Waroquiers Document changes to info [args|functions|locals|variables] gdb/doc/ChangeLog 2018-08-26 Philippe Waroquiers <philippe.waroquiers@skynet.be> * gdb.texinfo (Information About a Frame): Document changes to 'info args' and 'info locals'. (Examining the Symbol Table): Document changes to 'info functions' and 'info variables'. --- gdb/doc/gdb.texinfo | 121 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 12 deletions(-) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 5068c0ac81..a5f0b7506b 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -7759,15 +7759,73 @@ architectures) that you specify in the @code{frame} command. @xref{Selection, ,Selecting a Frame}. @kindex info args -@item info args +@item info args [-q] Print the arguments of the selected frame, each on a separate line. +The optional flag @samp{-q}, which stands for @samp{quiet}, disables +printing header information and messages explaining why no argument +have been printed. + +@item info args [-q] [-t @var{type_regexp}] [@var{regexp}] +Like @kbd{info args}, but only print the arguments selected +with the provided regexp(s). + +If @var{regexp} is provided, print only the arguments whose names +contain a match for regular expression @var{regexp}. + +If @var{type_regexp} is provided, print only the arguments whose +types contain a match for regular expression @var{type_regexp}. +The matching is done with the argument type as printed by the +@code{whatis} command. +If @var{type_regexp} contains space(s), it should be enclosed in single +quote characters. + +If both @var{regexp} and @var{type_regexp} are provided, an argument +is printed only if it matches the two regexps. + @item info locals -@kindex info locals +@kindex info locals [-q] Print the local variables of the selected frame, each on a separate line. These are all variables (declared either static or automatic) accessible at the point of execution of the selected frame. +The optional flag @samp{-q}, which stands for @samp{quiet}, disables +printing header information and messages explaining why no local variables +have been printed. + +@item info locals [-q] [-t @var{type_regexp}] [@var{regexp}] +Like @kbd{info locals}, but only print the local variables selected +with the provided regexp(s). + +If @var{regexp} is provided, print only the local variables whose names +contain a match for regular expression @var{regexp}. + +If @var{type_regexp} is provided, print only the local variables whose +types contain a match for regular expression @var{type_regexp}. +The matching is done with the local variable type as printed by the +@code{whatis} command. +If @var{type_regexp} contains space(s), it should be enclosed in single +quote characters. + +If both @var{regexp} and @var{type_regexp} are provided, a local variable +is printed only if it matches the two regexps. + +The command @kbd{info locals -q -t @var{type_regexp}} can usefully be +combined with the commands @kbd{frame apply} and @kbd{thread apply}. +For example, your program might use Resource Acquisition Is +Initialization types (RAII) such as @code{lock_something_t} : each +local variable of type @code{lock_something_t} automatically places a +lock that is destroyed when the variable goes out of scope. You can +then list all acquired locks in your program by doing +@smallexample +thread apply all -s frame apply all -s info locals -q -t lock_something_t +@end smallexample +@noindent +or the equivalent shorter form +@smallexample +tfaas i lo -q -t lock_something_t +@end smallexample + @end table @node Frame Apply @@ -17849,32 +17907,71 @@ debugging information, organized into two lists: files whose symbols have already been read, and files whose symbols will be read when needed. @kindex info functions -@item info functions +@item info functions [-q] Print the names and data types of all defined functions. Similarly to @samp{info types}, this command groups its output by source files and annotates each function definition with its source line number. -@item info functions @var{regexp} -Like @samp{info functions}, but only print the names and data types of -functions whose names contain a match for regular expression -@var{regexp}. Thus, @samp{info fun step} finds all functions whose +The optional flag @samp{-q}, which stands for @samp{quiet}, disables +printing header information and messages explaining why no functions +have been printed. + +@item info functions [-q] [-t @var{type_regexp}] [@var{regexp}] +Like @samp{info functions}, but only print the names and data types +of the functions selected with the provided regexp(s). + +If @var{regexp} is provided, print only the functions whose names +contain a match for regular expression @var{regexp}. +Thus, @samp{info fun step} finds all functions whose names include @code{step}; @samp{info fun ^step} finds those whose names start with @code{step}. If a function name contains characters that conflict with the regular expression language (e.g.@: @samp{operator*()}), they may be quoted with a backslash. +If @var{type_regexp} is provided, print only the functions whose +types contain a match for regular expression @var{type_regexp}. +The matching is done with the function type as printed by the +@code{whatis} command. +If @var{type_regexp} contains space(s), it should be enclosed in single +quote characters. +Thus, @samp{info fun -t '^int ('} finds the functions that return +an integer; @samp{info fun -t '(.*int.*'} finds the functions that +have an argument type containing int; @samp{info fun -t '^int (' ^step} +finds the functions whose names start with @code{step} and that are returning +an int. + +If both @var{regexp} and @var{type_regexp} are provided, a function +is printed only if it matches the two regexps. + + @kindex info variables -@item info variables +@item info variables [-q] Print the names and data types of all variables that are defined outside of functions (i.e.@: excluding local variables). The printed variables are grouped by source files and annotated with their respective source line numbers. -@item info variables @var{regexp} -Like @kbd{info variables}, but only print the names and data types of -non-local variables whose names contain a match for regular expression -@var{regexp}. +The optional flag @samp{-q}, which stands for @samp{quiet}, disables +printing header information and messages explaining why no variables +have been printed. + +@item info variables [-q] [-t @var{type_regexp}] [@var{regexp}] +Like @kbd{info variables}, but only print the variables selected +with the provided regexp(s). + +If @var{regexp} is provided, print only the variables whose names +contain a match for regular expression @var{regexp}. + +If @var{type_regexp} is provided, print only the variables whose +types contain a match for regular expression @var{type_regexp}. +The matching is done with the variable type as printed by the +@code{whatis} command. +If @var{type_regexp} contains space(s), it should be enclosed in single +quote characters. + +If both @var{regexp} and @var{type_regexp} are provided, an argument +is printed only if it matches the two regexps. @kindex info classes @cindex Objective-C, classes and selectors -- 2.18.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 4/6] Document changes to info [args|functions|locals|variables] 2018-08-26 16:54 ` [RFAv2 4/6] Document changes " Philippe Waroquiers @ 2018-08-26 18:19 ` Eli Zaretskii 0 siblings, 0 replies; 19+ messages in thread From: Eli Zaretskii @ 2018-08-26 18:19 UTC (permalink / raw) To: Philippe Waroquiers; +Cc: gdb-patches > From: Philippe Waroquiers <philippe.waroquiers@skynet.be> > Cc: Philippe Waroquiers <philippe.waroquiers@skynet.be> > Date: Sun, 26 Aug 2018 18:53:57 +0200 > > Document changes to info [args|functions|locals|variables] > > gdb/doc/ChangeLog > 2018-08-26 Philippe Waroquiers <philippe.waroquiers@skynet.be> > > * gdb.texinfo (Information About a Frame): Document changes > to 'info args' and 'info locals'. > (Examining the Symbol Table): Document changes to 'info functions' > and 'info variables'. Thanks. I have one minor comment: > +If @var{type_regexp} is provided, print only the arguments whose > +types contain a match for regular expression @var{type_regexp}. > +The matching is done with the argument type as printed by the > +@code{whatis} command. I'd rephrase these two sentences as one, and while at that lose one instance of passive tense: If @var{type_regexp} is provided, print only the arguments whose types, as printed by the @code{whatis} command, contain a match for regular expression @var{type_regexp}. > +Initialization types (RAII) such as @code{lock_something_t} : each ^ That blank is redundant. OK with this fixed. ^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFAv2 2/6] Make struct type_print_options default_ptype_flags non static. 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 4/6] Document changes " Philippe Waroquiers @ 2018-08-26 16:54 ` Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 6/6] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers ` (4 subsequent siblings) 7 siblings, 0 replies; 19+ messages in thread From: Philippe Waroquiers @ 2018-08-26 16:54 UTC (permalink / raw) To: gdb-patches; +Cc: Philippe Waroquiers Make struct type_print_options default_ptype_flags non static, as this will be needed in the type matching logic of info [args|functions|locals|variables], to ensure the type matching uses the same setting as the whatis command. gdb/ChangeLog 2018-08-26 Philippe Waroquiers <philippe.waroquiers@skynet.be> * typeprint.h (default_ptype_flags): New extern. * typeprint.c (default_ptype_flags): Make non-static. --- gdb/typeprint.c | 5 +++-- gdb/typeprint.h | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 7a0b7627ed..20925b7dcc 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -49,9 +49,10 @@ const struct type_print_options type_print_raw_options = NULL /* global_printers */ }; -/* The default flags for 'ptype' and 'whatis'. */ -static struct type_print_options default_ptype_flags = +/* See typeprint.h. */ + +struct type_print_options default_ptype_flags = { 0, /* raw */ 1, /* print_methods */ diff --git a/gdb/typeprint.h b/gdb/typeprint.h index edd8c396c8..e098782cf4 100644 --- a/gdb/typeprint.h +++ b/gdb/typeprint.h @@ -105,6 +105,10 @@ struct type_print_options extern const struct type_print_options type_print_raw_options; +/* The default flags for 'ptype' and 'whatis'. */ + +extern struct type_print_options default_ptype_flags; + /* A hash table holding typedef_field objects. This is more complicated than an ordinary hash because it must also track the lifetime of some -- but not all -- of the contained objects. */ -- 2.18.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFAv2 6/6] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers ` (2 preceding siblings ...) 2018-08-26 16:54 ` [RFAv2 2/6] Make struct type_print_options default_ptype_flags non static Philippe Waroquiers @ 2018-08-26 16:54 ` Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args Philippe Waroquiers ` (3 subsequent siblings) 7 siblings, 0 replies; 19+ messages in thread From: Philippe Waroquiers @ 2018-08-26 16:54 UTC (permalink / raw) To: gdb-patches; +Cc: Philippe Waroquiers Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] gdb/testsuite/ChangeLog 2018-08-26 Philippe Waroquiers <philippe.waroquiers@skynet.be> * gdb.base/info_qt.c: New file. * gdb.base/info_qt.exp: New file. --- gdb/testsuite/gdb.base/info_qt.c | 81 +++++++++++ gdb/testsuite/gdb.base/info_qt.exp | 221 +++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 gdb/testsuite/gdb.base/info_qt.c create mode 100644 gdb/testsuite/gdb.base/info_qt.exp diff --git a/gdb/testsuite/gdb.base/info_qt.c b/gdb/testsuite/gdb.base/info_qt.c new file mode 100644 index 0000000000..77c4ea8236 --- /dev/null +++ b/gdb/testsuite/gdb.base/info_qt.c @@ -0,0 +1,81 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2018 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> + +typedef int entier; + +int info_qt_inc = 0; +entier info_qt_ent = 0; + +static void +setup_done (void) +{ +} + +static void +setup (char arg_c, int arg_i, int arg_j) +{ + char loc_arg_c = arg_c; + int loc_arg_i = arg_i; + int loc_arg_j = arg_j; + + info_qt_inc += loc_arg_c + loc_arg_i + loc_arg_j; + setup_done (); +} + +void info_fun1 (void) +{ + info_qt_inc++; + info_qt_ent++; +} + +int info_fun2 (char c) +{ + info_qt_inc += c; + return info_qt_inc; +} + +int info_fun2bis (char c) +{ + info_qt_inc += c; + return info_qt_inc; +} + +entier info_fun2xxx (char arg_c, int arg_i, int arg_j) +{ + info_qt_inc += arg_c + arg_i + arg_j; + return info_qt_inc; +} + +entier info_fun2yyy (char arg_c, int arg_i, int arg_j) +{ + setup (arg_c, arg_i, arg_j); + info_qt_inc += arg_c + arg_i + arg_j; + return info_qt_inc; +} + +int +main (int argc, char **argv, char **envp) +{ + info_fun1 (); + (void) info_fun2 ('a'); + (void) info_fun2bis ('b'); + (void) info_fun2xxx ('c', 1, 2); + (void) info_fun2yyy ('d', 3, 4); +} diff --git a/gdb/testsuite/gdb.base/info_qt.exp b/gdb/testsuite/gdb.base/info_qt.exp new file mode 100644 index 0000000000..a657fec39e --- /dev/null +++ b/gdb/testsuite/gdb.base/info_qt.exp @@ -0,0 +1,221 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +# This test verifies that a macro using backtrace can be applied to all threads +# and will continue for each thread even though an error may occur in +# backtracing one of the threads. + +# Test info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile}] } { + return -1 +} + +clean_restart ${binfile} + +if ![runto setup_done] then { + gdb_suppress_tests +} +set any "\[^\r\n\]*" +set ws "\[ \t\]\+" +set number "\[0-9]\+" + + +############# test 'info functions' + +# test simple matching with name regexp +foreach_with_prefix cmd { + "info functions info_fun" + "info functions -- info_fun" + "info functions ^info_fun" } { + gdb_test $cmd \ + [multi_line \ + "All functions matching regular expression \".*info_fun.*\":" \ + "" \ + "File .*info_qt.c:" \ + "${number}: void info_fun1\\\(void\\\);" \ + "${number}: int info_fun2\\\(char\\\);" \ + "${number}: int info_fun2bis\\\(char\\\);" \ + "${number}: entier info_fun2xxx\\\(char, int, int\\\);" \ + "${number}: entier info_fun2yyy\\\(char, int, int\\\);" \ + ] \ + "info functions info_fun" +} + +# test simple matching with name regexp, but with -q to avoid the first header +foreach_with_prefix cmd { + "info functions -q info_fun" + "info functions -q -- info_fun" } { + gdb_test $cmd \ + [multi_line \ + "" \ + "File .*info_qt.c:" \ + "${number}: void info_fun1\\\(void\\\);" \ + "${number}: int info_fun2\\\(char\\\);" \ + "${number}: int info_fun2bis\\\(char\\\);" \ + "${number}: entier info_fun2xxx\\\(char, int, int\\\);" \ + "${number}: entier info_fun2yyy\\\(char, int, int\\\);" \ + ] \ + "info functions -q info_fun" +} + +# test -q and no matching functions +foreach_with_prefix cmd { + "info functions -q nowaythiscanmatch" + "info functions -q -- -q" } { + gdb_test $cmd "" "quiet info functions empty output" +} + +# test with a type regexp +foreach_with_prefix cmd { + "info functions -t entier -q info_fun" + "info functions -q -t 'entier (' -- info_fun" + "info functions -q -t '(char, int, int)' -- info_fun" + "info functions -q -t 'entier (char, int, int)' -- info_fun" } { + gdb_test $cmd \ + [multi_line \ + "" \ + "File .*info_qt.c:" \ + "${number}: entier info_fun2xxx\\\(char, int, int\\\);" \ + "${number}: entier info_fun2yyy\\\(char, int, int\\\);" \ + ] \ + "info functions -q info_fun" +} + +# test with a non matching type regexp +gdb_test "info functions -t ganze_Zahl -q info_fun" "" \ + "quiet output info functions non matching type" + + +############# test 'info variables' + +# test simple matching with name regexp +foreach_with_prefix cmd { + "info variables info_qt" + "info variables -- info_qt" + "info variables ^info_qt" } { + gdb_test $cmd \ + [multi_line \ + "All variables matching regular expression \".*info_qt.*\":" \ + "" \ + "File .*info_qt.c:" \ + "${number}: entier info_qt_ent;" \ + "${number}: int info_qt_inc;" \ + ] \ + "info functions info_fun" +} + +# test simple matching with name regexp, but with -q to avoid the first header + +# test -q and no matching variables +foreach_with_prefix cmd { + "info variables -q nowaythiscanmatch" + "info variables -q -- -q" } { + gdb_test $cmd "" "quiet info variables empty output" +} + +# test with a type regexp +foreach_with_prefix cmd { + "info variables -t entier -q info_qt" + "info variables -q -t entier -- info_qt" } { + gdb_test $cmd \ + [multi_line \ + "" \ + "File .*info_qt.c:" \ + "${number}: entier info_qt_ent;" \ + ] \ + "info variables -q -t entier info_fun" +} + +# test with a non matching type regexp +gdb_test "info variables -t ganze_Zahl -q info_at" "" \ + "quiet output info variables non matching type" + + + +############# test 'info args' in function setup. + +gdb_test "frame 1" ".* in setup .*" "set frame 1 for info args" + +# test name regexp matching all +foreach_with_prefix cmd { + "info args" + "info args arg_" + "info args g" + "info args -- .*" } { + gdb_test $cmd \ + [multi_line \ + "arg_c = 100 'd'" \ + "arg_i = 3" \ + "arg_j = 4" \ + ] \ + "info args" +} + +# test name regexp or type regexp matching some +foreach_with_prefix cmd { + "info args -t int" + "info args arg_[ij]"} { + gdb_test $cmd \ + [multi_line \ + "arg_i = 3" \ + "arg_j = 4" \ + ] \ + "info args" +} + +gdb_test "info args nowaythiscanmatch" "No matching arguments." "non matching args" +gdb_test "info args -q nowaythiscanmatch" "" "quiet non matching args" +gdb_test "info args -q -t entier" "" "quiet non matching args with type" + +############# test 'info locals' in function setup. + +gdb_test "frame 1" ".* in setup .*" "set frame 1 for info locals" + +# test name regexp matching all +foreach_with_prefix cmd { + "info locals" + "info locals loc_arg_" + "info locals g" + "info locals -- .*" } { + gdb_test $cmd \ + [multi_line \ + "loc_arg_c = 100 'd'" \ + "loc_arg_i = 3" \ + "loc_arg_j = 4" \ + ] \ + "info locals" +} + +# test name regexp or type regexp matching some +foreach_with_prefix cmd { + "info locals -t int" + "info locals arg_[ij]" + "info locals loc_arg_[ij]"} { + gdb_test $cmd \ + [multi_line \ + "loc_arg_i = 3" \ + "loc_arg_j = 4" \ + ] \ + "info args" +} + +gdb_test "info locals nowaythiscanmatch" "No matching locals." "non matching locals" +gdb_test "info locals -q nowaythiscanmatch" "" "quiet non matching locals" +gdb_test "info locals -q -t ganze_Zahl loc" "" "quiet non matching locals with type" -- 2.18.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers ` (3 preceding siblings ...) 2018-08-26 16:54 ` [RFAv2 6/6] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers @ 2018-08-26 16:54 ` Philippe Waroquiers 2018-09-18 15:31 ` Tom Tromey 2018-08-26 16:54 ` [RFAv2 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers ` (2 subsequent siblings) 7 siblings, 1 reply; 19+ messages in thread From: Philippe Waroquiers @ 2018-08-26 16:54 UTC (permalink / raw) To: gdb-patches; +Cc: Philippe Waroquiers New cli-utils.h/.c function extract_info_print_args factorises the extraction of the args '[-q] [-t TYPEREGEXP] [NAMEREGEXP]'. This function will be used by the commands info [args|functions|locals|variables] cli-utils.c has a new static function extract_arg_maybe_quoted that extracts an argument, possibly single quoted. gdb/ChangeLog 2018-08-26 Philippe Waroquiers <philippe.waroquiers@skynet.be> * cli-utils.c (extract_arg_maybe_quoted): New function. (extract_info_print_args): New function. * cli-utils.h (extract_arg_maybe_quoted): New function. (extract_info_print_args): New function. (INFO_PRINT_ARGS_HELP): new macro. --- gdb/cli/cli-utils.c | 113 ++++++++++++++++++++++++++++++++++++++++++++ gdb/cli/cli-utils.h | 20 ++++++++ 2 files changed, 133 insertions(+) diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c index 98b7414991..7adbab46a1 100644 --- a/gdb/cli/cli-utils.c +++ b/gdb/cli/cli-utils.c @@ -23,6 +23,9 @@ #include <ctype.h> +static std::string +extract_arg_maybe_quoted (const char **arg); + /* See documentation in cli-utils.h. */ int @@ -125,6 +128,56 @@ get_number (char **pp) return result; } +/* See documentation in cli-utils.h. */ + +void +extract_info_print_args (const char* command, + const char **args, + bool *quiet, + std::string *regexp, + std::string *t_regexp) +{ + *quiet = false; + *regexp = ""; + *t_regexp = ""; + + while (*args != NULL) + { + if (check_for_argument (args, "--", 2)) + { + *args = skip_spaces (*args); + break; + } + + if (check_for_argument (args, "-t", 2)) + { + *t_regexp = extract_arg_maybe_quoted (args); + *args = skip_spaces (*args); + continue; + } + + if (check_for_argument (args, "-q", 2)) + { + *quiet = true; + *args = skip_spaces (*args); + continue; + } + + if (**args != '-') + break; + + std::string option = extract_arg (args); + error (_("Unrecognized option '%s' to %s command. " + "Try \"help %s\"."), option.c_str (), + command, command); + } + + if (*args != NULL && **args != '\000') + *regexp = extract_arg (args); + +} + + /* See documentation in cli-utils.h. */ number_or_range_parser::number_or_range_parser (const char *string) @@ -282,6 +335,66 @@ remove_trailing_whitespace (const char *start, const char *s) return s; } +/* A helper function to extract an argument from *ARG. An argument is + delimited by whitespace, but it can also be optionally quoted using + single quote characters. The return value is empty if no argument + was found. */ + +static std::string +extract_arg_maybe_quoted (const char **arg) +{ + if (!*arg) + return std::string (); + + /* Find the start of the argument. */ + *arg = skip_spaces (*arg); + if (!**arg) + return std::string (); + + if (**arg == '\'') + { + /* Quoted argument. */ + const char *orig_arg = *arg; + std::string result; + const char *p; + + (*arg)++; /* Skip starting quote. */ + + /* Find the end of the quoted argument. */ + for (p = *arg; *p != '\0'; p++) + { + if (*p == '\'') + { + (*arg)++; /* Skip ending quote. */ + return result; + } + + if (*p == '\\' && p[1] == '\'') + { + /* Escaped quote. */ + p++; /* Skip escape char. */ + (*arg)++; /* Skip escape char. */ + } + + result = result + *p; + (*arg)++; + } + error (_("Unterminated quoted argument in %s"), orig_arg); + } + else + { + const char *result = *arg; + + /* Find the end of the argument. */ + *arg = skip_to_space (*arg + 1); + + if (result == *arg) + return std::string (); + + return std::string (result, *arg - result); + } +} + /* See documentation in cli-utils.h. */ std::string diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h index fa7d02d719..602a36314d 100644 --- a/gdb/cli/cli-utils.h +++ b/gdb/cli/cli-utils.h @@ -39,6 +39,26 @@ extern int get_number (const char **); extern int get_number (char **); +/* Extract from args the arguments [-q] [-t TYPEREGEXP] [--] NAMEREGEXP. + Only the above flags are accepted. Any other flag will raise an error. + COMMAND is used to produce the error message if an invalid flag is + given. */ +extern void extract_info_print_args (const char* command, + const char **args, + bool *quiet, + std::string *regexp, + std::string *t_regexp); + +#define INFO_PRINT_ARGS_HELP(entity_kind) \ +"If NAMEREGEXP is provided, only prints the " entity_kind " whose name\n\ +matches NAMEREGEXP.\n\ +If -t TYPEREGEXP is provided, only prints the " entity_kind " whose type\n\ +matches TYPEREGEXP. Note that the matching is done with the type\n\ +printed by the 'whatis' command.\n\ +By default, the command might produce headers and/or messages indicating\n\ +why no " entity_kind " can be printed.\n\ +The flag -q disables the production of these headers and messages." + /* Parse a number or a range. A number will be of the form handled by get_number. A range will be of the form <number1> - <number2>, and -- 2.18.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args 2018-08-26 16:54 ` [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args Philippe Waroquiers @ 2018-09-18 15:31 ` Tom Tromey 2018-09-23 20:16 ` Philippe Waroquiers 0 siblings, 1 reply; 19+ messages in thread From: Tom Tromey @ 2018-09-18 15:31 UTC (permalink / raw) To: Philippe Waroquiers; +Cc: gdb-patches >>>>> "Philippe" == Philippe Waroquiers <philippe.waroquiers@skynet.be> writes: Philippe> cli-utils.c has a new static function extract_arg_maybe_quoted Philippe> that extracts an argument, possibly single quoted. I think it would be better if this handled quotes the same way that gdb_argv (aka libiberty's buildargv) does. That approach seems ok-ish (maybe not perfect), and following it would mean that at least we're not increasing the number of ways that command lines are quoted in gdb. I guess the reason you did not simply use gdb_argv is that the trailing regexp is the rest of the input string. Philippe> +/* See documentation in cli-utils.h. */ Philippe> + Philippe> +void Philippe> +extract_info_print_args (const char* command, Philippe> + const char **args, Philippe> + bool *quiet, Philippe> + std::string *regexp, Philippe> + std::string *t_regexp) I tend to think this should go somewhere else, since cli-utils is more like "low level" parsing helpers. But I don't really know where I guess. Philippe> + if (*args != NULL && **args != '\000') Philippe> + *regexp = extract_arg (args); It seems to me that this should just be "*regexp = args" for backward compatibility. This formulation will stop at whitespace, whereas the previous code did not. If changing the meaning of "info types regexp" where the regexp has whitespace is ok, then switching fully to gdb_argv would be better. I don't know if it is ok to do but I suspect not. Philippe> +/* A helper function to extract an argument from *ARG. An argument is Philippe> + delimited by whitespace, but it can also be optionally quoted using Philippe> + single quote characters. The return value is empty if no argument Philippe> + was found. */ Philippe> + Philippe> +static std::string Philippe> +extract_arg_maybe_quoted (const char **arg) Philippe> +{ One question I have is whether we could just change extract_arg to do the dequoting. Auditing the existing calls to see if this change would negatively impact them might not be too hard. And, it would be nice to make gdb's CLI a bit more regular. Philippe> +#define INFO_PRINT_ARGS_HELP(entity_kind) \ Philippe> +"If NAMEREGEXP is provided, only prints the " entity_kind " whose name\n\ Philippe> +matches NAMEREGEXP.\n\ Philippe> +If -t TYPEREGEXP is provided, only prints the " entity_kind " whose type\n\ Philippe> +matches TYPEREGEXP. Note that the matching is done with the type\n\ Philippe> +printed by the 'whatis' command.\n\ Philippe> +By default, the command might produce headers and/or messages indicating\n\ Philippe> +why no " entity_kind " can be printed.\n\ Philippe> +The flag -q disables the production of these headers and messages." Constructing help text like this is i18n-unfriendly. gdb tries to do this correctly, though IIRC the build isn't all wired up properly and there aren't any actual translations :-/ Maybe it can be reworded somehow. I'm not sure if xgettext can handle this kind of string concatenation in combination with macro expansion, either. Tom ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args 2018-09-18 15:31 ` Tom Tromey @ 2018-09-23 20:16 ` Philippe Waroquiers 2018-09-24 13:07 ` Tom Tromey 0 siblings, 1 reply; 19+ messages in thread From: Philippe Waroquiers @ 2018-09-23 20:16 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches Thanks for the comments, feedback below. On Tue, 2018-09-18 at 09:23 -0600, Tom Tromey wrote: > > > > > > "Philippe" == Philippe Waroquiers <philippe.waroquiers@skynet.be> writes: > > Philippe> cli-utils.c has a new static function extract_arg_maybe_quoted > Philippe> that extracts an argument, possibly single quoted. > > I think it would be better if this handled quotes the same way that > gdb_argv (aka libiberty's buildargv) does. That approach seems ok-ish > (maybe not perfect), and following it would mean that at least we're not > increasing the number of ways that command lines are quoted in gdb. Agreed. In RFAv3, the quoting is handled the same way as gdb_argv. > > I guess the reason you did not simply use gdb_argv is that the trailing > regexp is the rest of the input string. Effectively. Using gdb_argv for handling the list of arguments would create backward incompatibilities (more details below). > > Philippe> +/* See documentation in cli-utils.h. */ > Philippe> + > Philippe> +void > Philippe> +extract_info_print_args (const char* command, > Philippe> + const char **args, > Philippe> + bool *quiet, > Philippe> + std::string *regexp, > Philippe> + std::string *t_regexp) > > I tend to think this should go somewhere else, since cli-utils is more > like "low level" parsing helpers. But I don't really know where I > guess. Yes, I found no better (existing) place, so I kept it there. If you prefer, I can create cli-arg_utils.h for 'higher level' arg parsing helpers if you believe this is cleaner. > > Philippe> + if (*args != NULL && **args != '\000') > Philippe> + *regexp = extract_arg (args); > > It seems to me that this should just be "*regexp = args" for backward > compatibility. This formulation will stop at whitespace, whereas the > previous code did not. Good catch ! I have fixed the regression, and added a specific check in info_qt.exp to verify that a space does not terminate the NAMEREGEXP. > > If changing the meaning of "info types regexp" where the regexp has > whitespace is ok, then switching fully to gdb_argv would be better. I > don't know if it is ok to do but I suspect not. I looked at using gdb_argv, but concluded that using gdb_argv would be backward incompatible for some likely use cases. E.g. in Ada, a . can be part of a variable name, and the behaviour of 'info variables a\.t' would change : a lot more variables would match. More generally, any backslashing of REGEXP special char would be broken. So, I did not switch fully to gdb_argv, but made extract_arg_maybe_quoted quoting and escaping compatible with gdb_argv. > > Philippe> +/* A helper function to extract an argument from *ARG. An argument is > Philippe> + delimited by whitespace, but it can also be optionally quoted using > Philippe> + single quote characters. The return value is empty if no argument > Philippe> + was found. */ > Philippe> + > Philippe> +static std::string > Philippe> +extract_arg_maybe_quoted (const char **arg) > Philippe> +{ > > One question I have is whether we could just change extract_arg to do > the dequoting. Auditing the existing calls to see if this change would > negatively impact them might not be too hard. And, it would be nice to > make gdb's CLI a bit more regular. I examined the calls to extract_arg : I found one possible unlikely backward incompatibility related to single quote handling : the mem command accepts expressions for addresses, and expressions in Ada can contain single quotes. So, it looks possible to have extract_arg behaviour replaced by extract_arg_maybe_quoted behaviour. If you agree with the above analysis, I will work on that in a separate patch series. > > Philippe> +#define INFO_PRINT_ARGS_HELP(entity_kind) \ > Philippe> +"If NAMEREGEXP is provided, only prints the " entity_kind " whose name\n\ > Philippe> +matches NAMEREGEXP.\n\ > Philippe> +If -t TYPEREGEXP is provided, only prints the " entity_kind " whose type\n\ > Philippe> +matches TYPEREGEXP. Note that the matching is done with the type\n\ > Philippe> +printed by the 'whatis' command.\n\ > Philippe> +By default, the command might produce headers and/or messages indicating\n\ > Philippe> +why no " entity_kind " can be printed.\n\ > Philippe> +The flag -q disables the production of these headers and messages." > > Constructing help text like this is i18n-unfriendly. gdb tries to do > this correctly, though IIRC the build isn't all wired up properly and > there aren't any actual translations :-/ > > Maybe it can be reworded somehow. I'm not sure if xgettext can handle > this kind of string concatenation in combination with macro expansion, > either. I have replaced the macro and string concatenation by a function, so that all string constants use the _("...") layout. Thanks Philippe ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args 2018-09-23 20:16 ` Philippe Waroquiers @ 2018-09-24 13:07 ` Tom Tromey 2018-09-25 4:37 ` Philippe Waroquiers 0 siblings, 1 reply; 19+ messages in thread From: Tom Tromey @ 2018-09-24 13:07 UTC (permalink / raw) To: Philippe Waroquiers; +Cc: Tom Tromey, gdb-patches >>>>> "Philippe" == Philippe Waroquiers <philippe.waroquiers@skynet.be> writes: Tom> I tend to think this should go somewhere else, since cli-utils is more Tom> like "low level" parsing helpers. But I don't really know where I Tom> guess. Philippe> Yes, I found no better (existing) place, so I kept it there. Philippe> If you prefer, I can create cli-arg_utils.h for 'higher level' Philippe> arg parsing helpers if you believe this is cleaner. I think your current approach is fine. Philippe> I looked at using gdb_argv, but concluded that using gdb_argv Philippe> would be backward incompatible for some likely use cases. [...] Philippe> So, I did not switch fully to gdb_argv, but made Philippe> extract_arg_maybe_quoted quoting and escaping compatible Philippe> with gdb_argv. Thank you for looking into this. Tom> One question I have is whether we could just change extract_arg to do Tom> the dequoting. Auditing the existing calls to see if this change would Tom> negatively impact them might not be too hard. And, it would be nice to Tom> make gdb's CLI a bit more regular. Philippe> I examined the calls to extract_arg : I found one possible unlikely Philippe> backward incompatibility related to single quote handling : Philippe> the mem command accepts expressions for addresses, and expressions Philippe> in Ada can contain single quotes. C-ish languages use single quotes for char constants, so this would be pretty bad there too. The "mem" command got the parsing wrong. The incorrectness dates back to when it was introduced in 2001. For example (today's code but it hasn't substantially changed): std::string tok = extract_arg (&args); if (tok == "") error (_("no lo address")); lo = parse_and_eval_address (tok.c_str ()); This is user-hostile for non-trivial expressions, because it forces you to write them without spaces. Instead code like this should use parse_to_comma_and_eval. Maybe it is too late to fix the "mem" command. I am not sure. I do know that back when I approved a similar change to "disasssemble" (I thought I'd written that! But the history shows not), there were complaints -- we broke people's workarounds for the bad parsing behavior. On the other hand, "disasssemble" is probably used a lot more than "mem". Philippe> So, it looks possible to have extract_arg behaviour replaced by Philippe> extract_arg_maybe_quoted behaviour. Philippe> If you agree with the above analysis, I will work on that in a separate Philippe> patch series. One idea might be to upgrade the calls where it seems reasonable and then leave the legacy behavior for the ones where it is not... perhaps at the end, renaming extract_arg so that the name makes it clear that it shouldn't be used in new code. What do you think of that? It's not necessary for you to do all the work involved. Tom ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args 2018-09-24 13:07 ` Tom Tromey @ 2018-09-25 4:37 ` Philippe Waroquiers 0 siblings, 0 replies; 19+ messages in thread From: Philippe Waroquiers @ 2018-09-25 4:37 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On Mon, 2018-09-24 at 07:07 -0600, Tom Tromey wrote: > Maybe it is too late to fix the "mem" command. I am not sure. I do > know that back when I approved a similar change to "disasssemble" (I > thought I'd written that! But the history shows not), there were > complaints -- we broke people's workarounds for the bad parsing > behavior. On the other hand, "disasssemble" is probably used a lot more > than "mem". > > Philippe> So, it looks possible to have extract_arg behaviour replaced by > Philippe> extract_arg_maybe_quoted behaviour. > Philippe> If you agree with the above analysis, I will work on that in a separate > Philippe> patch series. > > One idea might be to upgrade the calls where it seems reasonable and > then leave the legacy behavior for the ones where it is not... perhaps > at the end, renaming extract_arg so that the name makes it clear that it > shouldn't be used in new code. > > What do you think of that? It's not necessary for you to do all the > work involved. Yes, that sounds a reasonable approach. No problem for me to work on that, and give a proposal 'change to new behavior' or 'keep legacy behavior' for each extract_arg call (it might take a week or 2, as gdb is an evening/week-end activity). Once the analysis of which calls are reasonable to change is done, the code changes should be pretty small. Philippe ^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFAv2 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers ` (4 preceding siblings ...) 2018-08-26 16:54 ` [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args Philippe Waroquiers @ 2018-08-26 16:54 ` Philippe Waroquiers 2018-09-18 15:52 ` Tom Tromey 2018-09-06 20:16 ` PING Re: [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers 2018-09-13 19:27 ` PING^2 " Philippe Waroquiers 7 siblings, 1 reply; 19+ messages in thread From: Philippe Waroquiers @ 2018-08-26 16:54 UTC (permalink / raw) To: gdb-patches; +Cc: Philippe Waroquiers 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 defined in 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. * symtab.c: Add type/name matching logic to 'info functions|variables'. * stack.c : Add type/name matching logic to 'info args|locals'. gdb/ChangeLog 2018-08-26 Philippe Waroquiers <philippe.waroquiers@skynet.be> * 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 | 164 +++++++++++++++++++++++++++++++++++------- gdb/symtab.h | 8 ++- gdb/tracepoint.c | 8 ++- 11 files changed, 299 insertions(+), 56 deletions(-) diff --git a/gdb/linespec.c b/gdb/linespec.c index 73fbe4af3b..ba23eeaba6 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 40ff99b8fa..f3e8af6031 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, @@ -1829,7 +1832,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); @@ -1903,10 +1906,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<compiled_regex> &preg, + const gdb::optional<compiled_regex> &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data) { @@ -1926,6 +1933,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; @@ -1987,16 +2001,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<compiled_regex> &preg, + const gdb::optional<compiled_regex> &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. */ @@ -2043,30 +2061,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<compiled_regex> ®) +{ + 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<compiled_regex> preg; + gdb::optional<compiled_regex> 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; } @@ -2075,31 +2120,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<compiled_regex> &preg, + const gdb::optional<compiled_regex> &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data) { @@ -2109,7 +2176,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 @@ -2121,7 +2193,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); @@ -2131,26 +2202,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<compiled_regex> preg; + gdb::optional<compiled_regex> 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; } @@ -2159,20 +2244,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); } \f @@ -2815,10 +2917,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<compiled_regex> &preg, + const gdb::optional<compiled_regex> &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<compiled_regex> &preg, + const gdb::optional<compiled_regex> &treg, iterate_over_block_arg_local_vars_cb cb, void *cb_data); diff --git a/gdb/symfile.c b/gdb/symfile.c index 20697d9dca..3497093300 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 0a1caa51fb..5f2afe3582 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" @@ -4264,6 +4265,50 @@ 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; + 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 @@ -4279,7 +4324,9 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *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 @@ -4290,6 +4337,7 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *result) std::vector<symbol_search> search_symbols (const char *regexp, enum search_domain kind, + const char *t_regexp, int nfiles, const char *files[]) { struct compunit_symtab *cust; @@ -4315,6 +4363,7 @@ search_symbols (const char *regexp, enum search_domain kind, enum minimal_symbol_type ourtype4; std::vector<symbol_search> result; gdb::optional<compiled_regex> preg; + gdb::optional<compiled_regex> treg; gdb_assert (kind <= TYPES_DOMAIN); @@ -4364,6 +4413,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. */ @@ -4462,9 +4518,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)))) { @@ -4495,8 +4555,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. */ @@ -4597,7 +4661,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"}; @@ -4607,13 +4673,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<symbol_search> symbols = search_symbols (regexp, kind, 0, NULL); + std::vector<symbol_search> 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) { @@ -4623,7 +4709,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); @@ -4641,22 +4728,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. */ @@ -4699,6 +4805,7 @@ rbreak_command (const char *regexp, int from_tty) std::vector<symbol_search> symbols = search_symbols (regexp, FUNCTIONS_DOMAIN, + NULL, nfiles, files); scoped_rbreak_breakpoints finalize; @@ -5901,13 +6008,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 eb14f346b9..d413adbeab 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -25,6 +25,7 @@ #include <string> #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" @@ -2063,8 +2064,13 @@ private: }; extern std::vector<symbol_search> 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 a96f56a06b..69711a034e 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" @@ -1086,6 +1087,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<compiled_regex> nullreg; cb_data.collect = this; cb_data.gdbarch = gdbarch; @@ -1105,7 +1107,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.")); } @@ -1119,7 +1122,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.")); } -- 2.18.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] 2018-08-26 16:54 ` [RFAv2 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers @ 2018-09-18 15:52 ` Tom Tromey 2018-09-23 21:34 ` Philippe Waroquiers 0 siblings, 1 reply; 19+ messages in thread From: Tom Tromey @ 2018-09-18 15:52 UTC (permalink / raw) To: Philippe Waroquiers; +Cc: gdb-patches >>>>> "Philippe" == Philippe Waroquiers <philippe.waroquiers@skynet.be> writes: Philippe> As stack.h now uses a type defined in gdb_regex.h, all files including stack.h Philippe> need to include gdb_regex.h. It's better to just include gdb_regex.h from stack.h in this situation. Philippe> + if (preg I think preg.has_value (). gdb is trending away from these bool conversions, I think. At least that's been the style for pointers. Philippe> + if (treg Here too. Philippe> +/* Prepares the regular expression REG from REGEXP. Philippe> + If REGEXP is NULL, it results in an empty regular expression. */ Philippe> +static void Philippe> +prepare_reg (const char *regexp, gdb::optional<compiled_regex> ®) Out parameters should be pointers in the gdb style. Philippe> - iterate_over_block_local_vars (block, Philippe> + iterate_over_block_local_vars (block, preg, treg, Philippe> do_print_variable_and_value, Philippe> &cb_data); iterate_over_block_local_vars already takes some opaque data that it just passes through to the callback. So, I think there should not be a need to add the regexp parameters directly to it. Instead they can be put into the cb_data here. Philippe> void Philippe> iterate_over_block_arg_vars (const struct block *b, Philippe> + const gdb::optional<compiled_regex> &preg, Philippe> + const gdb::optional<compiled_regex> &treg, Philippe> iterate_over_block_arg_local_vars_cb cb, Philippe> void *cb_data) Same here. Philippe> +/* Returns true if the type_name of symbol_type of SYM matches TREG. Philippe> + If SYM has no symbol_type or symbol_name, returns false. */ Philippe> + Philippe> +bool Philippe> +treg_matches_sym_type_name (const compiled_regex &treg, Philippe> + const struct symbol *sym) Philippe> +{ Philippe> + if (language_mode == language_mode_auto) Philippe> + language_def (SYMBOL_LANGUAGE (sym))->la_print_type Philippe> + (sym_type, "", &printed_sym_type_name, Philippe> + -1, 0, &default_ptype_flags); I think this won't actually work, because the type printing code is free to use current_language. This is not good, but it is how it is. So instead I think what this should do is save and restore the current language. IIRC there's a helper RAII class for that already. Then you can just call type_print and drop patch #2. Philippe> +extern bool Philippe> +treg_matches_sym_type_name (const compiled_regex &treg, Philippe> + const struct symbol *sym); No newline after the "bool" for a declaration. Tom ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFAv2 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] 2018-09-18 15:52 ` Tom Tromey @ 2018-09-23 21:34 ` Philippe Waroquiers 0 siblings, 0 replies; 19+ messages in thread From: Philippe Waroquiers @ 2018-09-23 21:34 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches Feedback below ... RFAv3 will follow soon Thanks for the comments. Philippe On Tue, 2018-09-18 at 09:51 -0600, Tom Tromey wrote: > > > > > > "Philippe" == Philippe Waroquiers <philippe.waroquiers@skynet.be> writes: > > Philippe> As stack.h now uses a type defined in gdb_regex.h, all files including stack.h > Philippe> need to include gdb_regex.h. > > It's better to just include gdb_regex.h from stack.h in this situation. Done (rather, no need anymore for regexp in stack.h). > > Philippe> + if (preg > > I think preg.has_value (). gdb is trending away from these bool > conversions, I think. At least that's been the style for pointers. > > Philippe> + if (treg > > Here too. Done. > > Philippe> +/* Prepares the regular expression REG from REGEXP. > Philippe> + If REGEXP is NULL, it results in an empty regular expression. */ > Philippe> +static void > Philippe> +prepare_reg (const char *regexp, gdb::optional<compiled_regex> ®) > > Out parameters should be pointers in the gdb style. Done. > > Philippe> - iterate_over_block_local_vars (block, > Philippe> + iterate_over_block_local_vars (block, preg, treg, > Philippe> do_print_variable_and_value, > Philippe> &cb_data); > > iterate_over_block_local_vars already takes some opaque data that it > just passes through to the callback. So, I think there should not be > a need to add the regexp parameters directly to it. Instead they can be > put into the cb_data here. > > Philippe> void > Philippe> iterate_over_block_arg_vars (const struct block *b, > Philippe> + const gdb::optional<compiled_regex> &preg, > Philippe> + const gdb::optional<compiled_regex> &treg, > Philippe> iterate_over_block_arg_local_vars_cb cb, > Philippe> void *cb_data) > > Same here. Done: the preg/treg regexp have been put in the opaque cb_data, and regexp filtering logic has been moved to do_print_variable_and_value. > > Philippe> +/* Returns true if the type_name of symbol_type of SYM matches TREG. > Philippe> + If SYM has no symbol_type or symbol_name, returns false. */ > Philippe> + > Philippe> +bool > Philippe> +treg_matches_sym_type_name (const compiled_regex &treg, > Philippe> + const struct symbol *sym) > Philippe> +{ > Philippe> + if (language_mode == language_mode_auto) > Philippe> + language_def (SYMBOL_LANGUAGE (sym))->la_print_type > Philippe> + (sym_type, "", &printed_sym_type_name, > Philippe> + -1, 0, &default_ptype_flags); > > I think this won't actually work, because the type printing code is free > to use current_language. This is not good, but it is how it is. > > So instead I think what this should do is save and restore the current > language. IIRC there's a helper RAII class for that already. > > Then you can just call type_print and drop patch #2. Done. > > Philippe> +extern bool > Philippe> +treg_matches_sym_type_name (const compiled_regex &treg, > Philippe> + const struct symbol *sym); > > No newline after the "bool" for a declaration. Done. Thanks Philippe ^ permalink raw reply [flat|nested] 19+ messages in thread
* PING Re: [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers ` (5 preceding siblings ...) 2018-08-26 16:54 ` [RFAv2 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers @ 2018-09-06 20:16 ` Philippe Waroquiers 2018-09-13 19:27 ` PING^2 " Philippe Waroquiers 7 siblings, 0 replies; 19+ messages in thread From: Philippe Waroquiers @ 2018-09-06 20:16 UTC (permalink / raw) To: gdb-patches Ping Thanks Philippe On Sun, 2018-08-26 at 18:53 +0200, Philippe Waroquiers wrote: > [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] > > This is a follow up to the first RFA. > The documentation parts were already reviewed by Eli, other parts > were not reviewed yet. > Compared to the first RFA, the changes are a rebase to the last trunk version, > the removal of an unused local variable, and some updates to the new > info_qt.exp test to ensure unicity of test names. > > Thanks. > > > This patch series adds flags and/or arguments > [-q] [-t TYPEREGEXP] [NAMEREGEXP] to the commands > info [args|functions|locals|variables] > > The additional arguments allow to more precisely specify what to print. > As these new features can usefully be combined with frame apply and thread > apply, the documentation gives examples combining the above > and the 'thread apply' and 'frame apply' commands. > > Some examples: > * print functions returning an int: > info functions -t '^int (' > * print local variables having pthread_t type > info locals -t pthread_t > * print global variables having type 'struct addrinfo' > info var -t 'struct addrinfo' > * print args that are likely file descriptors > info arg -t int .*fd.* > > Below examples are combined with the 'thread/frame apply' commands: > > * Assuming lock_something_t is an RAII type, show all locks: > thread apply all -s frame apply all -s info locals -q -t lock_something_t > or shorter equivalent: > tfaas i lo -q -t lock_something_t > > * show frames and args having an arg with type matchin std::.*map > so likely std::map or std::unordered_map > frame apply all -s info args -q std::.*map > > > The code, documentation, NEWS, test and ChangeLog are (supposed to be) complete. > > The changes in RFA v2 are: > * Removal of an unused local variable. > * Updates to the test info_qt.exp, to ensure no duplicate in test names. > > Compared to the RFC, the changes in RFA v1 are: > * All comments of Eli on the documentation have been handled. > * ChangeLog entries added in commit messages > * Test added. > > > ^ permalink raw reply [flat|nested] 19+ messages in thread
* PING^2 Re: [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers ` (6 preceding siblings ...) 2018-09-06 20:16 ` PING Re: [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers @ 2018-09-13 19:27 ` Philippe Waroquiers 7 siblings, 0 replies; 19+ messages in thread From: Philippe Waroquiers @ 2018-09-13 19:27 UTC (permalink / raw) To: gdb-patches Thanks Philippe On Sun, 2018-08-26 at 18:53 +0200, Philippe Waroquiers wrote: > [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] > > This is a follow up to the first RFA. > The documentation parts were already reviewed by Eli, other parts > were not reviewed yet. > Compared to the first RFA, the changes are a rebase to the last trunk version, > the removal of an unused local variable, and some updates to the new > info_qt.exp test to ensure unicity of test names. > > Thanks. > > > This patch series adds flags and/or arguments > [-q] [-t TYPEREGEXP] [NAMEREGEXP] to the commands > info [args|functions|locals|variables] > > The additional arguments allow to more precisely specify what to print. > As these new features can usefully be combined with frame apply and thread > apply, the documentation gives examples combining the above > and the 'thread apply' and 'frame apply' commands. > > Some examples: > * print functions returning an int: > info functions -t '^int (' > * print local variables having pthread_t type > info locals -t pthread_t > * print global variables having type 'struct addrinfo' > info var -t 'struct addrinfo' > * print args that are likely file descriptors > info arg -t int .*fd.* > > Below examples are combined with the 'thread/frame apply' commands: > > * Assuming lock_something_t is an RAII type, show all locks: > thread apply all -s frame apply all -s info locals -q -t lock_something_t > or shorter equivalent: > tfaas i lo -q -t lock_something_t > > * show frames and args having an arg with type matchin std::.*map > so likely std::map or std::unordered_map > frame apply all -s info args -q std::.*map > > > The code, documentation, NEWS, test and ChangeLog are (supposed to be) complete. > > The changes in RFA v2 are: > * Removal of an unused local variable. > * Updates to the test info_qt.exp, to ensure no duplicate in test names. > > Compared to the RFC, the changes in RFA v1 are: > * All comments of Eli on the documentation have been handled. > * ChangeLog entries added in commit messages > * Test added. > > > ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2018-09-25 4:37 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-08-26 16:54 [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 5/6] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers 2018-08-26 18:21 ` Eli Zaretskii 2018-08-27 4:39 ` Philippe Waroquiers 2018-08-27 14:59 ` Eli Zaretskii 2018-08-26 16:54 ` [RFAv2 4/6] Document changes " Philippe Waroquiers 2018-08-26 18:19 ` Eli Zaretskii 2018-08-26 16:54 ` [RFAv2 2/6] Make struct type_print_options default_ptype_flags non static Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 6/6] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 1/6] New cli-utils.h/.c function extract_info_print_args Philippe Waroquiers 2018-09-18 15:31 ` Tom Tromey 2018-09-23 20:16 ` Philippe Waroquiers 2018-09-24 13:07 ` Tom Tromey 2018-09-25 4:37 ` Philippe Waroquiers 2018-08-26 16:54 ` [RFAv2 3/6] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers 2018-09-18 15:52 ` Tom Tromey 2018-09-23 21:34 ` Philippe Waroquiers 2018-09-06 20:16 ` PING Re: [RFAv2 0/6] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers 2018-09-13 19:27 ` PING^2 " Philippe Waroquiers
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox