* [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands
@ 2013-07-03 1:48 Yao Qi
2013-07-03 1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi
` (2 more replies)
0 siblings, 3 replies; 26+ messages in thread
From: Yao Qi @ 2013-07-03 1:48 UTC (permalink / raw)
To: gdb-patches
Hi,
This patch series add new option '--skip-unavailable' to MI commands
'-stack-list-{locals, arguments, variables}'. This option is optional,
and when it is used, locals or arguments whose values are not available
are not listed. It is useful when the MI front-end is not interested in
unavailable values.
The patch 1/2 is a refactor patch, use mi_getopt in
mi_cmd_stack_list_locals and mi_cmd_stack_list_variables, so it is
easier to add new option patch 2/2. Patch 2/2 is the major part of this
series.
Regression tested on x86_64-linux.
Note that this patch is for MI, but the idea that skipping unavailable
locals and arguments can be applied to CLI too. We can invent new CLI
commands on top of 'info locals' and 'info args' to display available
locals or arguments. This piece of work is not included in this
series.
*** BLURB HERE ***
Yao Qi (2):
Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables
Add options to skip unavailable locals
gdb/doc/gdb.texinfo | 17 ++-
gdb/mi/mi-cmd-stack.c | 256 ++++++++++++++++------
gdb/testsuite/gdb.trace/mi-trace-unavailable.exp | 9 +
gdb/valprint.c | 8 +-
gdb/valprint.h | 2 +
gdb/value.c | 20 ++
gdb/value.h | 4 +
7 files changed, 246 insertions(+), 70 deletions(-)
--
1.7.7.6
^ permalink raw reply [flat|nested] 26+ messages in thread* [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables 2013-07-03 1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi @ 2013-07-03 1:48 ` Yao Qi 2013-07-29 18:17 ` Pedro Alves 2013-07-03 1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi 2013-07-29 9:33 ` [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi 2 siblings, 1 reply; 26+ messages in thread From: Yao Qi @ 2013-07-03 1:48 UTC (permalink / raw) To: gdb-patches Hi, During the review of frame filter MI patch, Tom pointed that it is better to use mi_getopt to simplify option parsing. Unfortunately, the code doesn't do it. Since I am trying to add another option to commands '-stack-list-XXXX', I'd like to have a try to use mi_getopt. For command '-stack-list-locals' and '-stack-list-variables', the PRINT_VALUES may confuse option parsing by mi_getopt, so in this patch, we copy the argv except PRINT_VALUES to a new vector, and parse the new vector by mi_getopt. gdb: 2013-07-03 Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (mi_cmd_stack_list_locals): Don't call parse_no_frames_option. Copy ARGV to new_argv except PRINT_VALUES. Parse new_argv by mi_getopt. (mi_cmd_stack_list_variables): Likewise. --- gdb/mi/mi-cmd-stack.c | 99 ++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 89 insertions(+), 10 deletions(-) diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 4b21015..3212c03 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -212,16 +212,56 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) int raw_arg = 0; enum py_bt_status result = PY_BT_ERROR; int print_value; + int oind = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + if (argc > 1) + { + struct cleanup *cleanup; + int i; + char **new_argv = xmalloc ((argc - 1) * sizeof (char *)); + enum opt + { + NO_FRAME_FILTERS + }; + static const struct mi_opt opts[] = + { + {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + { 0, 0, 0 } + }; + + cleanup = make_cleanup (xfree, new_argv); + + for (i = 0; i < argc - 1; i++) + { + new_argv[i] = xstrdup (argv[i]); + make_cleanup (xfree, new_argv[i]); + } + + while (1) + { + char *oarg; + /* Don't parse 'print-values' as an option. */ + int opt = mi_getopt ("-stack-list-locals", argc - 1, new_argv, + opts, &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case NO_FRAME_FILTERS: + raw_arg = oind; + break; + } + } + do_cleanups (cleanup); + } - if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) - || (argc == 1 && raw_arg)) + /* After the last option is parsed, there should be only + 'print-values'. */ + if (argc - oind != 1) error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES")); frame = get_selected_frame (NULL); - print_value = mi_parse_print_values (argv[raw_arg]); + print_value = mi_parse_print_values (argv[oind]); if (! raw_arg && frame_filters) { @@ -341,17 +381,56 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) int raw_arg = 0; enum py_bt_status result = PY_BT_ERROR; int print_value; + int oind = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + if (argc > 1) + { + struct cleanup *cleanup; + int i; + char **new_argv = xmalloc ((argc - 1) * sizeof (char *)); + enum opt + { + NO_FRAME_FILTERS + }; + static const struct mi_opt opts[] = + { + {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + { 0, 0, 0 } + }; + cleanup = make_cleanup (xfree, new_argv); + + for (i = 0; i < argc - 1; i++) + { + new_argv[i] = xstrdup (argv[i]); + make_cleanup (xfree, new_argv[i]); + } + + while (1) + { + char *oarg; + /* Don't parse 'print-values' as an option. */ + int opt = mi_getopt ("-stack-list-variables", argc - 1, + new_argv, opts, &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case NO_FRAME_FILTERS: + raw_arg = oind; + break; + } + } + do_cleanups (cleanup); + } - if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) - || (argc == 1 && raw_arg)) + /* After the last option is parsed, there should be only + 'print-values'. */ + if (argc - oind != 1) error (_("-stack-list-variables: Usage: " \ "[--no-frame-filters] PRINT_VALUES")); frame = get_selected_frame (NULL); - print_value = mi_parse_print_values (argv[raw_arg]); + print_value = mi_parse_print_values (argv[oind]); if (! raw_arg && frame_filters) { -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables 2013-07-03 1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi @ 2013-07-29 18:17 ` Pedro Alves 2013-07-31 7:01 ` Yao Qi 0 siblings, 1 reply; 26+ messages in thread From: Pedro Alves @ 2013-07-29 18:17 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 07/03/2013 02:48 AM, Yao Qi wrote: > Hi, > During the review of frame filter MI patch, Tom pointed that it is better > to use mi_getopt to simplify option parsing. Unfortunately, the code > doesn't do it. Since I am trying to add another option to commands > '-stack-list-XXXX', I'd like to have a try to use mi_getopt. > > For command '-stack-list-locals' and '-stack-list-variables', > the PRINT_VALUES may confuse option parsing by mi_getopt, [to clarify,] because it throws error on unknown options, and PRINT_VALUES may look like an option (--no-values, --simple-values, etc.), or not (0, 1, etc.). > so in this > patch, we copy the argv except PRINT_VALUES to a new vector, and parse > the new vector by mi_getopt. Please help me understand the patch. Why do we need to copy the arg vector? Isn't it the same to do: /* Don't parse 'print-values' as an option. */ int opt = mi_getopt ("-stack-list-locals", argc - 1, argv, opts, &oind, &oarg); ? -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables 2013-07-29 18:17 ` Pedro Alves @ 2013-07-31 7:01 ` Yao Qi 2013-07-31 12:23 ` Pedro Alves 0 siblings, 1 reply; 26+ messages in thread From: Yao Qi @ 2013-07-31 7:01 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On 07/30/2013 02:17 AM, Pedro Alves wrote: > Please help me understand the patch. Why do we need to copy > the arg vector? Isn't it the same to do: > > /* Don't parse 'print-values' as an option. */ > int opt = mi_getopt ("-stack-list-locals", argc - 1, argv, > opts, &oind, &oarg); > > ? There was something wrong in mi_getopt (an internal error, IIRC) when I call mi_getopt with 'argc - 1', however, I can't reproduce it now. Probably because my tree was dirty then. I update the patch to avoid copying the arg vector. Patch 2/2 still apply. -- Yao (é½å°§) gdb: 2013-07-31 Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (mi_cmd_stack_list_locals): Parse argv by mi_getopt. (mi_cmd_stack_list_variables): Likewise. --- gdb/mi/mi-cmd-stack.c | 79 ++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 69 insertions(+), 10 deletions(-) diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 1f1068c..70ff0b6 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -212,16 +212,46 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) int raw_arg = 0; enum py_bt_status result = PY_BT_ERROR; int print_value; + int oind = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + if (argc > 1) + { + int i; + enum opt + { + NO_FRAME_FILTERS + }; + static const struct mi_opt opts[] = + { + {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + { 0, 0, 0 } + }; + + while (1) + { + char *oarg; + /* Don't parse 'print-values' as an option. */ + int opt = mi_getopt ("-stack-list-locals", argc - 1, argv, + opts, &oind, &oarg); + + if (opt < 0) + break; + switch ((enum opt) opt) + { + case NO_FRAME_FILTERS: + raw_arg = oind; + break; + } + } + } - if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) - || (argc == 1 && raw_arg)) + /* After the last option is parsed, there should be only + 'print-values'. */ + if (argc - oind != 1) error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES")); frame = get_selected_frame (NULL); - print_value = mi_parse_print_values (argv[raw_arg]); + print_value = mi_parse_print_values (argv[oind]); if (! raw_arg && frame_filters) { @@ -341,17 +371,46 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) int raw_arg = 0; enum py_bt_status result = PY_BT_ERROR; int print_value; + int oind = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + if (argc > 1) + { + int i; + enum opt + { + NO_FRAME_FILTERS + }; + static const struct mi_opt opts[] = + { + {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + { 0, 0, 0 } + }; + + while (1) + { + char *oarg; + /* Don't parse 'print-values' as an option. */ + int opt = mi_getopt ("-stack-list-variables", argc - 1, + argv, opts, &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case NO_FRAME_FILTERS: + raw_arg = oind; + break; + } + } + } - if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) - || (argc == 1 && raw_arg)) + /* After the last option is parsed, there should be only + 'print-values'. */ + if (argc - oind != 1) error (_("-stack-list-variables: Usage: " \ "[--no-frame-filters] PRINT_VALUES")); frame = get_selected_frame (NULL); - print_value = mi_parse_print_values (argv[raw_arg]); + print_value = mi_parse_print_values (argv[oind]); if (! raw_arg && frame_filters) { -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables 2013-07-31 7:01 ` Yao Qi @ 2013-07-31 12:23 ` Pedro Alves 2013-08-01 6:45 ` Yao Qi 0 siblings, 1 reply; 26+ messages in thread From: Pedro Alves @ 2013-07-31 12:23 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 07/31/2013 08:00 AM, Yao Qi wrote: > 2013-07-31 Yao Qi <yao@codesourcery.com> > > * mi/mi-cmd-stack.c (mi_cmd_stack_list_locals): Parse argv by > mi_getopt. s/by/with/ > (mi_cmd_stack_list_variables): Likewise. OK. -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables 2013-07-31 12:23 ` Pedro Alves @ 2013-08-01 6:45 ` Yao Qi 0 siblings, 0 replies; 26+ messages in thread From: Yao Qi @ 2013-08-01 6:45 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On 07/31/2013 08:22 PM, Pedro Alves wrote: > s/by/with/ > >> > (mi_cmd_stack_list_variables): Likewise. > OK. Thanks for the review. Changelog is fixed and patch is committed to cvs. -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 2/2] Add options to skip unavailable locals 2013-07-03 1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi 2013-07-03 1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi @ 2013-07-03 1:48 ` Yao Qi 2013-07-03 4:14 ` asmwarrior 2013-07-03 19:22 ` Eli Zaretskii 2013-07-29 9:33 ` [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi 2 siblings, 2 replies; 26+ messages in thread From: Yao Qi @ 2013-07-03 1:48 UTC (permalink / raw) To: gdb-patches This is the patch to add new option '--skip-unavailable' to MI commands '-stack-list-{locals, arguments, variables}'. This patch extends list_args_or_locals to add a new parameter 'skip_unavailable', and don't list locals or arguments if values are unavailable and 'skip_unavailable' is true. This is inspecting a trace frame (tfind mode), where only a few locals have been collected. -stack-list-locals, no switch vs new switch: -stack-list-locals --simple-values ^done,locals=[{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}] -stack-list-locals --skip-unavailable --simple-values ^done,locals=[{name="array",type="unsigned char [2]"}] -stack-list-arguments, no switch vs new switch: -stack-list-arguments --simple-values ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"},{name="s",type="char *",value="<unavailable>"}]},frame={level="1",args=[]}] -stack-list-arguments --skip-unavailable --simple-values ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"}]},frame={level="1",args=[]}] -stack-list-variables, no switch vs new switch: -stack-list-variables --simple-values ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="s",arg="1",type="char *",value="<unavailable>"},{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}] -stack-list-variables --skip-unavailable --simple-values ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="array",type="unsigned char [2]"}] tests are added to test these new options. gdb: 2013-07-03 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype. (parse_no_frames_option): Remove. (mi_cmd_stack_list_locals): Handle --skip-unavailable. (mi_cmd_stack_list_args): Adjust. (mi_cmd_stack_list_variables): Handle --skip-unavailable. (list_args_or_locals): New parameter 'skip_unavailable'. Handle it. * valprint.c (scalar_type_p): Rename to ... (val_print_scalar_type_p): ... this. Make extern. (val_print, value_check_printable): Adjust. * valprint.h (val_print_scalar_type_p): Declare. * value.c (value_entirely_unavailable): New function. * value.h (value_entirely_unavailable): Declare. * NEWS: Mention the new option "--skip-unavailable" to these MI commands. gdb/doc: 2013-07-03 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (GDB/MI Stack Manipulation)<-stack-list-locals>: Document new --skip-unavailable option. <-stack-list-arguments>: Likewise. <-stack-list-variables>: Likewise. gdb/testsuite: 2013-07-03 Yao Qi <yao@codesourcery.com> * gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable): Add tests for new option '--skip-unavailable'. --- gdb/NEWS | 5 + gdb/doc/gdb.texinfo | 17 ++- gdb/mi/mi-cmd-stack.c | 161 ++++++++++++++-------- gdb/testsuite/gdb.trace/mi-trace-unavailable.exp | 9 ++ gdb/valprint.c | 8 +- gdb/valprint.h | 2 + gdb/value.c | 20 +++ gdb/value.h | 4 + 8 files changed, 164 insertions(+), 62 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index e469f1e..8309c8b 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -84,6 +84,11 @@ show range-stepping ** The new command -trace-frame-collected dumps collected variables, computed expressions, tvars, memory and registers in a traceframe. + ** The commands -stack-list-locals, -stack-list-arguments and + -stack-list-variables now accept an optional "--skip-unavailable" + option. When used, only the available locals or arguments are + displayed. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index d75a3d1..790c9d2 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -31242,7 +31242,7 @@ For a stack with frame levels 0 through 11: @subsubheading Synopsis @smallexample - -stack-list-arguments [ --no-frame-filters ] @var{print-values} + -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} [ @var{low-frame} @var{high-frame} ] @end smallexample @@ -31262,6 +31262,9 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, arguments that +have not been available are not listed. Partially available objects +are still displayed, however. Use of this command to obtain arguments in a single frame is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31446,7 +31449,7 @@ Show a single frame: @subsubheading Synopsis @smallexample - -stack-list-locals [ --no-frame-filters ] @var{print-values} + -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the local variable names for the selected frame. If @@ -31460,6 +31463,10 @@ other data types when the user wishes to explore their values in more detail. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, local variables +that have not been available are not listed. Partially available +objects are still displayed, however. + This command is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31490,7 +31497,7 @@ This command is deprecated in favor of the @subsubheading Synopsis @smallexample - -stack-list-variables [ --no-frame-filters ] @var{print-values} + -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the names of local variables and function arguments for the selected frame. If @@ -31501,6 +31508,10 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, then, local +variables and arguments that have not been collected are not listed. +Partially available objects are still displayed, however. + @subsubheading Example @smallexample diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 3212c03..1c0464d 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -39,9 +39,10 @@ enum what_to_list { locals, arguments, all }; -static void list_args_or_locals (enum what_to_list what, +static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi); + struct frame_info *fi, + int skip_unavailable); /* True if we want to allow Python-based frame filters. */ static int frame_filters = 0; @@ -54,17 +55,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc) frame_filters = 1; } -/* Parse the --no-frame-filters option in commands where we cannot use - mi_getopt. */ -static int -parse_no_frames_option (const char *arg) -{ - if (arg && (strcmp (arg, "--no-frame-filters") == 0)) - return 1; - - return 0; -} - /* Print a list of the stack frames. Args can be none, in which case we want to print the whole backtrace, or a pair of numbers specifying the frame numbers at which to start and stop the @@ -213,6 +203,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; + int i; if (argc > 1) { @@ -221,11 +213,13 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) char **new_argv = xmalloc ((argc - 1) * sizeof (char *)); enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -249,6 +243,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) { case NO_FRAME_FILTERS: raw_arg = oind; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; break; } } @@ -258,7 +254,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-locals: Usage: [--no-frame-filters] " + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -275,7 +272,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (locals, print_value, frame); + list_args_or_locals (locals, print_value, frame, + skip_unavailable); } } @@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) struct ui_out *uiout = current_uiout; int raw_arg = 0; enum py_bt_status result = PY_BT_ERROR; + int skip_unavailable = 0; + int oind = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + /* We can't use mi_getopt here, because the number of options is not + determined. */ + for (oind = 0; oind < argc; oind++) + { + int found = 0; - if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg)) + if (strcmp (argv[oind], "--no-frame-filters") == 0) + { + raw_arg = oind + 1; + found = 1; + } + else if (strcmp (argv[oind], "--skip-unavailable") == 0) + { + skip_unavailable = 1; + found = 1; + } + + if (!found) + break; + } + + if (argc - oind != 1 && argc - oind != 3) error (_("-stack-list-arguments: Usage: " \ - "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); + "[--no-frame-filters] [--skip-unavailable] " + "PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); - if (argc >= 3) + if (argc - oind == 3) { - frame_low = atoi (argv[1 + raw_arg]); - frame_high = atoi (argv[2 + raw_arg]); + frame_low = atoi (argv[1 + oind]); + frame_high = atoi (argv[2 + oind]); } else { @@ -316,7 +335,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) frame_high = -1; } - print_values = mi_parse_print_values (argv[raw_arg]); + print_values = mi_parse_print_values (argv[oind]); /* Let's position fi on the frame at which to start the display. Could be the innermost frame if the whole stack needs @@ -362,7 +381,8 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) QUIT; cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); ui_out_field_int (uiout, "level", i); - list_args_or_locals (arguments, print_values, fi); + list_args_or_locals (arguments, print_values, fi, + skip_unavailable); do_cleanups (cleanup_frame); } } @@ -382,6 +402,7 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; if (argc > 1) { @@ -390,11 +411,13 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) char **new_argv = xmalloc ((argc - 1) * sizeof (char *)); enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; cleanup = make_cleanup (xfree, new_argv); @@ -418,6 +441,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) case NO_FRAME_FILTERS: raw_arg = oind; break; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; + break; } } do_cleanups (cleanup); @@ -426,8 +452,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-variables: Usage: " \ - "[--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-variables: Usage: [--no-frame-filters] " \ + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -444,7 +470,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (all, print_value, frame); + list_args_or_locals (all, print_value, frame, + skip_unavailable); } } @@ -525,11 +552,12 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, /* Print a list of the locals or the arguments for the currently selected frame. If the argument passed is 0, printonly the names of the variables, if an argument of 1 is passed, print the values - as well. */ + as well. If SKIP_UNAVAILABLE is true, print the arguments or local + variables whose values are available. */ static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi) + struct frame_info *fi, int skip_unavailable) { struct block *block; struct symbol *sym; @@ -564,6 +592,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values, ALL_BLOCK_SYMBOLS (block, iter, sym) { int print_me = 0; + struct value *val = NULL; switch (SYMBOL_CLASS (sym)) { @@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values, if (print_me) { struct symbol *sym2; - struct frame_arg arg, entryarg; if (SYMBOL_IS_ARGUMENT (sym)) sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), @@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values, sym2 = sym; gdb_assert (sym2 != NULL); - memset (&arg, 0, sizeof (arg)); - arg.sym = sym2; - arg.entry_kind = print_entry_values_no; - memset (&entryarg, 0, sizeof (entryarg)); - entryarg.sym = sym2; - entryarg.entry_kind = print_entry_values_no; - - switch (values) + /* Need to read the value before being able to determine + whether its unavailable. */ + if (values == PRINT_ALL_VALUES + || values == PRINT_SIMPLE_VALUES + || skip_unavailable) + val = read_var_value (sym2, fi); + + if (skip_unavailable + && (value_entirely_unavailable (val) + /* A scalar object that does not have all bits + available is also considered unavailable, + because all bits contribute to its + representation. */ + || (val_print_scalar_type_p (value_type (val)) + && !value_bytes_available (val, + value_embedded_offset (val), + TYPE_LENGTH (value_type (val)))))) + ; + else { - case PRINT_SIMPLE_VALUES: - type = check_typedef (sym2->type); - if (TYPE_CODE (type) != TYPE_CODE_ARRAY - && TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION) + struct frame_arg arg, entryarg; + + memset (&arg, 0, sizeof (arg)); + arg.sym = sym2; + arg.entry_kind = print_entry_values_no; + memset (&entryarg, 0, sizeof (entryarg)); + entryarg.sym = sym2; + entryarg.entry_kind = print_entry_values_no; + + switch (values) { - case PRINT_ALL_VALUES: - read_frame_arg (sym2, fi, &arg, &entryarg); + case PRINT_SIMPLE_VALUES: + type = check_typedef (sym2->type); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + case PRINT_ALL_VALUES: + read_frame_arg (sym2, fi, &arg, &entryarg); + } + break; } - break; - } - if (arg.entry_kind != print_entry_values_only) - list_arg_or_local (&arg, what, values); - if (entryarg.entry_kind != print_entry_values_no) - list_arg_or_local (&entryarg, what, values); - xfree (arg.error); - xfree (entryarg.error); + if (arg.entry_kind != print_entry_values_only) + list_arg_or_local (&arg, what, values); + if (entryarg.entry_kind != print_entry_values_no) + list_arg_or_local (&entryarg, what, values); + xfree (arg.error); + xfree (entryarg.error); + } } } diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp index 42f6e32..f147899 100644 --- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp +++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp @@ -93,16 +93,25 @@ proc test_trace_unavailable { data_source } { mi_gdb_test "-stack-list-locals --simple-values" \ ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-locals --simple-values" + mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \ + ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-locals --skip-unavailable --simple-values" # Test MI command '-stack-list-arguments'. mi_gdb_test "-stack-list-arguments --simple-values" \ ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \ "-stack-list-arguments --simple-values" + mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \ + ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \ + "-stack-list-arguments --skip-unavailable --simple-values" # Test MI command '-stack-list-variables'. mi_gdb_test "-stack-list-variables --simple-values" \ ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-variables --simple-values" + mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \ + ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-variables --skip-unavailable --simple-values" mi_gdb_test "-trace-find frame-number 1" \ ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \ diff --git a/gdb/valprint.c b/gdb/valprint.c index bc21f4f..2368ea8 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -272,8 +272,8 @@ show_symbol_print (struct ui_file *file, int from_tty, we want to print scalar arguments, but not aggregate arguments. This function distinguishes between the two. */ -static int -scalar_type_p (struct type *type) +int +val_print_scalar_type_p (struct type *type) { CHECK_TYPEDEF (type); while (TYPE_CODE (type) == TYPE_CODE_REF) @@ -767,7 +767,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* Handle summary mode. If the value is a scalar, print it; otherwise, print an ellipsis. */ - if (options->summary && !scalar_type_p (type)) + if (options->summary && !val_print_scalar_type_p (type)) { fprintf_filtered (stream, "..."); return; @@ -799,7 +799,7 @@ value_check_printable (struct value *val, struct ui_file *stream, if (value_entirely_optimized_out (val)) { - if (options->summary && !scalar_type_p (value_type (val))) + if (options->summary && !val_print_scalar_type_p (value_type (val))) fprintf_filtered (stream, "..."); else val_print_optimized_out (stream); diff --git a/gdb/valprint.h b/gdb/valprint.h index 7baef2f..eeb0cc4 100644 --- a/gdb/valprint.h +++ b/gdb/valprint.h @@ -209,4 +209,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type, extern void output_command_const (const char *args, int from_tty); +extern int val_print_scalar_type_p (struct type *type); + #endif diff --git a/gdb/value.c b/gdb/value.c index fae8b98..a1b9742 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -352,6 +352,26 @@ value_entirely_available (struct value *value) return 0; } +int +value_entirely_unavailable (struct value *value) +{ + /* We can only tell whether the whole value is available when we try + to read it. */ + if (value->lazy) + value_fetch_lazy (value); + + if (VEC_length (range_s, value->unavailable) == 1) + { + struct range *t = VEC_index (range_s, value->unavailable, 0); + + if (t->offset == 0 + && t->length == TYPE_LENGTH (value_enclosing_type (value))) + return 1; + } + + return 0; +} + void mark_value_bytes_unavailable (struct value *value, int offset, int length) { diff --git a/gdb/value.h b/gdb/value.h index 8a66aa4..c224f10 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -429,6 +429,10 @@ extern int value_bytes_available (const struct value *value, whole object is unavailable. */ extern int value_entirely_available (struct value *value); +/* Like value_entirely_available, but return false if any byte in the + whole object is available. */ +extern int value_entirely_unavailable (struct value *value); + /* Mark VALUE's content bytes starting at OFFSET and extending for LENGTH bytes as unavailable. */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-07-03 1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi @ 2013-07-03 4:14 ` asmwarrior 2013-07-03 5:21 ` Yao Qi 2013-07-03 19:22 ` Eli Zaretskii 1 sibling, 1 reply; 26+ messages in thread From: asmwarrior @ 2013-07-03 4:14 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches For me, when I firstly see this word, an "unavaliable locals" means those local variables which does not constructed. E.g.: void f(void) { ClassA a; some statements; // when your are here, "b" is not constructed. ClassB b; } But I believe you mean(under GDB) the variable which does not have enough info to print. Yuanhui Zhang ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-07-03 4:14 ` asmwarrior @ 2013-07-03 5:21 ` Yao Qi 0 siblings, 0 replies; 26+ messages in thread From: Yao Qi @ 2013-07-03 5:21 UTC (permalink / raw) To: asmwarrior; +Cc: gdb-patches On 07/03/2013 12:20 PM, asmwarrior wrote: > For me, when I firstly see this word, an "unavaliable locals" means those local variables which does not constructed. > E.g.: > void f(void) > { > ClassA a; > some statements; // when your are here, "b" is not constructed. > ClassB b; > } > > But I believe you mean(under GDB) the variable which does not have enough info to print. Right, under the context of GDB, "unavailable locals" means "locals whose value are unavailable". Probably, the subject of this mail should be "Add options to skip locals or arguments whose values are unavailable". -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-07-03 1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi 2013-07-03 4:14 ` asmwarrior @ 2013-07-03 19:22 ` Eli Zaretskii 2013-07-22 1:38 ` Yao Qi 1 sibling, 1 reply; 26+ messages in thread From: Eli Zaretskii @ 2013-07-03 19:22 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches > From: Yao Qi <yao@codesourcery.com> > Date: Wed, 3 Jul 2013 09:48:26 +0800 > > This is the patch to add new option '--skip-unavailable' to MI > commands '-stack-list-{locals, arguments, variables}'. This patch > extends list_args_or_locals to add a new parameter 'skip_unavailable', > and don't list locals or arguments if values are unavailable and > 'skip_unavailable' is true. Thanks. > + ** The commands -stack-list-locals, -stack-list-arguments and > + -stack-list-variables now accept an optional "--skip-unavailable" > + option. When used, only the available locals or arguments are > + displayed. "optional option" doesn't sound right. I think dropping the "optional" part is all you need. > +If the @code{--skip-unavailable} option is specified, arguments that > +have not been available are not listed. Partially available objects ^^^^^^^^^^^^^^^^^^^^^^^ "are not available". And why "objects" instead of "arguments"? > +If the @code{--skip-unavailable} option is specified, local variables > +that have not been available are not listed. Partially available > +objects are still displayed, however. Likewise, on both accounts. There are other places with the same problems. > +If the @code{--skip-unavailable} option is specified, then, local ^^^^^ This "then" and the comma after it should be deleted. OK with those changes. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-07-03 19:22 ` Eli Zaretskii @ 2013-07-22 1:38 ` Yao Qi 2013-08-01 12:33 ` Pedro Alves 0 siblings, 1 reply; 26+ messages in thread From: Yao Qi @ 2013-07-22 1:38 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches On 07/04/2013 03:21 AM, Eli Zaretskii wrote: >> + ** The commands -stack-list-locals, -stack-list-arguments and >> >+ -stack-list-variables now accept an optional "--skip-unavailable" >> >+ option. When used, only the available locals or arguments are >> >+ displayed. > "optional option" doesn't sound right. I think dropping the > "optional" part is all you need. > >> >+If the @code{--skip-unavailable} option is specified, arguments that >> >+have not been available are not listed. Partially available objects > ^^^^^^^^^^^^^^^^^^^^^^^ > "are not available". > > And why "objects" instead of "arguments"? > >> >+If the @code{--skip-unavailable} option is specified, local variables >> >+that have not been available are not listed. Partially available >> >+objects are still displayed, however. > Likewise, on both accounts. There are other places with the same > problems. > >> >+If the @code{--skip-unavailable} option is specified, then, local > ^^^^^ > This "then" and the comma after it should be deleted. > > OK with those changes. Eli, Thanks for the review. The updated patch addresses all your comments on doc bits. Ping for the review to the rest of patches. -- Yao (é½å°§) gdb: 2013-07-22 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype. (parse_no_frames_option): Remove. (mi_cmd_stack_list_locals): Handle --skip-unavailable. (mi_cmd_stack_list_args): Adjust. (mi_cmd_stack_list_variables): Handle --skip-unavailable. (list_args_or_locals): New parameter 'skip_unavailable'. Handle it. * valprint.c (scalar_type_p): Rename to ... (val_print_scalar_type_p): ... this. Make extern. (val_print, value_check_printable): Adjust. * valprint.h (val_print_scalar_type_p): Declare. * value.c (value_entirely_unavailable): New function. * value.h (value_entirely_unavailable): Declare. * NEWS: Mention the new option "--skip-unavailable" to these MI commands. gdb/doc: 2013-07-22 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (GDB/MI Stack Manipulation)<-stack-list-locals>: Document new --skip-unavailable option. <-stack-list-variables>: Document new --skip-unavailable option. gdb/testsuite: 2013-07-22 Yao Qi <yao@codesourcery.com> * gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable): Add tests for new option '--skip-unavailable'. --- gdb/NEWS | 4 + gdb/doc/gdb.texinfo | 17 ++- gdb/mi/mi-cmd-stack.c | 161 ++++++++++++++-------- gdb/testsuite/gdb.trace/mi-trace-unavailable.exp | 9 ++ gdb/valprint.c | 8 +- gdb/valprint.h | 2 + gdb/value.c | 20 +++ gdb/value.h | 4 + 8 files changed, 163 insertions(+), 62 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index a4238d0..342a244 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -89,6 +89,10 @@ show range-stepping ** The new command -trace-frame-collected dumps collected variables, computed expressions, tvars, memory and registers in a traceframe. + ** The commands -stack-list-locals, -stack-list-arguments and + -stack-list-variables now accept an option "--skip-unavailable". + When used, only the available locals or arguments are displayed. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 4caeea5..4d45548 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -31244,7 +31244,7 @@ For a stack with frame levels 0 through 11: @subsubheading Synopsis @smallexample - -stack-list-arguments [ --no-frame-filters ] @var{print-values} + -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} [ @var{low-frame} @var{high-frame} ] @end smallexample @@ -31264,6 +31264,9 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, arguments that +are not available are not listed. Partially available arguments +are still displayed, however. Use of this command to obtain arguments in a single frame is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31448,7 +31451,7 @@ Show a single frame: @subsubheading Synopsis @smallexample - -stack-list-locals [ --no-frame-filters ] @var{print-values} + -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the local variable names for the selected frame. If @@ -31462,6 +31465,10 @@ other data types when the user wishes to explore their values in more detail. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, local variables +that are not available are not listed. Partially available locals +variables are still displayed, however. + This command is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31492,7 +31499,7 @@ This command is deprecated in favor of the @subsubheading Synopsis @smallexample - -stack-list-variables [ --no-frame-filters ] @var{print-values} + -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the names of local variables and function arguments for the selected frame. If @@ -31503,6 +31510,10 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, local variables +and arguments that are not collected are not listed. Partially +available arguments and local variables are still displayed, however. + @subsubheading Example @smallexample diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 5a81bcd..0d565e5 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -39,9 +39,10 @@ enum what_to_list { locals, arguments, all }; -static void list_args_or_locals (enum what_to_list what, +static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi); + struct frame_info *fi, + int skip_unavailable); /* True if we want to allow Python-based frame filters. */ static int frame_filters = 0; @@ -54,17 +55,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc) frame_filters = 1; } -/* Parse the --no-frame-filters option in commands where we cannot use - mi_getopt. */ -static int -parse_no_frames_option (const char *arg) -{ - if (arg && (strcmp (arg, "--no-frame-filters") == 0)) - return 1; - - return 0; -} - /* Print a list of the stack frames. Args can be none, in which case we want to print the whole backtrace, or a pair of numbers specifying the frame numbers at which to start and stop the @@ -213,6 +203,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; + int i; if (argc > 1) { @@ -221,11 +213,13 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) char **new_argv = xmalloc ((argc - 1) * sizeof (char *)); enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -249,6 +243,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) { case NO_FRAME_FILTERS: raw_arg = oind; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; break; } } @@ -258,7 +254,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-locals: Usage: [--no-frame-filters] " + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -275,7 +272,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (locals, print_value, frame); + list_args_or_locals (locals, print_value, frame, + skip_unavailable); } } @@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) struct ui_out *uiout = current_uiout; int raw_arg = 0; enum py_bt_status result = PY_BT_ERROR; + int skip_unavailable = 0; + int oind = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + /* We can't use mi_getopt here, because the number of options is not + determined. */ + for (oind = 0; oind < argc; oind++) + { + int found = 0; - if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg)) + if (strcmp (argv[oind], "--no-frame-filters") == 0) + { + raw_arg = oind + 1; + found = 1; + } + else if (strcmp (argv[oind], "--skip-unavailable") == 0) + { + skip_unavailable = 1; + found = 1; + } + + if (!found) + break; + } + + if (argc - oind != 1 && argc - oind != 3) error (_("-stack-list-arguments: Usage: " \ - "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); + "[--no-frame-filters] [--skip-unavailable] " + "PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); - if (argc >= 3) + if (argc - oind == 3) { - frame_low = atoi (argv[1 + raw_arg]); - frame_high = atoi (argv[2 + raw_arg]); + frame_low = atoi (argv[1 + oind]); + frame_high = atoi (argv[2 + oind]); } else { @@ -316,7 +335,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) frame_high = -1; } - print_values = mi_parse_print_values (argv[raw_arg]); + print_values = mi_parse_print_values (argv[oind]); /* Let's position fi on the frame at which to start the display. Could be the innermost frame if the whole stack needs @@ -362,7 +381,8 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) QUIT; cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); ui_out_field_int (uiout, "level", i); - list_args_or_locals (arguments, print_values, fi); + list_args_or_locals (arguments, print_values, fi, + skip_unavailable); do_cleanups (cleanup_frame); } } @@ -382,6 +402,7 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; if (argc > 1) { @@ -390,11 +411,13 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) char **new_argv = xmalloc ((argc - 1) * sizeof (char *)); enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; cleanup = make_cleanup (xfree, new_argv); @@ -418,6 +441,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) case NO_FRAME_FILTERS: raw_arg = oind; break; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; + break; } } do_cleanups (cleanup); @@ -426,8 +452,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-variables: Usage: " \ - "[--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-variables: Usage: [--no-frame-filters] " \ + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -444,7 +470,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (all, print_value, frame); + list_args_or_locals (all, print_value, frame, + skip_unavailable); } } @@ -525,11 +552,12 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, /* Print a list of the locals or the arguments for the currently selected frame. If the argument passed is 0, printonly the names of the variables, if an argument of 1 is passed, print the values - as well. */ + as well. If SKIP_UNAVAILABLE is true, print the arguments or local + variables whose values are available. */ static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi) + struct frame_info *fi, int skip_unavailable) { struct block *block; struct symbol *sym; @@ -564,6 +592,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values, ALL_BLOCK_SYMBOLS (block, iter, sym) { int print_me = 0; + struct value *val = NULL; switch (SYMBOL_CLASS (sym)) { @@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values, if (print_me) { struct symbol *sym2; - struct frame_arg arg, entryarg; if (SYMBOL_IS_ARGUMENT (sym)) sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), @@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values, sym2 = sym; gdb_assert (sym2 != NULL); - memset (&arg, 0, sizeof (arg)); - arg.sym = sym2; - arg.entry_kind = print_entry_values_no; - memset (&entryarg, 0, sizeof (entryarg)); - entryarg.sym = sym2; - entryarg.entry_kind = print_entry_values_no; - - switch (values) + /* Need to read the value before being able to determine + whether its unavailable. */ + if (values == PRINT_ALL_VALUES + || values == PRINT_SIMPLE_VALUES + || skip_unavailable) + val = read_var_value (sym2, fi); + + if (skip_unavailable + && (value_entirely_unavailable (val) + /* A scalar object that does not have all bits + available is also considered unavailable, + because all bits contribute to its + representation. */ + || (val_print_scalar_type_p (value_type (val)) + && !value_bytes_available (val, + value_embedded_offset (val), + TYPE_LENGTH (value_type (val)))))) + ; + else { - case PRINT_SIMPLE_VALUES: - type = check_typedef (sym2->type); - if (TYPE_CODE (type) != TYPE_CODE_ARRAY - && TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION) + struct frame_arg arg, entryarg; + + memset (&arg, 0, sizeof (arg)); + arg.sym = sym2; + arg.entry_kind = print_entry_values_no; + memset (&entryarg, 0, sizeof (entryarg)); + entryarg.sym = sym2; + entryarg.entry_kind = print_entry_values_no; + + switch (values) { - case PRINT_ALL_VALUES: - read_frame_arg (sym2, fi, &arg, &entryarg); + case PRINT_SIMPLE_VALUES: + type = check_typedef (sym2->type); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + case PRINT_ALL_VALUES: + read_frame_arg (sym2, fi, &arg, &entryarg); + } + break; } - break; - } - if (arg.entry_kind != print_entry_values_only) - list_arg_or_local (&arg, what, values); - if (entryarg.entry_kind != print_entry_values_no) - list_arg_or_local (&entryarg, what, values); - xfree (arg.error); - xfree (entryarg.error); + if (arg.entry_kind != print_entry_values_only) + list_arg_or_local (&arg, what, values); + if (entryarg.entry_kind != print_entry_values_no) + list_arg_or_local (&entryarg, what, values); + xfree (arg.error); + xfree (entryarg.error); + } } } diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp index 42f6e32..f147899 100644 --- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp +++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp @@ -93,16 +93,25 @@ proc test_trace_unavailable { data_source } { mi_gdb_test "-stack-list-locals --simple-values" \ ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-locals --simple-values" + mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \ + ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-locals --skip-unavailable --simple-values" # Test MI command '-stack-list-arguments'. mi_gdb_test "-stack-list-arguments --simple-values" \ ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \ "-stack-list-arguments --simple-values" + mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \ + ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \ + "-stack-list-arguments --skip-unavailable --simple-values" # Test MI command '-stack-list-variables'. mi_gdb_test "-stack-list-variables --simple-values" \ ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-variables --simple-values" + mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \ + ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-variables --skip-unavailable --simple-values" mi_gdb_test "-trace-find frame-number 1" \ ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \ diff --git a/gdb/valprint.c b/gdb/valprint.c index 753ae34..0f6d65e 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -275,8 +275,8 @@ show_symbol_print (struct ui_file *file, int from_tty, we want to print scalar arguments, but not aggregate arguments. This function distinguishes between the two. */ -static int -scalar_type_p (struct type *type) +int +val_print_scalar_type_p (struct type *type) { CHECK_TYPEDEF (type); while (TYPE_CODE (type) == TYPE_CODE_REF) @@ -770,7 +770,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* Handle summary mode. If the value is a scalar, print it; otherwise, print an ellipsis. */ - if (options->summary && !scalar_type_p (type)) + if (options->summary && !val_print_scalar_type_p (type)) { fprintf_filtered (stream, "..."); return; @@ -802,7 +802,7 @@ value_check_printable (struct value *val, struct ui_file *stream, if (value_entirely_optimized_out (val)) { - if (options->summary && !scalar_type_p (value_type (val))) + if (options->summary && !val_print_scalar_type_p (value_type (val))) fprintf_filtered (stream, "..."); else val_print_optimized_out (stream); diff --git a/gdb/valprint.h b/gdb/valprint.h index 2959098..e7073b6 100644 --- a/gdb/valprint.h +++ b/gdb/valprint.h @@ -211,4 +211,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type, extern void output_command_const (const char *args, int from_tty); +extern int val_print_scalar_type_p (struct type *type); + #endif diff --git a/gdb/value.c b/gdb/value.c index 04f325f..54d4232 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -353,6 +353,26 @@ value_entirely_available (struct value *value) return 0; } +int +value_entirely_unavailable (struct value *value) +{ + /* We can only tell whether the whole value is available when we try + to read it. */ + if (value->lazy) + value_fetch_lazy (value); + + if (VEC_length (range_s, value->unavailable) == 1) + { + struct range *t = VEC_index (range_s, value->unavailable, 0); + + if (t->offset == 0 + && t->length == TYPE_LENGTH (value_enclosing_type (value))) + return 1; + } + + return 0; +} + void mark_value_bytes_unavailable (struct value *value, int offset, int length) { diff --git a/gdb/value.h b/gdb/value.h index 5e00c89..5197df9 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -435,6 +435,10 @@ extern int value_bytes_available (const struct value *value, whole object is unavailable. */ extern int value_entirely_available (struct value *value); +/* Like value_entirely_available, but return false if any byte in the + whole object is available. */ +extern int value_entirely_unavailable (struct value *value); + /* Mark VALUE's content bytes starting at OFFSET and extending for LENGTH bytes as unavailable. */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-07-22 1:38 ` Yao Qi @ 2013-08-01 12:33 ` Pedro Alves 2013-08-01 13:59 ` Yao Qi 2013-08-25 3:43 ` [PATCH 0/2 v2] " Yao Qi 0 siblings, 2 replies; 26+ messages in thread From: Pedro Alves @ 2013-08-01 12:33 UTC (permalink / raw) To: Yao Qi; +Cc: Eli Zaretskii, gdb-patches On 07/22/2013 02:37 AM, Yao Qi wrote: > 2013-07-22 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype. > (parse_no_frames_option): Remove. > (mi_cmd_stack_list_locals): Handle --skip-unavailable. > (mi_cmd_stack_list_args): Adjust. > (mi_cmd_stack_list_variables): Handle --skip-unavailable. > (list_args_or_locals): New parameter 'skip_unavailable'. > Handle it. > * valprint.c (scalar_type_p): Rename to ... > (val_print_scalar_type_p): ... this. Make extern. > (val_print, value_check_printable): Adjust. > * valprint.h (val_print_scalar_type_p): Declare. > * value.c (value_entirely_unavailable): New function. > * value.h (value_entirely_unavailable): Declare. > > * NEWS: Mention the new option "--skip-unavailable" to these > MI commands. Hmm, this "these" reads out of nowhere. "Which these?" > > gdb/doc: > > 2013-07-22 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * gdb.texinfo (GDB/MI Stack Manipulation)<-stack-list-locals>: Space before "<". > Document new --skip-unavailable option. > <-stack-list-variables>: Document new --skip-unavailable option. > > +If the @code{--skip-unavailable} option is specified, local variables > +that are not available are not listed. Partially available locals > +variables are still displayed, however. s/available locals variables/available local variables/ > +If the @code{--skip-unavailable} option is specified, local variables > +and arguments that are not collected are not listed. This still says "that are not collected". I think it should say "that that are not available", like the other bits (and similarly to the adjustment done in other patches, IIRC). > @@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) > struct ui_out *uiout = current_uiout; > int raw_arg = 0; > enum py_bt_status result = PY_BT_ERROR; > + int skip_unavailable = 0; > + int oind = 0; > > - if (argc > 0) > - raw_arg = parse_no_frames_option (argv[0]); > + /* We can't use mi_getopt here, because the number of options is not > + determined. */ Hmm. Isn't that easy to fix though? We'd just need an mi_getopt variant that doesn't error out when it sees an unknown option, but instead returns that option's position (similarly to getopt). It's then the caller's responsibility to parse the rest of the option string. > + for (oind = 0; oind < argc; oind++) > + { > + int found = 0; > > - if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg)) > + if (strcmp (argv[oind], "--no-frame-filters") == 0) > + { > + raw_arg = oind + 1; > + found = 1; > + } > + else if (strcmp (argv[oind], "--skip-unavailable") == 0) > + { > + skip_unavailable = 1; > + found = 1; > + } > + > + if (!found) > + break; > + } > + > + if (argc - oind != 1 && argc - oind != 3) > error (_("-stack-list-arguments: Usage: " \ > - "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); > + "[--no-frame-filters] [--skip-unavailable] " > + "PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); > > - if (argc >= 3) > + if (argc - oind == 3) > { > - frame_low = atoi (argv[1 + raw_arg]); > - frame_high = atoi (argv[2 + raw_arg]); > + frame_low = atoi (argv[1 + oind]); > + frame_high = atoi (argv[2 + oind]); > } > else > { > @@ -316,7 +335,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) > frame_high = -1; > } > > @@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values, > if (print_me) > { > struct symbol *sym2; > - struct frame_arg arg, entryarg; > > if (SYMBOL_IS_ARGUMENT (sym)) > sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), > @@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values, > sym2 = sym; > gdb_assert (sym2 != NULL); > > - memset (&arg, 0, sizeof (arg)); > - arg.sym = sym2; > - arg.entry_kind = print_entry_values_no; > - memset (&entryarg, 0, sizeof (entryarg)); > - entryarg.sym = sym2; > - entryarg.entry_kind = print_entry_values_no; > - > - switch (values) > + /* Need to read the value before being able to determine > + whether its unavailable. */ > + if (values == PRINT_ALL_VALUES > + || values == PRINT_SIMPLE_VALUES > + || skip_unavailable) > + val = read_var_value (sym2, fi); > + > + if (skip_unavailable > + && (value_entirely_unavailable (val) > + /* A scalar object that does not have all bits > + available is also considered unavailable, > + because all bits contribute to its > + representation. */ > + || (val_print_scalar_type_p (value_type (val)) > + && !value_bytes_available (val, > + value_embedded_offset (val), > + TYPE_LENGTH (value_type (val)))))) > + ; > + else I don't think this has been updated right for entry values. With entry values, we now have _two_ values to account for. I think we need to do this once for each of the regular arg and the entry arg? > { > - case PRINT_SIMPLE_VALUES: > - type = check_typedef (sym2->type); > - if (TYPE_CODE (type) != TYPE_CODE_ARRAY > - && TYPE_CODE (type) != TYPE_CODE_STRUCT > - && TYPE_CODE (type) != TYPE_CODE_UNION) > + struct frame_arg arg, entryarg; > + > + memset (&arg, 0, sizeof (arg)); > + arg.sym = sym2; > + arg.entry_kind = print_entry_values_no; > + memset (&entryarg, 0, sizeof (entryarg)); > + entryarg.sym = sym2; > + entryarg.entry_kind = print_entry_values_no; > + > + switch (values) > { > - case PRINT_ALL_VALUES: > - read_frame_arg (sym2, fi, &arg, &entryarg); > + case PRINT_SIMPLE_VALUES: > + type = check_typedef (sym2->type); > + if (TYPE_CODE (type) != TYPE_CODE_ARRAY > + && TYPE_CODE (type) != TYPE_CODE_STRUCT > + && TYPE_CODE (type) != TYPE_CODE_UNION) > + { > + case PRINT_ALL_VALUES: > + read_frame_arg (sym2, fi, &arg, &entryarg); > + } > + break; > } > - break; > - } > > - if (arg.entry_kind != print_entry_values_only) > - list_arg_or_local (&arg, what, values); > - if (entryarg.entry_kind != print_entry_values_no) > - list_arg_or_local (&entryarg, what, values); > - xfree (arg.error); > - xfree (entryarg.error); > + if (arg.entry_kind != print_entry_values_only) > + list_arg_or_local (&arg, what, values); > + if (entryarg.entry_kind != print_entry_values_no) > + list_arg_or_local (&entryarg, what, values); > + xfree (arg.error); > + xfree (entryarg.error); > + } > } > } > -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-08-01 12:33 ` Pedro Alves @ 2013-08-01 13:59 ` Yao Qi 2013-08-01 14:47 ` Pedro Alves 2013-08-25 3:43 ` [PATCH 0/2 v2] " Yao Qi 1 sibling, 1 reply; 26+ messages in thread From: Yao Qi @ 2013-08-01 13:59 UTC (permalink / raw) To: Pedro Alves; +Cc: Eli Zaretskii, gdb-patches On 08/01/2013 08:33 PM, Pedro Alves wrote: >> + if (skip_unavailable >> >+ && (value_entirely_unavailable (val) >> >+ /* A scalar object that does not have all bits >> >+ available is also considered unavailable, >> >+ because all bits contribute to its >> >+ representation. */ >> >+ || (val_print_scalar_type_p (value_type (val)) >> >+ && !value_bytes_available (val, >> >+ value_embedded_offset (val), >> >+ TYPE_LENGTH (value_type (val)))))) >> >+ ; >> >+ else > I don't think this has been updated right for entry values. With > entry values, we now have_two_ values to account for. I think > we need to do this once for each of the regular arg and the > entry arg? > OK, will update the patch to handle both regular arg and entry value. Is it possible that one is available and the other is not? If yes, when option '--skip-unavailable' is used, some thing we have to think about, 1. if regular arg is available but entry is unavailable, like this, {name="j",type="int",value="4"},{name="j@entry",type="int",value="<unavailable>"} what is the expected output? how about displaying regular arg only as it is available? like: {name="j",type="int",value="4"} 2. if entry is available but regular arg is not, like this, {name="j",type="int",value="<unavailable>"},{name="j@entry",type="int",value="4"} what is the expected output? how about displaying entry value only as it is available? like: {name="j@entry",type="int",value="4"} -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-08-01 13:59 ` Yao Qi @ 2013-08-01 14:47 ` Pedro Alves 0 siblings, 0 replies; 26+ messages in thread From: Pedro Alves @ 2013-08-01 14:47 UTC (permalink / raw) To: Yao Qi; +Cc: Eli Zaretskii, gdb-patches On 08/01/2013 02:59 PM, Yao Qi wrote: > On 08/01/2013 08:33 PM, Pedro Alves wrote: >> I don't think this has been updated right for entry values. With >> entry values, we now have_two_ values to account for. I think >> we need to do this once for each of the regular arg and the >> entry arg? >> > > OK, will update the patch to handle both regular arg and entry value. > > Is it possible that one is available and the other is not? Sure. The debug info just tells us where to fetch the entry value from (registers, memory, etc.) just like the regular arg. So it'll depend on which chunks of memory/registers have been collected. > If yes, > when option '--skip-unavailable' is used, some thing we have to think about, > > 1. if regular arg is available but entry is unavailable, like this, > > > {name="j",type="int",value="4"},{name="j@entry",type="int",value="<unavailable>"} > > what is the expected output? how about displaying regular arg only as > it is available? like: > > {name="j",type="int",value="4"} > > 2. if entry is available but regular arg is not, like this, > > > {name="j",type="int",value="<unavailable>"},{name="j@entry",type="int",value="4"} > > what is the expected output? how about displaying entry value only as it > is available? like: > > {name="j@entry",type="int",value="4"} > Yes, that's what I'd expect. -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 0/2 v2] Add options to skip unavailable locals 2013-08-01 12:33 ` Pedro Alves 2013-08-01 13:59 ` Yao Qi @ 2013-08-25 3:43 ` Yao Qi 2013-08-25 3:43 ` [PATCH 2/2] " Yao Qi 2013-08-25 3:43 ` [PATCH 1/2] Use mi_getopt_silent Yao Qi 1 sibling, 2 replies; 26+ messages in thread From: Yao Qi @ 2013-08-25 3:43 UTC (permalink / raw) To: gdb-patches Hi, In the review to '[PATCH 2/2] Add options to skip unavailable locals', Pedro pointed out two things here <http://sourceware.org/ml/gdb-patches/2013-08/msg00019.html> On 08/01/2013 08:33 PM, Pedro Alves wrote:>> @@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) >> > struct ui_out *uiout = current_uiout; >> > int raw_arg = 0; >> > enum py_bt_status result = PY_BT_ERROR; >> >+ int skip_unavailable = 0; >> >+ int oind = 0; >> > >> >- if (argc > 0) >> >- raw_arg = parse_no_frames_option (argv[0]); >> >+ /* We can't use mi_getopt here, because the number of options is not >> >+ determined. */ > Hmm. Isn't that easy to fix though? We'd just need an mi_getopt > variant that doesn't error out when it sees an unknown option, but > instead returns that option's position (similarly to getopt). It's > then the caller's responsibility to parse the rest of the option > string. I add a variant mi_getopt_silent in patch 1/2 and use it here. >> >@@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values, >> > if (print_me) >> > { >> > struct symbol *sym2; >> >- struct frame_arg arg, entryarg; >> > >> > if (SYMBOL_IS_ARGUMENT (sym)) >> > sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), >> >@@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values, >> > sym2 = sym; >> > gdb_assert (sym2 != NULL); >> > >> >- memset (&arg, 0, sizeof (arg)); >> >- arg.sym = sym2; >> >- arg.entry_kind = print_entry_values_no; >> >- memset (&entryarg, 0, sizeof (entryarg)); >> >- entryarg.sym = sym2; >> >- entryarg.entry_kind = print_entry_values_no; >> >- >> >- switch (values) >> >+ /* Need to read the value before being able to determine >> >+ whether its unavailable. */ >> >+ if (values == PRINT_ALL_VALUES >> >+ || values == PRINT_SIMPLE_VALUES >> >+ || skip_unavailable) >> >+ val = read_var_value (sym2, fi); >> >+ >> >+ if (skip_unavailable >> >+ && (value_entirely_unavailable (val) >> >+ /* A scalar object that does not have all bits >> >+ available is also considered unavailable, >> >+ because all bits contribute to its >> >+ representation. */ >> >+ || (val_print_scalar_type_p (value_type (val)) >> >+ && !value_bytes_available (val, >> >+ value_embedded_offset (val), >> >+ TYPE_LENGTH (value_type (val)))))) >> >+ ; >> >+ else > I don't think this has been updated right for entry values. With > entry values, we now have_two_ values to account for. I think > we need to do this once for each of the regular arg and the > entry arg? > Patch 2/2 is updated to handle entry values by adding a parameter 'skip_unavailable' in function list_arg_or_local. Other comments on changelog and doc are addressed too. Regression tested on x86_64-linux both native and gdbserver. *** BLURB HERE *** Yao Qi (2): Use mi_getopt_silent Add options to skip unavailable locals gdb/NEWS | 4 + gdb/doc/gdb.texinfo | 17 +++- gdb/mi/mi-cmd-stack.c | 127 +++++++++++++++------- gdb/mi/mi-getopt.c | 35 +++++- gdb/mi/mi-getopt.h | 8 +- gdb/testsuite/gdb.trace/entry-values.exp | 5 + gdb/testsuite/gdb.trace/mi-trace-unavailable.exp | 9 ++ gdb/valprint.c | 8 +- gdb/valprint.h | 2 + gdb/value.c | 20 ++++ gdb/value.h | 4 + 11 files changed, 185 insertions(+), 54 deletions(-) -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 2/2] Add options to skip unavailable locals 2013-08-25 3:43 ` [PATCH 0/2 v2] " Yao Qi @ 2013-08-25 3:43 ` Yao Qi 2013-08-26 16:40 ` Pedro Alves 2013-08-25 3:43 ` [PATCH 1/2] Use mi_getopt_silent Yao Qi 1 sibling, 1 reply; 26+ messages in thread From: Yao Qi @ 2013-08-25 3:43 UTC (permalink / raw) To: gdb-patches V2: Add a new parameter 'skip_unavailable' in function list_arg_or_local, and return early if ARG is unavailable and SKIP_UNAVAILABLE is true. This is the patch to add new option '--skip-unavailable' to MI commands '-stack-list-{locals, arguments, variables}'. This patch extends list_args_or_locals to add a new parameter 'skip_unavailable', and don't list locals or arguments if values are unavailable and 'skip_unavailable' is true. This is inspecting a trace frame (tfind mode), where only a few locals have been collected. -stack-list-locals, no switch vs new switch: -stack-list-locals --simple-values ^done,locals=[{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}] -stack-list-locals --skip-unavailable --simple-values ^done,locals=[{name="array",type="unsigned char [2]"}] -stack-list-arguments, no switch vs new switch: -stack-list-arguments --simple-values ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"},{name="s",type="char *",value="<unavailable>"}]},frame={level="1",args=[]}] -stack-list-arguments --skip-unavailable --simple-values ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"}]},frame={level="1",args=[]}] -stack-list-variables, no switch vs new switch: -stack-list-variables --simple-values ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="s",arg="1",type="char *",value="<unavailable>"},{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}] -stack-list-variables --skip-unavailable --simple-values ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="array",type="unsigned char [2]"}] tests are added to test these new options. Doc bits were reviewed by Eli <http://sourceware.org/ml/gdb-patches/2013-07/msg00154.html> and all comments were addressed. gdb: 2013-08-24 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype. (parse_no_frames_option): Remove. (mi_cmd_stack_list_locals): Handle --skip-unavailable. (mi_cmd_stack_list_args): Adjust. (mi_cmd_stack_list_variables): Handle --skip-unavailable. (list_arg_or_local): Add new parameter 'skip_unavailable'. Return early if SKIP_UNAVAILABLE is true and ARG->val is unavailable. Caller update. (list_args_or_locals): New parameter 'skip_unavailable'. Handle it. * valprint.c (scalar_type_p): Rename to ... (val_print_scalar_type_p): ... this. Make extern. (val_print, value_check_printable): Adjust. * valprint.h (val_print_scalar_type_p): Declare. * value.c (value_entirely_unavailable): New function. * value.h (value_entirely_unavailable): Declare. * NEWS: Mention the new option "--skip-unavailable" to MI commands '-stack-list-locals' '-stack-list-arguments' and '-stack-list-variables'. gdb/doc: 2013-08-24 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (GDB/MI Stack Manipulation) <-stack-list-locals>: Document new --skip-unavailable option. <-stack-list-variables>: Document new --skip-unavailable option. gdb/testsuite: 2013-08-24 Yao Qi <yao@codesourcery.com> * gdb.trace/entry-values.exp: Test unavailable entry value is not shown when option '--skip-unavailable' is specified. * gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable): Add tests for new option '--skip-unavailable'. --- gdb/NEWS | 4 + gdb/doc/gdb.texinfo | 17 ++++- gdb/mi/mi-cmd-stack.c | 77 ++++++++++++++++------ gdb/testsuite/gdb.trace/entry-values.exp | 5 ++ gdb/testsuite/gdb.trace/mi-trace-unavailable.exp | 9 +++ gdb/valprint.c | 8 +- gdb/valprint.h | 2 + gdb/value.c | 20 ++++++ gdb/value.h | 4 + 9 files changed, 119 insertions(+), 27 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index f246ee1..f47eba5 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -91,6 +91,10 @@ show range-stepping ** The new command -trace-frame-collected dumps collected variables, computed expressions, tvars, memory and registers in a traceframe. + ** The commands -stack-list-locals, -stack-list-arguments and + -stack-list-variables now accept an option "--skip-unavailable". + When used, only the available locals or arguments are displayed. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6d5dec4..7ec3dfb 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -31249,7 +31249,7 @@ For a stack with frame levels 0 through 11: @subsubheading Synopsis @smallexample - -stack-list-arguments [ --no-frame-filters ] @var{print-values} + -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} [ @var{low-frame} @var{high-frame} ] @end smallexample @@ -31269,6 +31269,9 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, arguments that +are not available are not listed. Partially available arguments +are still displayed, however. Use of this command to obtain arguments in a single frame is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31453,7 +31456,7 @@ Show a single frame: @subsubheading Synopsis @smallexample - -stack-list-locals [ --no-frame-filters ] @var{print-values} + -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the local variable names for the selected frame. If @@ -31467,6 +31470,10 @@ other data types when the user wishes to explore their values in more detail. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, local variables +that are not available are not listed. Partially available local +variables are still displayed, however. + This command is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31497,7 +31504,7 @@ This command is deprecated in favor of the @subsubheading Synopsis @smallexample - -stack-list-variables [ --no-frame-filters ] @var{print-values} + -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the names of local variables and function arguments for the selected frame. If @@ -31508,6 +31515,10 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, local variables +and arguments that are not available are not listed. Partially +available arguments and local variables are still displayed, however. + @subsubheading Example @smallexample diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index b280e7d..6b6b8dc 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -39,9 +39,10 @@ enum what_to_list { locals, arguments, all }; -static void list_args_or_locals (enum what_to_list what, +static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi); + struct frame_info *fi, + int skip_unavailable); /* True if we want to allow Python-based frame filters. */ static int frame_filters = 0; @@ -202,17 +203,21 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; + int i; if (argc > 1) { int i; enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -229,6 +234,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) { case NO_FRAME_FILTERS: raw_arg = oind; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; break; } } @@ -237,7 +244,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-locals: Usage: [--no-frame-filters] " + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -254,7 +262,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (locals, print_value, frame); + list_args_or_locals (locals, print_value, frame, + skip_unavailable); } } @@ -274,14 +283,17 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) struct ui_out *uiout = current_uiout; int raw_arg = 0; int oind = 0; + int skip_unavailable = 0; enum py_bt_status result = PY_BT_ERROR; enum opt { NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -298,12 +310,16 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) case NO_FRAME_FILTERS: raw_arg = oind; break; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; + break; } } if (argc - oind != 1 && argc - oind != 3) error (_("-stack-list-arguments: Usage: " \ - "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); + "[--no-frame-filters] [--skip-unavailable] " + "PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); if (argc - oind == 3) { @@ -364,7 +380,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) QUIT; cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); ui_out_field_int (uiout, "level", i); - list_args_or_locals (arguments, print_values, fi); + list_args_or_locals (arguments, print_values, fi, skip_unavailable); do_cleanups (cleanup_frame); } } @@ -384,17 +400,20 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; if (argc > 1) { int i; enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -411,6 +430,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) case NO_FRAME_FILTERS: raw_arg = oind; break; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; + break; } } } @@ -418,8 +440,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-variables: Usage: " \ - "[--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-variables: Usage: [--no-frame-filters] " \ + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -436,7 +458,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (all, print_value, frame); + list_args_or_locals (all, print_value, frame, + skip_unavailable); } } @@ -444,19 +467,17 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) WHAT and VALUES see list_args_or_locals. Errors are printed as if they would be the parameter value. Use - zeroed ARG iff it should not be printed according to VALUES. */ + zeroed ARG iff it should not be printed according to VALUES. If + SKIP_UNAVAILABLE is true, print ARG if it is available. */ static void list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, - enum print_values values) + enum print_values values, int skip_unavailable) { struct cleanup *old_chain; struct ui_out *uiout = current_uiout; struct ui_file *stb; - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); - gdb_assert (!arg->val || !arg->error); gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL && arg->error == NULL) @@ -467,6 +488,20 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, || (arg->entry_kind == print_entry_values_only && (arg->val || arg->error))); + if (skip_unavailable && arg->val != NULL + && (value_entirely_unavailable (arg->val) + /* A scalar object that does not have all bits available is + also considered unavailable, because all bits contribute + to its representation. */ + || (val_print_scalar_type_p (value_type (arg->val)) + && !value_bytes_available (arg->val, + value_embedded_offset (arg->val), + TYPE_LENGTH (value_type (arg->val)))))) + return; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + if (values != PRINT_NO_VALUES || what == all) make_cleanup_ui_out_tuple_begin_end (uiout, NULL); @@ -516,11 +551,13 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, /* Print a list of the objects for the frame FI in a certain form, which is determined by VALUES. The objects can be locals, - arguments or both, which is determined by WHAT. */ + arguments or both, which is determined by WHAT. If SKIP_UNAVAILABLE + is true, print the arguments or local variables whose values are + available. */ static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi) + struct frame_info *fi, int skip_unavailable) { struct block *block; struct symbol *sym; @@ -623,9 +660,9 @@ list_args_or_locals (enum what_to_list what, enum print_values values, } if (arg.entry_kind != print_entry_values_only) - list_arg_or_local (&arg, what, values); + list_arg_or_local (&arg, what, values, skip_unavailable); if (entryarg.entry_kind != print_entry_values_no) - list_arg_or_local (&entryarg, what, values); + list_arg_or_local (&entryarg, what, values, skip_unavailable); xfree (arg.error); xfree (entryarg.error); } diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp index bb62e5d..85306ad 100644 --- a/gdb/testsuite/gdb.trace/entry-values.exp +++ b/gdb/testsuite/gdb.trace/entry-values.exp @@ -276,4 +276,9 @@ gdb_test "tfind" "Found trace frame 0, .*" "tfind start" # Since 'global2' is not collected, j@entry is expected to be 'unavailable'. gdb_test "bt 1" "#0 .* foo \\(i=\[-\]?$decimal, i@entry=2, j=\[-\]?$decimal, j@entry=<unavailable>\\).*" +# Test that unavailable "j@entry" is not shown when command option +# --skip-unavailable is used. +gdb_test "interpreter-exec mi \"-stack-list-arguments --skip-unavailable --simple-values\"" \ + "\r\n\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"i\",type=\"int\",value=\".*\"},{name=\"i@entry\",type=\"int\",value=\"2\"},{name=\"j\",type=\"int\",value=\".*\"}\\\]},frame=.*\\\].*" + gdb_test "tfind" "Target failed to find requested trace frame\..*" diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp index d96ec8b..c69891b 100644 --- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp +++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp @@ -106,16 +106,25 @@ proc test_trace_unavailable { data_source } { mi_gdb_test "-stack-list-locals --simple-values" \ ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-locals --simple-values" + mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \ + ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-locals --skip-unavailable --simple-values" # Test MI command '-stack-list-arguments'. mi_gdb_test "-stack-list-arguments --simple-values" \ ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \ "-stack-list-arguments --simple-values" + mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \ + ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \ + "-stack-list-arguments --skip-unavailable --simple-values" # Test MI command '-stack-list-variables'. mi_gdb_test "-stack-list-variables --simple-values" \ ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-variables --simple-values" + mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \ + ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-variables --skip-unavailable --simple-values" mi_gdb_test "-trace-find frame-number 1" \ ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \ diff --git a/gdb/valprint.c b/gdb/valprint.c index 753ae34..0f6d65e 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -275,8 +275,8 @@ show_symbol_print (struct ui_file *file, int from_tty, we want to print scalar arguments, but not aggregate arguments. This function distinguishes between the two. */ -static int -scalar_type_p (struct type *type) +int +val_print_scalar_type_p (struct type *type) { CHECK_TYPEDEF (type); while (TYPE_CODE (type) == TYPE_CODE_REF) @@ -770,7 +770,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* Handle summary mode. If the value is a scalar, print it; otherwise, print an ellipsis. */ - if (options->summary && !scalar_type_p (type)) + if (options->summary && !val_print_scalar_type_p (type)) { fprintf_filtered (stream, "..."); return; @@ -802,7 +802,7 @@ value_check_printable (struct value *val, struct ui_file *stream, if (value_entirely_optimized_out (val)) { - if (options->summary && !scalar_type_p (value_type (val))) + if (options->summary && !val_print_scalar_type_p (value_type (val))) fprintf_filtered (stream, "..."); else val_print_optimized_out (stream); diff --git a/gdb/valprint.h b/gdb/valprint.h index 2959098..e7073b6 100644 --- a/gdb/valprint.h +++ b/gdb/valprint.h @@ -211,4 +211,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type, extern void output_command_const (const char *args, int from_tty); +extern int val_print_scalar_type_p (struct type *type); + #endif diff --git a/gdb/value.c b/gdb/value.c index 09ab1bb..d96c07b 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -353,6 +353,26 @@ value_entirely_available (struct value *value) return 0; } +int +value_entirely_unavailable (struct value *value) +{ + /* We can only tell whether the whole value is available when we try + to read it. */ + if (value->lazy) + value_fetch_lazy (value); + + if (VEC_length (range_s, value->unavailable) == 1) + { + struct range *t = VEC_index (range_s, value->unavailable, 0); + + if (t->offset == 0 + && t->length == TYPE_LENGTH (value_enclosing_type (value))) + return 1; + } + + return 0; +} + void mark_value_bytes_unavailable (struct value *value, int offset, int length) { diff --git a/gdb/value.h b/gdb/value.h index bef193c..f03cf76 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -435,6 +435,10 @@ extern int value_bytes_available (const struct value *value, whole object is unavailable. */ extern int value_entirely_available (struct value *value); +/* Like value_entirely_available, but return false if any byte in the + whole object is available. */ +extern int value_entirely_unavailable (struct value *value); + /* Mark VALUE's content bytes starting at OFFSET and extending for LENGTH bytes as unavailable. */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-08-25 3:43 ` [PATCH 2/2] " Yao Qi @ 2013-08-26 16:40 ` Pedro Alves 2013-08-27 5:22 ` Yao Qi 0 siblings, 1 reply; 26+ messages in thread From: Pedro Alves @ 2013-08-26 16:40 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches Looks good to me. A few tiny-tiny suggestions below: > * NEWS: Mention the new option "--skip-unavailable" to MI > commands '-stack-list-locals' '-stack-list-arguments' and ^ Missing comma. > '-stack-list-variables'. > Errors are printed as if they would be the parameter value. Use > - zeroed ARG iff it should not be printed according to VALUES. */ > + zeroed ARG iff it should not be printed according to VALUES. If > + SKIP_UNAVAILABLE is true, print ARG if it is available. */ "is true, only print ARG" > > static void > list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, > - enum print_values values) > + enum print_values values, int skip_unavailable) > { > /* Print a list of the objects for the frame FI in a certain form, > which is determined by VALUES. The objects can be locals, > - arguments or both, which is determined by WHAT. */ > + arguments or both, which is determined by WHAT. If SKIP_UNAVAILABLE > + is true, print the arguments or local variables whose values are > + available. */ "is true, only print the" > > static void > list_args_or_locals (enum what_to_list what, enum print_values values, > - struct frame_info *fi) > + struct frame_info *fi, int skip_unavailable) > { > struct block *block; -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/2] Add options to skip unavailable locals 2013-08-26 16:40 ` Pedro Alves @ 2013-08-27 5:22 ` Yao Qi 0 siblings, 0 replies; 26+ messages in thread From: Yao Qi @ 2013-08-27 5:22 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On 08/27/2013 12:40 AM, Pedro Alves wrote: > Looks good to me. A few tiny-tiny suggestions below: > >> > * NEWS: Mention the new option "--skip-unavailable" to MI >> > commands '-stack-list-locals' '-stack-list-arguments' and > ^ > Missing comma. > Added. >> > '-stack-list-variables'. > > >> > Errors are printed as if they would be the parameter value. Use >> >- zeroed ARG iff it should not be printed according to VALUES. */ >> >+ zeroed ARG iff it should not be printed according to VALUES. If >> >+ SKIP_UNAVAILABLE is true, print ARG if it is available. */ > "is true, only print ARG" > "only" is added here... >> > >> > static void >> > list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, >> >- enum print_values values) >> >+ enum print_values values, int skip_unavailable) >> > { > > >> > /* Print a list of the objects for the frame FI in a certain form, >> > which is determined by VALUES. The objects can be locals, >> >- arguments or both, which is determined by WHAT. */ >> >+ arguments or both, which is determined by WHAT. If SKIP_UNAVAILABLE >> >+ is true, print the arguments or local variables whose values are >> >+ available. */ > "is true, only print the" > and here. Thanks for the review, Pedro. Patch below is what I committed. -- Yao (é½å°§) gdb: 2013-08-27 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype. (parse_no_frames_option): Remove. (mi_cmd_stack_list_locals): Handle --skip-unavailable. (mi_cmd_stack_list_args): Adjust. (mi_cmd_stack_list_variables): Handle --skip-unavailable. (list_arg_or_local): Add new parameter 'skip_unavailable'. Return early if SKIP_UNAVAILABLE is true and ARG->val is unavailable. Caller update. (list_args_or_locals): New parameter 'skip_unavailable'. Handle it. * valprint.c (scalar_type_p): Rename to ... (val_print_scalar_type_p): ... this. Make extern. (val_print, value_check_printable): Adjust. * valprint.h (val_print_scalar_type_p): Declare. * value.c (value_entirely_unavailable): New function. * value.h (value_entirely_unavailable): Declare. * NEWS: Mention the new option "--skip-unavailable" to MI commands '-stack-list-locals', '-stack-list-arguments' and '-stack-list-variables'. gdb/doc: 2013-08-27 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (GDB/MI Stack Manipulation) <-stack-list-locals>: Document new --skip-unavailable option. <-stack-list-variables>: Document new --skip-unavailable option. gdb/testsuite: 2013-08-27 Yao Qi <yao@codesourcery.com> * gdb.trace/entry-values.exp: Test unavailable entry value is not shown when option '--skip-unavailable' is specified. * gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable): Add tests for new option '--skip-unavailable'. --- gdb/NEWS | 4 + gdb/doc/gdb.texinfo | 17 ++++- gdb/mi/mi-cmd-stack.c | 77 ++++++++++++++++------ gdb/testsuite/gdb.trace/entry-values.exp | 5 ++ gdb/testsuite/gdb.trace/mi-trace-unavailable.exp | 9 +++ gdb/valprint.c | 8 +- gdb/valprint.h | 2 + gdb/value.c | 20 ++++++ gdb/value.h | 4 + 9 files changed, 119 insertions(+), 27 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 75016c1..ca8baea 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -93,6 +93,10 @@ show range-stepping ** The new command -trace-frame-collected dumps collected variables, computed expressions, tvars, memory and registers in a traceframe. + ** The commands -stack-list-locals, -stack-list-arguments and + -stack-list-variables now accept an option "--skip-unavailable". + When used, only the available locals or arguments are displayed. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c88ee65..21250fe 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -31249,7 +31249,7 @@ For a stack with frame levels 0 through 11: @subsubheading Synopsis @smallexample - -stack-list-arguments [ --no-frame-filters ] @var{print-values} + -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} [ @var{low-frame} @var{high-frame} ] @end smallexample @@ -31269,6 +31269,9 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, arguments that +are not available are not listed. Partially available arguments +are still displayed, however. Use of this command to obtain arguments in a single frame is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31453,7 +31456,7 @@ Show a single frame: @subsubheading Synopsis @smallexample - -stack-list-locals [ --no-frame-filters ] @var{print-values} + -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the local variable names for the selected frame. If @@ -31467,6 +31470,10 @@ other data types when the user wishes to explore their values in more detail. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, local variables +that are not available are not listed. Partially available local +variables are still displayed, however. + This command is deprecated in favor of the @samp{-stack-list-variables} command. @@ -31497,7 +31504,7 @@ This command is deprecated in favor of the @subsubheading Synopsis @smallexample - -stack-list-variables [ --no-frame-filters ] @var{print-values} + -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values} @end smallexample Display the names of local variables and function arguments for the selected frame. If @@ -31508,6 +31515,10 @@ type and value for simple data types, and the name and type for arrays, structures and unions. If the option @code{--no-frame-filters} is supplied, then Python frame filters will not be executed. +If the @code{--skip-unavailable} option is specified, local variables +and arguments that are not available are not listed. Partially +available arguments and local variables are still displayed, however. + @subsubheading Example @smallexample diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 2df97e2..7bf9ab8 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -39,9 +39,10 @@ enum what_to_list { locals, arguments, all }; -static void list_args_or_locals (enum what_to_list what, +static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi); + struct frame_info *fi, + int skip_unavailable); /* True if we want to allow Python-based frame filters. */ static int frame_filters = 0; @@ -202,17 +203,21 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; + int i; if (argc > 1) { int i; enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -229,6 +234,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) { case NO_FRAME_FILTERS: raw_arg = oind; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; break; } } @@ -237,7 +244,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-locals: Usage: [--no-frame-filters] " + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -254,7 +262,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (locals, print_value, frame); + list_args_or_locals (locals, print_value, frame, + skip_unavailable); } } @@ -274,14 +283,17 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) struct ui_out *uiout = current_uiout; int raw_arg = 0; int oind = 0; + int skip_unavailable = 0; enum py_bt_status result = PY_BT_ERROR; enum opt { NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -298,12 +310,16 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) case NO_FRAME_FILTERS: raw_arg = oind; break; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; + break; } } if (argc - oind != 1 && argc - oind != 3) error (_("-stack-list-arguments: Usage: " \ - "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); + "[--no-frame-filters] [--skip-unavailable] " + "PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); if (argc - oind == 3) { @@ -364,7 +380,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) QUIT; cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); ui_out_field_int (uiout, "level", i); - list_args_or_locals (arguments, print_values, fi); + list_args_or_locals (arguments, print_values, fi, skip_unavailable); do_cleanups (cleanup_frame); } } @@ -384,17 +400,20 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) enum py_bt_status result = PY_BT_ERROR; int print_value; int oind = 0; + int skip_unavailable = 0; if (argc > 1) { int i; enum opt { - NO_FRAME_FILTERS + NO_FRAME_FILTERS, + SKIP_UNAVAILABLE, }; static const struct mi_opt opts[] = { {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + {"-skip-unavailable", SKIP_UNAVAILABLE, 0}, { 0, 0, 0 } }; @@ -411,6 +430,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) case NO_FRAME_FILTERS: raw_arg = oind; break; + case SKIP_UNAVAILABLE: + skip_unavailable = 1; + break; } } } @@ -418,8 +440,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) /* After the last option is parsed, there should be only 'print-values'. */ if (argc - oind != 1) - error (_("-stack-list-variables: Usage: " \ - "[--no-frame-filters] PRINT_VALUES")); + error (_("-stack-list-variables: Usage: [--no-frame-filters] " \ + "[--skip-unavailable] PRINT_VALUES")); frame = get_selected_frame (NULL); print_value = mi_parse_print_values (argv[oind]); @@ -436,7 +458,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) if "--no-frame-filters" has been specified from the command. */ if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) { - list_args_or_locals (all, print_value, frame); + list_args_or_locals (all, print_value, frame, + skip_unavailable); } } @@ -444,19 +467,17 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) WHAT and VALUES see list_args_or_locals. Errors are printed as if they would be the parameter value. Use - zeroed ARG iff it should not be printed according to VALUES. */ + zeroed ARG iff it should not be printed according to VALUES. If + SKIP_UNAVAILABLE is true, only print ARG if it is available. */ static void list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, - enum print_values values) + enum print_values values, int skip_unavailable) { struct cleanup *old_chain; struct ui_out *uiout = current_uiout; struct ui_file *stb; - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); - gdb_assert (!arg->val || !arg->error); gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL && arg->error == NULL) @@ -467,6 +488,20 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, || (arg->entry_kind == print_entry_values_only && (arg->val || arg->error))); + if (skip_unavailable && arg->val != NULL + && (value_entirely_unavailable (arg->val) + /* A scalar object that does not have all bits available is + also considered unavailable, because all bits contribute + to its representation. */ + || (val_print_scalar_type_p (value_type (arg->val)) + && !value_bytes_available (arg->val, + value_embedded_offset (arg->val), + TYPE_LENGTH (value_type (arg->val)))))) + return; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + if (values != PRINT_NO_VALUES || what == all) make_cleanup_ui_out_tuple_begin_end (uiout, NULL); @@ -516,11 +551,13 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, /* Print a list of the objects for the frame FI in a certain form, which is determined by VALUES. The objects can be locals, - arguments or both, which is determined by WHAT. */ + arguments or both, which is determined by WHAT. If SKIP_UNAVAILABLE + is true, only print the arguments or local variables whose values + are available. */ static void list_args_or_locals (enum what_to_list what, enum print_values values, - struct frame_info *fi) + struct frame_info *fi, int skip_unavailable) { struct block *block; struct symbol *sym; @@ -623,9 +660,9 @@ list_args_or_locals (enum what_to_list what, enum print_values values, } if (arg.entry_kind != print_entry_values_only) - list_arg_or_local (&arg, what, values); + list_arg_or_local (&arg, what, values, skip_unavailable); if (entryarg.entry_kind != print_entry_values_no) - list_arg_or_local (&entryarg, what, values); + list_arg_or_local (&entryarg, what, values, skip_unavailable); xfree (arg.error); xfree (entryarg.error); } diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp index bb62e5d..85306ad 100644 --- a/gdb/testsuite/gdb.trace/entry-values.exp +++ b/gdb/testsuite/gdb.trace/entry-values.exp @@ -276,4 +276,9 @@ gdb_test "tfind" "Found trace frame 0, .*" "tfind start" # Since 'global2' is not collected, j@entry is expected to be 'unavailable'. gdb_test "bt 1" "#0 .* foo \\(i=\[-\]?$decimal, i@entry=2, j=\[-\]?$decimal, j@entry=<unavailable>\\).*" +# Test that unavailable "j@entry" is not shown when command option +# --skip-unavailable is used. +gdb_test "interpreter-exec mi \"-stack-list-arguments --skip-unavailable --simple-values\"" \ + "\r\n\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"i\",type=\"int\",value=\".*\"},{name=\"i@entry\",type=\"int\",value=\"2\"},{name=\"j\",type=\"int\",value=\".*\"}\\\]},frame=.*\\\].*" + gdb_test "tfind" "Target failed to find requested trace frame\..*" diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp index d96ec8b..c69891b 100644 --- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp +++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp @@ -106,16 +106,25 @@ proc test_trace_unavailable { data_source } { mi_gdb_test "-stack-list-locals --simple-values" \ ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-locals --simple-values" + mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \ + ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-locals --skip-unavailable --simple-values" # Test MI command '-stack-list-arguments'. mi_gdb_test "-stack-list-arguments --simple-values" \ ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \ "-stack-list-arguments --simple-values" + mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \ + ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \ + "-stack-list-arguments --skip-unavailable --simple-values" # Test MI command '-stack-list-variables'. mi_gdb_test "-stack-list-variables --simple-values" \ ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \ "-stack-list-variables --simple-values" + mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \ + ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \ + "-stack-list-variables --skip-unavailable --simple-values" mi_gdb_test "-trace-find frame-number 1" \ ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \ diff --git a/gdb/valprint.c b/gdb/valprint.c index 753ae34..0f6d65e 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -275,8 +275,8 @@ show_symbol_print (struct ui_file *file, int from_tty, we want to print scalar arguments, but not aggregate arguments. This function distinguishes between the two. */ -static int -scalar_type_p (struct type *type) +int +val_print_scalar_type_p (struct type *type) { CHECK_TYPEDEF (type); while (TYPE_CODE (type) == TYPE_CODE_REF) @@ -770,7 +770,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* Handle summary mode. If the value is a scalar, print it; otherwise, print an ellipsis. */ - if (options->summary && !scalar_type_p (type)) + if (options->summary && !val_print_scalar_type_p (type)) { fprintf_filtered (stream, "..."); return; @@ -802,7 +802,7 @@ value_check_printable (struct value *val, struct ui_file *stream, if (value_entirely_optimized_out (val)) { - if (options->summary && !scalar_type_p (value_type (val))) + if (options->summary && !val_print_scalar_type_p (value_type (val))) fprintf_filtered (stream, "..."); else val_print_optimized_out (stream); diff --git a/gdb/valprint.h b/gdb/valprint.h index 2959098..e7073b6 100644 --- a/gdb/valprint.h +++ b/gdb/valprint.h @@ -211,4 +211,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type, extern void output_command_const (const char *args, int from_tty); +extern int val_print_scalar_type_p (struct type *type); + #endif diff --git a/gdb/value.c b/gdb/value.c index 09ab1bb..d96c07b 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -353,6 +353,26 @@ value_entirely_available (struct value *value) return 0; } +int +value_entirely_unavailable (struct value *value) +{ + /* We can only tell whether the whole value is available when we try + to read it. */ + if (value->lazy) + value_fetch_lazy (value); + + if (VEC_length (range_s, value->unavailable) == 1) + { + struct range *t = VEC_index (range_s, value->unavailable, 0); + + if (t->offset == 0 + && t->length == TYPE_LENGTH (value_enclosing_type (value))) + return 1; + } + + return 0; +} + void mark_value_bytes_unavailable (struct value *value, int offset, int length) { diff --git a/gdb/value.h b/gdb/value.h index bef193c..f03cf76 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -435,6 +435,10 @@ extern int value_bytes_available (const struct value *value, whole object is unavailable. */ extern int value_entirely_available (struct value *value); +/* Like value_entirely_available, but return false if any byte in the + whole object is available. */ +extern int value_entirely_unavailable (struct value *value); + /* Mark VALUE's content bytes starting at OFFSET and extending for LENGTH bytes as unavailable. */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 1/2] Use mi_getopt_silent 2013-08-25 3:43 ` [PATCH 0/2 v2] " Yao Qi 2013-08-25 3:43 ` [PATCH 2/2] " Yao Qi @ 2013-08-25 3:43 ` Yao Qi 2013-08-26 8:58 ` Agovic, Sanimir 2013-08-26 16:22 ` Pedro Alves 1 sibling, 2 replies; 26+ messages in thread From: Yao Qi @ 2013-08-25 3:43 UTC (permalink / raw) To: gdb-patches This patch is to add a new function mi_getopt_silent, which returns -1 silently (without throwing error) when unknown option is met, and use this function to parse options for command '-stack-list-arguments'. It makes easier to add a new option in patch 2/2. gdb: 2013-08-24 Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (parse_no_frames_option): Remove. (mi_cmd_stack_list_args): Use mi_getopt_silent to handle options. * mi/mi-getopt.c (mi_getopt): Remove. (mi_getopt_1): Renamed from mi_getopt. Add one parameter 'error_on_unknown'. (mi_getopt): Call mi_getopt_1. (mi_getopt_silent): New. * mi/mi-getopt.h (mi_getopt_silent): Declare. --- gdb/mi/mi-cmd-stack.c | 50 ++++++++++++++++++++++++++++++------------------ gdb/mi/mi-getopt.c | 35 ++++++++++++++++++++++++++++----- gdb/mi/mi-getopt.h | 8 +++++- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index e542fc1..b280e7d 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -54,17 +54,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc) frame_filters = 1; } -/* Parse the --no-frame-filters option in commands where we cannot use - mi_getopt. */ -static int -parse_no_frames_option (const char *arg) -{ - if (arg && (strcmp (arg, "--no-frame-filters") == 0)) - return 1; - - return 0; -} - /* Print a list of the stack frames. Args can be none, in which case we want to print the whole backtrace, or a pair of numbers specifying the frame numbers at which to start and stop the @@ -284,19 +273,42 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) enum print_values print_values; struct ui_out *uiout = current_uiout; int raw_arg = 0; + int oind = 0; enum py_bt_status result = PY_BT_ERROR; + enum opt + { + NO_FRAME_FILTERS, + }; + static const struct mi_opt opts[] = + { + {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + { 0, 0, 0 } + }; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + while (1) + { + char *oarg; + int opt = mi_getopt_silent ("-stack-list-args", argc, argv, opts, + &oind, &oarg); + + if (opt < 0) + break; + switch ((enum opt) opt) + { + case NO_FRAME_FILTERS: + raw_arg = oind; + break; + } + } - if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg)) - error (_("-stack-list-arguments: Usage: " \ + if (argc - oind != 1 && argc - oind != 3) + error (_("-stack-list-arguments: Usage: " \ "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); - if (argc >= 3) + if (argc - oind == 3) { - frame_low = atoi (argv[1 + raw_arg]); - frame_high = atoi (argv[2 + raw_arg]); + frame_low = atoi (argv[1 + oind]); + frame_high = atoi (argv[2 + oind]); } else { @@ -306,7 +318,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) frame_high = -1; } - print_values = mi_parse_print_values (argv[raw_arg]); + print_values = mi_parse_print_values (argv[oind]); /* Let's position fi on the frame at which to start the display. Could be the innermost frame if the whole stack needs diff --git a/gdb/mi/mi-getopt.c b/gdb/mi/mi-getopt.c index a1e2ccc..0255d22 100644 --- a/gdb/mi/mi-getopt.c +++ b/gdb/mi/mi-getopt.c @@ -21,11 +21,14 @@ #include "mi-getopt.h" #include "gdb_string.h" -int -mi_getopt (const char *prefix, - int argc, char **argv, - const struct mi_opt *opts, - int *oind, char **oarg) +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h. + When there is an unknown option, if ERROR_ON_UNKNOWN is true, it + throws an error, otherwise return -1. */ + +static int +mi_getopt_1 (const char *prefix, int argc, char **argv, + const struct mi_opt *opts, int *oind, char **oarg, + int error_on_unknown) { char *arg; const struct mi_opt *opt; @@ -71,7 +74,27 @@ mi_getopt (const char *prefix, return opt->index; } } - error (_("%s: Unknown option ``%s''"), prefix, arg + 1); + + if (error_on_unknown) + error (_("%s: Unknown option ``%s''"), prefix, arg + 1); + else + return -1; +} + +int +mi_getopt (const char *prefix, + int argc, char **argv, + const struct mi_opt *opts, + int *oind, char **oarg) +{ + return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 1); +} + +int +mi_getopt_silent (const char *prefix, int argc, char **argv, + const struct mi_opt *opts, int *oind, char **oarg) +{ + return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 0); } int diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h index 9600353..cabe488 100644 --- a/gdb/mi/mi-getopt.h +++ b/gdb/mi/mi-getopt.h @@ -46,11 +46,15 @@ struct mi_opt If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated to specify the non-option argument. OPTARG is set to NULL. - mi_getopt() calls ``error("%s: Unknown option %c", prefix, - option)'' if an unknown option is encountered. */ + If an unknown option is encountered, mi_getopt() calls + ``error("%s: Unknown option %c", prefix, option)'' and mi_getopt_silent + returns -1. */ extern int mi_getopt (const char *prefix, int argc, char **argv, const struct mi_opt *opt, int *optind, char **optarg); +extern int mi_getopt_silent (const char *prefix, int argc, char **argv, + const struct mi_opt *opts, int *oind, + char **oarg); /* mi_valid_noargs determines if ARGC/ARGV are a valid set of parameters to satisfy an MI function that is not supposed to -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH 1/2] Use mi_getopt_silent 2013-08-25 3:43 ` [PATCH 1/2] Use mi_getopt_silent Yao Qi @ 2013-08-26 8:58 ` Agovic, Sanimir 2013-08-26 10:18 ` Yao Qi 2013-08-26 16:22 ` Pedro Alves 1 sibling, 1 reply; 26+ messages in thread From: Agovic, Sanimir @ 2013-08-26 8:58 UTC (permalink / raw) To: 'Yao Qi'; +Cc: gdb-patches Hello Yao, I`d rather catch the exception in mi_cmd_stack_list_args to prevent the error to bubble up to upper layers. This requires the use of throw_error (NOT_FOUND_ERROR, ...) instead of error (...) in mi_getopt to catch the right exception (*) and re-throw otherwise. Due to the poor exception handling in gdb this may lead to some boilerplate code. On the other side it keeps the interface simple & consistent e.g. (*) in the patch below mi_getopt_silent may still be verbose/throw. -Sanimir > -----Original Message----- > From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-owner@sourceware.org] On Behalf > Of Yao Qi > Sent: Sunday, August 25, 2013 05:42 AM > To: gdb-patches@sourceware.org > Subject: [PATCH 1/2] Use mi_getopt_silent > > This patch is to add a new function mi_getopt_silent, which returns -1 > silently (without throwing error) when unknown option is met, and use > this function to parse options for command '-stack-list-arguments'. > > It makes easier to add a new option in patch 2/2. > gdb: > > 2013-08-24 Yao Qi <yao@codesourcery.com> > > * mi/mi-cmd-stack.c (parse_no_frames_option): Remove. > (mi_cmd_stack_list_args): Use mi_getopt_silent to handle > options. > * mi/mi-getopt.c (mi_getopt): Remove. > (mi_getopt_1): Renamed from mi_getopt. Add one parameter > 'error_on_unknown'. > (mi_getopt): Call mi_getopt_1. > (mi_getopt_silent): New. > * mi/mi-getopt.h (mi_getopt_silent): Declare. > --- > gdb/mi/mi-cmd-stack.c | 50 ++++++++++++++++++++++++++++++------------------ > gdb/mi/mi-getopt.c | 35 ++++++++++++++++++++++++++++----- > gdb/mi/mi-getopt.h | 8 +++++- > 3 files changed, 66 insertions(+), 27 deletions(-) > > diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c > index e542fc1..b280e7d 100644 > --- a/gdb/mi/mi-cmd-stack.c > +++ b/gdb/mi/mi-cmd-stack.c > @@ -54,17 +54,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc) > frame_filters = 1; > } > > -/* Parse the --no-frame-filters option in commands where we cannot use > - mi_getopt. */ > -static int > -parse_no_frames_option (const char *arg) > -{ > - if (arg && (strcmp (arg, "--no-frame-filters") == 0)) > - return 1; > - > - return 0; > -} > - > /* Print a list of the stack frames. Args can be none, in which case > we want to print the whole backtrace, or a pair of numbers > specifying the frame numbers at which to start and stop the > @@ -284,19 +273,42 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) > enum print_values print_values; > struct ui_out *uiout = current_uiout; > int raw_arg = 0; > + int oind = 0; > enum py_bt_status result = PY_BT_ERROR; > + enum opt > + { > + NO_FRAME_FILTERS, > + }; > + static const struct mi_opt opts[] = > + { > + {"-no-frame-filters", NO_FRAME_FILTERS, 0}, > + { 0, 0, 0 } > + }; > > - if (argc > 0) > - raw_arg = parse_no_frames_option (argv[0]); > + while (1) > + { > + char *oarg; > + int opt = mi_getopt_silent ("-stack-list-args", argc, argv, opts, > + &oind, &oarg); > + > + if (opt < 0) > + break; > + switch ((enum opt) opt) > + { > + case NO_FRAME_FILTERS: > + raw_arg = oind; > + break; > + } > + } > > - if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg)) > - error (_("-stack-list-arguments: Usage: " \ > + if (argc - oind != 1 && argc - oind != 3) > + error (_("-stack-list-arguments: Usage: " \ > "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); > > - if (argc >= 3) > + if (argc - oind == 3) > { > - frame_low = atoi (argv[1 + raw_arg]); > - frame_high = atoi (argv[2 + raw_arg]); > + frame_low = atoi (argv[1 + oind]); > + frame_high = atoi (argv[2 + oind]); > } > else > { > @@ -306,7 +318,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) > frame_high = -1; > } > > - print_values = mi_parse_print_values (argv[raw_arg]); > + print_values = mi_parse_print_values (argv[oind]); > > /* Let's position fi on the frame at which to start the > display. Could be the innermost frame if the whole stack needs > diff --git a/gdb/mi/mi-getopt.c b/gdb/mi/mi-getopt.c > index a1e2ccc..0255d22 100644 > --- a/gdb/mi/mi-getopt.c > +++ b/gdb/mi/mi-getopt.c > @@ -21,11 +21,14 @@ > #include "mi-getopt.h" > #include "gdb_string.h" > > -int > -mi_getopt (const char *prefix, > - int argc, char **argv, > - const struct mi_opt *opts, > - int *oind, char **oarg) > +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h. > + When there is an unknown option, if ERROR_ON_UNKNOWN is true, it > + throws an error, otherwise return -1. */ > + > +static int > +mi_getopt_1 (const char *prefix, int argc, char **argv, > + const struct mi_opt *opts, int *oind, char **oarg, > + int error_on_unknown) > { > char *arg; > const struct mi_opt *opt; > @@ -71,7 +74,27 @@ mi_getopt (const char *prefix, > return opt->index; > } > } > - error (_("%s: Unknown option ``%s''"), prefix, arg + 1); > + > + if (error_on_unknown) > + error (_("%s: Unknown option ``%s''"), prefix, arg + 1); > + else > + return -1; > +} > + > +int > +mi_getopt (const char *prefix, > + int argc, char **argv, > + const struct mi_opt *opts, > + int *oind, char **oarg) > +{ > + return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 1); > +} > + > +int > +mi_getopt_silent (const char *prefix, int argc, char **argv, > + const struct mi_opt *opts, int *oind, char **oarg) > +{ > + return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 0); > } > > int > diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h > index 9600353..cabe488 100644 > --- a/gdb/mi/mi-getopt.h > +++ b/gdb/mi/mi-getopt.h > @@ -46,11 +46,15 @@ struct mi_opt > If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated > to specify the non-option argument. OPTARG is set to NULL. > > - mi_getopt() calls ``error("%s: Unknown option %c", prefix, > - option)'' if an unknown option is encountered. */ > + If an unknown option is encountered, mi_getopt() calls > + ``error("%s: Unknown option %c", prefix, option)'' and mi_getopt_silent > + returns -1. */ > > extern int mi_getopt (const char *prefix, int argc, char **argv, > const struct mi_opt *opt, int *optind, char **optarg); > +extern int mi_getopt_silent (const char *prefix, int argc, char **argv, > + const struct mi_opt *opts, int *oind, > + char **oarg); > > /* mi_valid_noargs determines if ARGC/ARGV are a valid set of > parameters to satisfy an MI function that is not supposed to > -- > 1.7.7.6 Intel GmbH Dornacher Strasse 1 85622 Feldkirchen/Muenchen, Deutschland Sitz der Gesellschaft: Feldkirchen bei Muenchen Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk Registergericht: Muenchen HRB 47456 Ust.-IdNr./VAT Registration No.: DE129385895 Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt_silent 2013-08-26 8:58 ` Agovic, Sanimir @ 2013-08-26 10:18 ` Yao Qi 2013-08-26 16:01 ` Pedro Alves 0 siblings, 1 reply; 26+ messages in thread From: Yao Qi @ 2013-08-26 10:18 UTC (permalink / raw) To: Agovic, Sanimir; +Cc: gdb-patches On 08/26/2013 04:58 PM, Agovic, Sanimir wrote: > I`d rather catch the exception in mi_cmd_stack_list_args to prevent the > error to bubble up to upper layers. This requires the use of > throw_error (NOT_FOUND_ERROR, ...) instead of error (...) in mi_getopt > to catch the right exception (*) and re-throw otherwise. Sanimir, thanks for your comments. I am not inclined to use exception here because exception handling in GDB is poor. On the other hand, I don't like using exception to control the program flow. In some commands, there is no unknown options, and in other commands, there may be unknown options. Both of them are expected. In the former, GDB can throw an error, and in the later, GDB can silently return -1. > Due to the poor exception handling in gdb this may lead to some boilerplate > code. On the other side it keeps the interface simple & consistent > e.g. (*) in the patch below mi_getopt_silent may still be verbose/throw. Yes, mi_getopt_silent may throw error when the argument of an option is missing, because it is wrong. "silent" here is only for unknown options, which is expected in some commands. -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt_silent 2013-08-26 10:18 ` Yao Qi @ 2013-08-26 16:01 ` Pedro Alves 0 siblings, 0 replies; 26+ messages in thread From: Pedro Alves @ 2013-08-26 16:01 UTC (permalink / raw) To: Yao Qi; +Cc: Agovic, Sanimir, gdb-patches On 08/26/2013 11:16 AM, Yao Qi wrote: > On 08/26/2013 04:58 PM, Agovic, Sanimir wrote: >> I`d rather catch the exception in mi_cmd_stack_list_args to prevent the >> error to bubble up to upper layers. This requires the use of >> throw_error (NOT_FOUND_ERROR, ...) instead of error (...) in mi_getopt >> to catch the right exception (*) and re-throw otherwise. > > Sanimir, thanks for your comments. > > I am not inclined to use exception here because exception handling in > GDB is poor. On the other hand, I don't like using exception to > control the program flow. In some commands, there is no unknown > options, and in other commands, there may be unknown options. Both of > them are expected. In the former, GDB can throw an error, and in the > later, GDB can silently return -1. Agreed. Sometimes it's hard to avoid going the throw + swallow-error route, but in this case it's trivial. >> Due to the poor exception handling in gdb this may lead to some boilerplate >> code. On the other side it keeps the interface simple & consistent >> e.g. (*) in the patch below mi_getopt_silent may still be verbose/throw. > > Yes, mi_getopt_silent may throw error when the argument of an option is > missing, because it is wrong. "silent" here is only for unknown > options, which is expected in some commands. Maybe it's just "silent" that's the confusing term to use. Maybe mi_getopt_unknown or even something longer would make it less confusing. -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt_silent 2013-08-25 3:43 ` [PATCH 1/2] Use mi_getopt_silent Yao Qi 2013-08-26 8:58 ` Agovic, Sanimir @ 2013-08-26 16:22 ` Pedro Alves 2013-08-27 3:30 ` Yao Qi 1 sibling, 1 reply; 26+ messages in thread From: Pedro Alves @ 2013-08-26 16:22 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 08/25/2013 04:42 AM, Yao Qi wrote: > This patch is to add a new function mi_getopt_silent, which returns -1 > silently (without throwing error) when unknown option is met, and use > this function to parse options for command '-stack-list-arguments'. > > It makes easier to add a new option in patch 2/2. Thanks! This is OK. A few minor suggestions below. > 2013-08-24 Yao Qi <yao@codesourcery.com> > > * mi/mi-cmd-stack.c (parse_no_frames_option): Remove. > (mi_cmd_stack_list_args): Use mi_getopt_silent to handle > options. > * mi/mi-getopt.c (mi_getopt): Remove. This "remove" got me confused, and made think it was a ChangeLog mistake. > (mi_getopt_1): Renamed from mi_getopt. Add one parameter > 'error_on_unknown'. > (mi_getopt): Call mi_getopt_1. > (mi_getopt_silent): New. Here's what I suggest: * mi/mi-getopt.c (mi_getopt): Rename to ... (mi_getopt_1): ... this. Add parameter 'error_on_unknown'. (mi_getopt): Reimplement as wrapper around mi_getopt_1. (mi_getopt_silent): New function. > * mi/mi-getopt.h (mi_getopt_silent): Declare. > --- a/gdb/mi/mi-getopt.c > +++ b/gdb/mi/mi-getopt.c > @@ -21,11 +21,14 @@ > #include "mi-getopt.h" > #include "gdb_string.h" > > -int > -mi_getopt (const char *prefix, > - int argc, char **argv, > - const struct mi_opt *opts, > - int *oind, char **oarg) > +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h. > + When there is an unknown option, if ERROR_ON_UNKNOWN is true, it > + throws an error, otherwise return -1. */ ("throws" -> "returns"). I'd suggest: If an unknown option is encountered, if ERROR_ON_UNKNOWN is true, throw an error, otherwise return -1. */ > + > +static int > +mi_getopt_1 (const char *prefix, int argc, char **argv, > + const struct mi_opt *opts, int *oind, char **oarg, > + int error_on_unknown) > { > > int > diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h > index 9600353..cabe488 100644 > --- a/gdb/mi/mi-getopt.h > +++ b/gdb/mi/mi-getopt.h > @@ -46,11 +46,15 @@ struct mi_opt > If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated > to specify the non-option argument. OPTARG is set to NULL. > > - mi_getopt() calls ``error("%s: Unknown option %c", prefix, > - option)'' if an unknown option is encountered. */ > + If an unknown option is encountered, mi_getopt() calls > + ``error("%s: Unknown option %c", prefix, option)'' and mi_getopt_silent > + returns -1. */ I'd suggest s/and/while/. > > extern int mi_getopt (const char *prefix, int argc, char **argv, > const struct mi_opt *opt, int *optind, char **optarg); > +extern int mi_getopt_silent (const char *prefix, int argc, char **argv, > + const struct mi_opt *opts, int *oind, > + char **oarg); -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt_silent 2013-08-26 16:22 ` Pedro Alves @ 2013-08-27 3:30 ` Yao Qi 2013-08-27 11:43 ` Pedro Alves 0 siblings, 1 reply; 26+ messages in thread From: Yao Qi @ 2013-08-27 3:30 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On 08/27/2013 12:22 AM, Pedro Alves wrote: > Here's what I suggest: > > * mi/mi-getopt.c (mi_getopt): Rename to ... > (mi_getopt_1): ... this. Add parameter 'error_on_unknown'. > (mi_getopt): Reimplement as wrapper around mi_getopt_1. > (mi_getopt_silent): New function. > OK. >> > * mi/mi-getopt.h (mi_getopt_silent): Declare. > > >> >--- a/gdb/mi/mi-getopt.c >> >+++ b/gdb/mi/mi-getopt.c >> >@@ -21,11 +21,14 @@ >> > #include "mi-getopt.h" >> > #include "gdb_string.h" >> > >> >-int >> >-mi_getopt (const char *prefix, >> >- int argc, char **argv, >> >- const struct mi_opt *opts, >> >- int *oind, char **oarg) >> >+/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h. >> >+ When there is an unknown option, if ERROR_ON_UNKNOWN is true, it >> >+ throws an error, otherwise return -1. */ > ("throws" -> "returns"). I'd suggest: > I assume you meant "return" -> "returns" here. > If an unknown option is encountered, if ERROR_ON_UNKNOWN is true, > throw an error, otherwise return -1. */ > Anyway, copy this into the patch. I also rename mi_getopt_silent to mi_getopt_allow_unknown. Patch below is what I committed. -- Yao (é½å°§) gdb: 2013-08-27 Yao Qi <yao@codesourcery.com> * mi/mi-cmd-stack.c (parse_no_frames_option): Remove. (mi_cmd_stack_list_args): Use mi_getopt_allow_unknown to handle options. * mi/mi-getopt.c (mi_getopt): Rename to ... (mi_getopt_1): ... this. Add parameter 'error_on_unknown'. (mi_getopt): Reimplement as wrapper around mi_getopt_1. (mi_getopt_allow_unknown): New function. * mi/mi-getopt.h (mi_getopt_allow_unknown): Declare. --- gdb/mi/mi-cmd-stack.c | 50 ++++++++++++++++++++++++++++++------------------ gdb/mi/mi-getopt.c | 35 ++++++++++++++++++++++++++++----- gdb/mi/mi-getopt.h | 8 +++++- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index e542fc1..2df97e2 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -54,17 +54,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc) frame_filters = 1; } -/* Parse the --no-frame-filters option in commands where we cannot use - mi_getopt. */ -static int -parse_no_frames_option (const char *arg) -{ - if (arg && (strcmp (arg, "--no-frame-filters") == 0)) - return 1; - - return 0; -} - /* Print a list of the stack frames. Args can be none, in which case we want to print the whole backtrace, or a pair of numbers specifying the frame numbers at which to start and stop the @@ -284,19 +273,42 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) enum print_values print_values; struct ui_out *uiout = current_uiout; int raw_arg = 0; + int oind = 0; enum py_bt_status result = PY_BT_ERROR; + enum opt + { + NO_FRAME_FILTERS, + }; + static const struct mi_opt opts[] = + { + {"-no-frame-filters", NO_FRAME_FILTERS, 0}, + { 0, 0, 0 } + }; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + while (1) + { + char *oarg; + int opt = mi_getopt_allow_unknown ("-stack-list-args", argc, argv, + opts, &oind, &oarg); + + if (opt < 0) + break; + switch ((enum opt) opt) + { + case NO_FRAME_FILTERS: + raw_arg = oind; + break; + } + } - if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg)) - error (_("-stack-list-arguments: Usage: " \ + if (argc - oind != 1 && argc - oind != 3) + error (_("-stack-list-arguments: Usage: " \ "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); - if (argc >= 3) + if (argc - oind == 3) { - frame_low = atoi (argv[1 + raw_arg]); - frame_high = atoi (argv[2 + raw_arg]); + frame_low = atoi (argv[1 + oind]); + frame_high = atoi (argv[2 + oind]); } else { @@ -306,7 +318,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) frame_high = -1; } - print_values = mi_parse_print_values (argv[raw_arg]); + print_values = mi_parse_print_values (argv[oind]); /* Let's position fi on the frame at which to start the display. Could be the innermost frame if the whole stack needs diff --git a/gdb/mi/mi-getopt.c b/gdb/mi/mi-getopt.c index a1e2ccc..f207249 100644 --- a/gdb/mi/mi-getopt.c +++ b/gdb/mi/mi-getopt.c @@ -21,11 +21,14 @@ #include "mi-getopt.h" #include "gdb_string.h" -int -mi_getopt (const char *prefix, - int argc, char **argv, - const struct mi_opt *opts, - int *oind, char **oarg) +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h. + When there is an unknown option, if ERROR_ON_UNKNOWN is true, + throw an error, otherwise return -1. */ + +static int +mi_getopt_1 (const char *prefix, int argc, char **argv, + const struct mi_opt *opts, int *oind, char **oarg, + int error_on_unknown) { char *arg; const struct mi_opt *opt; @@ -71,7 +74,27 @@ mi_getopt (const char *prefix, return opt->index; } } - error (_("%s: Unknown option ``%s''"), prefix, arg + 1); + + if (error_on_unknown) + error (_("%s: Unknown option ``%s''"), prefix, arg + 1); + else + return -1; +} + +int +mi_getopt (const char *prefix, + int argc, char **argv, + const struct mi_opt *opts, + int *oind, char **oarg) +{ + return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 1); +} + +int +mi_getopt_allow_unknown (const char *prefix, int argc, char **argv, + const struct mi_opt *opts, int *oind, char **oarg) +{ + return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 0); } int diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h index 9600353..7db0bf4 100644 --- a/gdb/mi/mi-getopt.h +++ b/gdb/mi/mi-getopt.h @@ -46,11 +46,15 @@ struct mi_opt If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated to specify the non-option argument. OPTARG is set to NULL. - mi_getopt() calls ``error("%s: Unknown option %c", prefix, - option)'' if an unknown option is encountered. */ + If an unknown option is encountered, mi_getopt() calls + ``error("%s: Unknown option %c", prefix, option)'' while + mi_getopt_allow_unknown returns -1. */ extern int mi_getopt (const char *prefix, int argc, char **argv, const struct mi_opt *opt, int *optind, char **optarg); +extern int mi_getopt_allow_unknown (const char *prefix, int argc, + char **argv, const struct mi_opt *opts, + int *oind, char **oarg); /* mi_valid_noargs determines if ARGC/ARGV are a valid set of parameters to satisfy an MI function that is not supposed to -- 1.7.7.6 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 1/2] Use mi_getopt_silent 2013-08-27 3:30 ` Yao Qi @ 2013-08-27 11:43 ` Pedro Alves 0 siblings, 0 replies; 26+ messages in thread From: Pedro Alves @ 2013-08-27 11:43 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 08/27/2013 04:28 AM, Yao Qi wrote: > On 08/27/2013 12:22 AM, Pedro Alves wrote: >>>> -int >>>> -mi_getopt (const char *prefix, >>>> - int argc, char **argv, >>>> - const struct mi_opt *opts, >>>> - int *oind, char **oarg) >>>> +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h. >>>> + When there is an unknown option, if ERROR_ON_UNKNOWN is true, it >>>> + throws an error, otherwise return -1. */ >> ("throws" -> "returns"). I'd suggest: >> > > I assume you meant "return" -> "returns" here. Yeah, specifically, I meant, you have "it throws", so it should be "it returns", as the subject is still "it". > I also rename mi_getopt_silent to mi_getopt_allow_unknown. Excellent! I like that. -- Pedro Alves ^ permalink raw reply [flat|nested] 26+ messages in thread
* [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands 2013-07-03 1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi 2013-07-03 1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi 2013-07-03 1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi @ 2013-07-29 9:33 ` Yao Qi 2 siblings, 0 replies; 26+ messages in thread From: Yao Qi @ 2013-07-29 9:33 UTC (permalink / raw) To: gdb-patches On 07/03/2013 09:48 AM, Yao Qi wrote: > Hi, > This patch series add new option '--skip-unavailable' to MI commands > '-stack-list-{locals, arguments, variables}'. This option is optional, > and when it is used, locals or arguments whose values are not available > are not listed. It is useful when the MI front-end is not interested in > unavailable values. > > The patch 1/2 is a refactor patch, use mi_getopt in > mi_cmd_stack_list_locals and mi_cmd_stack_list_variables, so it is > easier to add new option patch 2/2. Patch 2/2 is the major part of this > series. > > Regression tested on x86_64-linux. > > Note that this patch is for MI, but the idea that skipping unavailable > locals and arguments can be applied to CLI too. We can invent new CLI > commands on top of 'info locals' and 'info args' to display available > locals or arguments. This piece of work is not included in this > series. Ping. http://sourceware.org/ml/gdb-patches/2013-07/msg00101.html -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2013-08-27 11:43 UTC | newest] Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-07-03 1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi 2013-07-03 1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi 2013-07-29 18:17 ` Pedro Alves 2013-07-31 7:01 ` Yao Qi 2013-07-31 12:23 ` Pedro Alves 2013-08-01 6:45 ` Yao Qi 2013-07-03 1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi 2013-07-03 4:14 ` asmwarrior 2013-07-03 5:21 ` Yao Qi 2013-07-03 19:22 ` Eli Zaretskii 2013-07-22 1:38 ` Yao Qi 2013-08-01 12:33 ` Pedro Alves 2013-08-01 13:59 ` Yao Qi 2013-08-01 14:47 ` Pedro Alves 2013-08-25 3:43 ` [PATCH 0/2 v2] " Yao Qi 2013-08-25 3:43 ` [PATCH 2/2] " Yao Qi 2013-08-26 16:40 ` Pedro Alves 2013-08-27 5:22 ` Yao Qi 2013-08-25 3:43 ` [PATCH 1/2] Use mi_getopt_silent Yao Qi 2013-08-26 8:58 ` Agovic, Sanimir 2013-08-26 10:18 ` Yao Qi 2013-08-26 16:01 ` Pedro Alves 2013-08-26 16:22 ` Pedro Alves 2013-08-27 3:30 ` Yao Qi 2013-08-27 11:43 ` Pedro Alves 2013-07-29 9:33 ` [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox