From patchwork Wed Jun 19 16:06:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philippe Waroquiers X-Patchwork-Id: 33217 Received: (qmail 17478 invoked by alias); 19 Jun 2019 16:06:49 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 17122 invoked by uid 89); 19 Jun 2019 16:06:46 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.1 spammy=ellipsis, sal, valprinth, UD:valprint.h X-HELO: mailsec117.isp.belgacom.be Received: from mailsec117.isp.belgacom.be (HELO mailsec117.isp.belgacom.be) (195.238.20.113) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 19 Jun 2019 16:06:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skynet.be; i=@skynet.be; q=dns/txt; s=securemail; t=1560960402; x=1592496402; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uWmo/DOp4BkNuW+xIJGFbHpWdkgLeViT8m176SDRIbc=; b=thdDRIoHlZZBR9KHTHMt7yMKsbAlL2UpBmse4gCxeplEdGs/RdqReo+H 8y2WKwbWmiFiNsmWvkNZIOWyhnr7Pg==; Received: from 96.218-128-109.adsl-dyn.isp.belgacom.be (HELO md.home) ([109.128.218.96]) by relay.skynet.be with ESMTP/TLS/DHE-RSA-AES128-GCM-SHA256; 19 Jun 2019 18:06:35 +0200 From: Philippe Waroquiers To: gdb-patches@sourceware.org Cc: Philippe Waroquiers Subject: [RFAv3 1/3] Implement 'set print frame-info|frame-arguments presence'. Date: Wed, 19 Jun 2019 18:06:25 +0200 Message-Id: <20190619160627.12531-2-philippe.waroquiers@skynet.be> In-Reply-To: <20190619160627.12531-1-philippe.waroquiers@skynet.be> References: <20190619160627.12531-1-philippe.waroquiers@skynet.be> MIME-Version: 1.0 X-IsSubscribed: yes New settings allow to better control what frame information is printed. 'set print frame-info' allows to override the default frame information printed when a GDB command prints a frame. The backtrace command has a new option -frame-info to override this global setting. It is now possible to have very short frame information by using the new 'set print frame-arguments presence' and 'set print frame-info short-location'. Combined with 'set print address off', a backtrace will only show the essential information to see the function call chain, e.g.: (gdb) set print address off (gdb) set print frame-arguments presence (gdb) set print frame-info short-location (gdb) bt #0 break_me () #1 call_me (...) #2 main () (gdb) This is handy in particular for big backtraces with functions having many arguments. Python frame filter printing logic has been updated to respect the new setting in non MI mode. Also, the default frame information printed was inconsistent when backtrace was printing the frame information itself, or when the python frame filtering code was printing the frame information. This patch changes the default of python frame filtering to have a consistent behaviour regarding printed frame-information, whatever the presence/activity/matches of python filters. 2019-06-19 Philippe Waroquiers * frame.h (enum print_what): New value 'SHORT_LOCATION', update comments. (print_frame_info_auto, print_frame_info_source_line, print_frame_info_location, print_frame_info_source_and_location, print_frame_info_location_and_address, print_frame_info_short_location): New declarations. (struct frame_print_options): New member print_frame_info. * extension.h (enum ext_lang_frame_args): New value CLI_PRESENCE. * stack.h (get_user_print_what_frame_info): New declaration. (frame_show_address): New declaration. * stack.c (print_frame_arguments_choices): New value 'presence'. (print_frame_info_auto, print_frame_info_source_line, print_frame_info_location, print_frame_info_source_and_location, print_frame_info_location_and_address, print_frame_info_short_location, print_frame_info_choices, print_frame_info_print_what): New definitions. (print_frame_args): Only print dots for args if print frame-arguments is 'presence'. (frame_print_option_defs): New element for "frame-info". (get_user_print_what_frame_info): New function. (frame_show_address): Make non static. Move comment to stack.h. (print_frame_info_to_print_what): New function. (print_frame_info): Update comment. Use fp_opts.print_frame_info to decide what to print. (backtrace_command_1): Handle the new print_frame_arguments_presence value. (_initialize_stack): Call add_setshow_enum_cmd for frame-info. * python/py-framefilter.c (py_print_args): Handle CLI_PRESENCE. (py_print_frame): In non-mi mode, use LOCATION as default for print_what, similarly to frame information printed directly by backtrace command. Handle frame-info user option in non MI mode. --- gdb/extension.h | 5 +- gdb/frame.h | 37 ++++++++--- gdb/python/py-framefilter.c | 90 ++++++++++++++++++++++---- gdb/stack.c | 123 ++++++++++++++++++++++++++++++------ gdb/stack.h | 12 ++++ 5 files changed, 226 insertions(+), 41 deletions(-) diff --git a/gdb/extension.h b/gdb/extension.h index 2f1b71851c..405346ff6a 100644 --- a/gdb/extension.h +++ b/gdb/extension.h @@ -125,7 +125,10 @@ enum ext_lang_frame_args CLI_SCALAR_VALUES, /* Print all values for arguments when invoked from the CLI. */ - CLI_ALL_VALUES + CLI_ALL_VALUES, + + /* Only indicate the presence of arguments when invoked from the CLI. */ + CLI_PRESENCE }; /* The possible results of diff --git a/gdb/frame.h b/gdb/frame.h index a79eeeeab1..ccc285005a 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -677,18 +677,28 @@ extern struct gdbarch *frame_unwind_arch (frame_info *next_frame); extern struct gdbarch *frame_unwind_caller_arch (struct frame_info *frame); -/* Values for the source flag to be used in print_frame_info_base(). */ +/* Values for the source flag to be used in print_frame_info (). + For all the cases below, the address is never printed if + 'set print address' is off. When 'set print address' is on, + the address is printed if the program counter is not at the + beginning of the source line of the frame + and PRINT_WHAT is != LOC_AND_ADDRESS. */ enum print_what - { - /* Print only the source line, like in stepi. */ - SRC_LINE = -1, - /* Print only the location, i.e. level, address (sometimes) - function, args, file, line, line num. */ + { + /* Print only the address, source line, like in stepi. */ + SRC_LINE = -1, + /* Print only the location, i.e. level, address, + function, args (as controlled by 'set print frame-arguments'), + file, line, line num. */ LOCATION, /* Print both of the above. */ - SRC_AND_LOC, - /* Print location only, but always include the address. */ - LOC_AND_ADDRESS + SRC_AND_LOC, + /* Print location only, print the address even if the program counter + is at the beginning of the source line. */ + LOC_AND_ADDRESS, + /* Print only level and function, + i.e. location only, without address, file, line, line num. */ + SHORT_LOCATION }; /* Allocate zero initialized memory from the frame cache obstack. @@ -772,6 +782,14 @@ extern const char print_frame_arguments_all[]; extern const char print_frame_arguments_scalars[]; extern const char print_frame_arguments_none[]; +/* The possible choices of "set print frame-info". */ +extern const char print_frame_info_auto[]; +extern const char print_frame_info_source_line[]; +extern const char print_frame_info_location[]; +extern const char print_frame_info_source_and_location[]; +extern const char print_frame_info_location_and_address[]; +extern const char print_frame_info_short_location[]; + /* The possible choices of "set print entry-values". */ extern const char print_entry_values_no[]; extern const char print_entry_values_only[]; @@ -787,6 +805,7 @@ extern const char print_entry_values_default[]; struct frame_print_options { const char *print_frame_arguments = print_frame_arguments_scalars; + const char *print_frame_info = print_frame_info_auto; const char *print_entry_values = print_entry_values_default; /* If non-zero, don't invoke pretty-printers for frame diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index 95ad410f23..f1282597a5 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -25,6 +25,8 @@ #include "python.h" #include "ui-out.h" #include "valprint.h" +#include "stack.h" +#include "source.h" #include "annotate.h" #include "hashtab.h" #include "demangle.h" @@ -713,9 +715,21 @@ py_print_args (PyObject *filter, annotate_frame_args (); out->text (" ("); - if (args_iter != Py_None - && (enumerate_args (args_iter.get (), out, args_type, 0, frame) - == EXT_LANG_BT_ERROR)) + if (args_type == CLI_PRESENCE) + { + if (args_iter != Py_None) + { + gdbpy_ref<> item (PyIter_Next (args_iter.get ())); + + if (item != NULL) + out->text ("..."); + else if (PyErr_Occurred ()) + return EXT_LANG_BT_ERROR; + } + } + else if (args_iter != Py_None + && (enumerate_args (args_iter.get (), out, args_type, 0, frame) + == EXT_LANG_BT_ERROR)) return EXT_LANG_BT_ERROR; out->text (")"); @@ -748,7 +762,16 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, struct gdbarch *gdbarch = NULL; struct frame_info *frame = NULL; struct value_print_options opts; + int print_level, print_frame_info, print_args, print_locals; + /* Note that the below default in non-mi mode is the same as the + default value for the backtrace command (see the call to print_frame_info + in backtrace_command_1). + Having the same default ensures that 'bt' and 'bt no-filters' + have the same behaviour when some filters exist but do not apply + to a frame. */ + enum print_what print_what + = out->is_mi_like_p () ? LOC_AND_ADDRESS : LOCATION; gdb::unique_xmalloc_ptr function_to_free; /* Extract print settings from FLAGS. */ @@ -758,6 +781,17 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, print_locals = (flags & PRINT_LOCALS) ? 1 : 0; get_user_print_options (&opts); + if (print_frame_info) + { + gdb::optional user_frame_info_print_what; + + get_user_print_what_frame_info (&user_frame_info_print_what); + if (!out->is_mi_like_p () && user_frame_info_print_what.has_value ()) + { + /* Use the specific frame information desired by the user. */ + print_what = *user_frame_info_print_what; + } + } /* Get the underlying frame. This is needed to determine GDB architecture, and also, in the cases of frame variables/arguments to @@ -771,6 +805,8 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, if (frame == NULL) return EXT_LANG_BT_ERROR; + symtab_and_line sal = find_frame_sal (frame); + gdbarch = get_frame_arch (frame); /* stack-list-variables. */ @@ -815,9 +851,19 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, } } + /* For MI, each piece is controlled individually. */ + bool location_print = (print_frame_info + && !out->is_mi_like_p () + && (print_what == LOCATION + || print_what == SRC_AND_LOC + || print_what == LOC_AND_ADDRESS + || print_what == SHORT_LOCATION)); + /* Print frame level. MI does not require the level if locals/variables only are being printed. */ - if ((print_frame_info || print_args) && print_level) + if (print_level + && (location_print + || (out->is_mi_like_p () && (print_frame_info || print_args)))) { struct frame_info **slot; int level; @@ -844,16 +890,21 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, } } - if (print_frame_info) + if (location_print || (out->is_mi_like_p () && print_frame_info)) { /* Print address to the address field. If an address is not provided, print nothing. */ if (opts.addressprint && has_addr) { - annotate_frame_address (); - out->field_core_addr ("addr", gdbarch, address); - annotate_frame_address_end (); - out->text (" in "); + if (!sal.symtab + || frame_show_address (frame, sal) + || print_what == LOC_AND_ADDRESS) + { + annotate_frame_address (); + out->field_core_addr ("addr", gdbarch, address); + annotate_frame_address_end (); + out->text (" in "); + } } /* Print frame function name. */ @@ -905,14 +956,17 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, /* Frame arguments. Check the result, and error if something went wrong. */ - if (print_args) + if (print_args && (location_print || out->is_mi_like_p ())) { if (py_print_args (filter, out, args_type, frame) == EXT_LANG_BT_ERROR) return EXT_LANG_BT_ERROR; } /* File name/source/line number information. */ - if (print_frame_info) + bool print_location_source + = ((location_print && print_what != SHORT_LOCATION) + || (out->is_mi_like_p () && print_frame_info)); + if (print_location_source) { annotate_frame_source_begin (); @@ -964,12 +1018,24 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, (gdbarch_bfd_arch_info (gdbarch))->printable_name); } + bool source_print + = (! out->is_mi_like_p () + && (print_what == SRC_LINE || print_what == SRC_AND_LOC)); + if (source_print) + { + if (print_location_source) + out->text ("\n"); /* Newline after the location source. */ + print_source_lines (sal.symtab, sal.line, sal.line + 1, 0); + } + /* For MI we need to deal with the "children" list population of elided frames, so if MI output detected do not send newline. */ if (! out->is_mi_like_p ()) { annotate_frame_end (); - out->text ("\n"); + /* print_source_lines has already printed a newline. */ + if (!source_print) + out->text ("\n"); } if (print_locals) diff --git a/gdb/stack.c b/gdb/stack.c index b3d113d3b4..de3eb27d0c 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -61,15 +61,42 @@ const char print_frame_arguments_all[] = "all"; const char print_frame_arguments_scalars[] = "scalars"; const char print_frame_arguments_none[] = "none"; +const char print_frame_arguments_presence[] = "presence"; static const char *const print_frame_arguments_choices[] = { print_frame_arguments_all, print_frame_arguments_scalars, print_frame_arguments_none, + print_frame_arguments_presence, NULL }; +/* The possible choices of "set print frame-info", and the value + of this setting. */ + +const char print_frame_info_auto[] = "auto"; +const char print_frame_info_source_line[] = "source-line"; +const char print_frame_info_location[] = "location"; +const char print_frame_info_source_and_location[] = "source-and-location"; +const char print_frame_info_location_and_address[] = "location-and-address"; +const char print_frame_info_short_location[] = "short-location"; + +static const char *const print_frame_info_choices[] = + {print_frame_info_auto, + print_frame_info_source_line, + print_frame_info_location, + print_frame_info_source_and_location, + print_frame_info_location_and_address, + print_frame_info_short_location, + NULL}; + +/* print_frame_info_print_what[i] maps a choice to the corresponding + print_what enum. */ +static const gdb::optional print_frame_info_print_what[] = + {{}, /* Empty value for "auto". */ + SRC_LINE, LOCATION, SRC_AND_LOC, LOC_AND_ADDRESS, SHORT_LOCATION}; + /* The possible choices of "set print entry-values", and the value of this setting. */ @@ -137,6 +164,17 @@ or both. Note that one or both of these values may be ."), N_("If set, frame arguments are printed in raw form, bypassing any\n\ pretty-printers for that value.") }, + + enum_option_def { + "frame-info", + print_frame_info_choices, + [] (frame_print_options *opt) { return &opt->print_frame_info; }, + NULL, /* show_cmd_cb */ + N_("Set printing of frame information."), + N_("Show printing of frame information."), + NULL /* help_doc */ + } + }; /* Options for the "backtrace" command. */ @@ -209,10 +247,9 @@ static struct symtab *last_displayed_symtab = 0; static int last_displayed_line = 0; -/* Return 1 if we should display the address in addition to the location, - because we are in the middle of a statement. */ +/* See stack.h. */ -static int +int frame_show_address (struct frame_info *frame, struct symtab_and_line sal) { @@ -631,9 +668,13 @@ print_frame_args (const frame_print_options &fp_opts, long highest_offset = -1; /* Number of ints of arguments that we have printed so far. */ int args_printed = 0; + /* True if we should print arg names. If false, we only indicate + the presence of arguments by printing ellipsis. */ + bool print_names + = fp_opts.print_frame_arguments != print_frame_arguments_presence; /* True if we should print arguments, false otherwise. */ - bool print_args - = fp_opts.print_frame_arguments != print_frame_arguments_none; + bool print_args = print_names + && fp_opts.print_frame_arguments != print_frame_arguments_none; if (func) { @@ -653,6 +694,13 @@ print_frame_args (const frame_print_options &fp_opts, if (!SYMBOL_IS_ARGUMENT (sym)) continue; + if (!print_names) + { + uiout->text ("..."); + first = 0; + break; + } + switch (SYMBOL_CLASS (sym)) { case LOC_ARG: @@ -801,8 +849,11 @@ print_frame_args (const frame_print_options &fp_opts, else start = highest_offset; - print_frame_nameless_args (frame, start, num - args_printed, - first, stream); + if (!print_names && !first && num > 0) + uiout->text ("..."); + else + print_frame_nameless_args (frame, start, num - args_printed, + first, stream); } } @@ -859,13 +910,35 @@ do_gdb_disassembly (struct gdbarch *gdbarch, } } +/* Converts the PRINT_FRAME_INFO choice to an optional enum print_what. + Value not present indicates to the caller to use default values + specific to the command being executed. */ + +static gdb::optional +print_frame_info_to_print_what (const char *print_frame_info) +{ + + for (int i = 0; print_frame_info_choices[i] != NULL; i++) + if (print_frame_info == print_frame_info_choices[i]) + return print_frame_info_print_what[i]; + + internal_error (__FILE__, __LINE__, + "Unexpected print frame-info value `%s'.", + print_frame_info); +} + +void +get_user_print_what_frame_info (gdb::optional *what) +{ + *what = print_frame_info_to_print_what + (user_frame_print_options.print_frame_info); +} + /* Print information about frame FRAME. The output is format according - to PRINT_LEVEL and PRINT_WHAT and PRINT_ARGS. The meaning of - PRINT_WHAT is: - - SRC_LINE: Print only source line. - LOCATION: Print only location. - SRC_AND_LOC: Print location and source line. + to PRINT_LEVEL and PRINT_WHAT and PRINT_ARGS. For the meaning of + PRINT_WHAT, see enum print_what comments in frame.h. + Note that PRINT_WHAT is overriden if FP_OPTS.print_frame_info + != print_frame_info_auto. Used in "where" output, and to emit breakpoint or step messages. */ @@ -881,6 +954,13 @@ print_frame_info (const frame_print_options &fp_opts, int location_print; struct ui_out *uiout = current_uiout; + if (!current_uiout->is_mi_like_p () + && fp_opts.print_frame_info != print_frame_info_auto) + { + /* Use the specific frame information desired by the user. */ + print_what = *print_frame_info_to_print_what (fp_opts.print_frame_info); + } + if (get_frame_type (frame) == DUMMY_FRAME || get_frame_type (frame) == SIGTRAMP_FRAME || get_frame_type (frame) == ARCH_FRAME) @@ -944,10 +1024,10 @@ print_frame_info (const frame_print_options &fp_opts, to get the line containing FRAME->pc. */ symtab_and_line sal = find_frame_sal (frame); - location_print = (print_what == LOCATION + location_print = (print_what == LOCATION + || print_what == SRC_AND_LOC || print_what == LOC_AND_ADDRESS - || print_what == SRC_AND_LOC); - + || print_what == SHORT_LOCATION); if (location_print || !sal.symtab) print_frame (fp_opts, frame, print_level, print_what, print_args, sal); @@ -1299,7 +1379,7 @@ print_frame (const frame_print_options &fp_opts, QUIT; } uiout->text (")"); - if (sal.symtab) + if (print_what != SHORT_LOCATION && sal.symtab) { const char *filename_display; @@ -1322,7 +1402,8 @@ print_frame (const frame_print_options &fp_opts, annotate_frame_source_end (); } - if (pc_p && (funname == NULL || sal.symtab == NULL)) + if (print_what != SHORT_LOCATION + && pc_p && (funname == NULL || sal.symtab == NULL)) { char *lib = solib_name_from_address (get_frame_program_space (frame), get_frame_pc (frame)); @@ -1932,8 +2013,12 @@ backtrace_command_1 (const frame_print_options &fp_opts, arg_type = CLI_SCALAR_VALUES; else if (fp_opts.print_frame_arguments == print_frame_arguments_all) arg_type = CLI_ALL_VALUES; - else + else if (fp_opts.print_frame_arguments == print_frame_arguments_presence) + arg_type = CLI_PRESENCE; + else if (fp_opts.print_frame_arguments == print_frame_arguments_none) arg_type = NO_VALUES; + else + gdb_assert (0); result = apply_ext_lang_frame_filter (get_current_frame (), flags, arg_type, current_uiout, diff --git a/gdb/stack.h b/gdb/stack.h index 9ac77c0617..dda4fc9f66 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -42,6 +42,18 @@ void iterate_over_block_local_vars (const struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Initialize *WHAT to be a copy of the user desired print what frame info. + If !WHAT.has_value (), the printing function chooses a default set of + information to print, otherwise the printing function should print + the relevant information. */ + +void get_user_print_what_frame_info (gdb::optional *what); + +/* Return 1 if we should display the address in addition to the location, + because we are in the middle of a statement. */ + +int frame_show_address (struct frame_info *frame, struct symtab_and_line sal); + /* Get or set the last displayed symtab and line, which is, e.g. where we set a * breakpoint when `break' is supplied with no arguments. */ void clear_last_displayed_sal (void);