From: Yao Qi Date: Tue, 27 Aug 2013 05:20:57 +0000 (+0000) Subject: Add options to skip unavailable locals X-Git-Tag: binutils-2_24-branchpoint~164 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6211c335ec2c2428b70b65819f69b72d349527d5;p=external%2Fbinutils.git Add options to skip unavailable locals 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=""}] -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=""}]},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=""},{name="array",type="unsigned char [2]"},{name="i",type="int",value=""}] -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-08-27 Pedro Alves Yao Qi * 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 Yao Qi * 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 * 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'. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d92f194..d41b1da 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2013-08-27 Pedro Alves + Yao Qi + + * 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'. + 2013-08-27 Yao Qi * mi/mi-cmd-stack.c (parse_no_frames_option): Remove. 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/ChangeLog b/gdb/doc/ChangeLog index 61a6f41..67d3320 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2013-08-27 Pedro Alves + Yao Qi + + * gdb.texinfo (GDB/MI Stack Manipulation) <-stack-list-locals>: + Document new --skip-unavailable option. + <-stack-list-variables>: Document new --skip-unavailable option. + 2013-08-26 Doug Evans * gdb.texinfo (Maintenance Commands): "maint print objfiles" now takes 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/ChangeLog b/gdb/testsuite/ChangeLog index cbc4e6f..7467bb9 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2013-08-27 Yao Qi + * 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'. + +2013-08-27 Yao Qi + * lib/gdb.exp (gdb_remote_download): Don't pass $tofile to remote_download if it is empty. 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=\\).*" +# 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=\"\"\}\\\]" \ "-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=\"\"\}\\\]\},.*\}.*" \ "-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=\"\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"\"\}\\\]" \ "-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. */