Implement 'set print frame-info|frame-arguments presence'.

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-07-29  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* 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.
This commit is contained in:
Philippe Waroquiers 2019-05-04 23:40:56 +02:00
parent de28a3b72e
commit 4b5e8d19af
6 changed files with 263 additions and 40 deletions

View File

@ -1,3 +1,36 @@
2019-07-29 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* 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.
2019-07-27 Kevin Buettner <kevinb@redhat.com>
* linux-thread-db.c (thread_db_target::thread_handle_to_thread_info):

View File

@ -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

View File

@ -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

View File

@ -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<char> 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<enum print_what> 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;
@ -843,16 +889,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. */
@ -904,14 +955,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 ();
@ -963,12 +1017,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)

View File

@ -61,15 +61,44 @@
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<enum print_what> 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 +166,17 @@ or both. Note that one or both of these values may be <optimized out>."),
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 +249,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 +670,14 @@ 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;
= (print_names
&& fp_opts.print_frame_arguments != print_frame_arguments_none);
if (func)
{
@ -653,6 +697,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 +852,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 +913,37 @@ 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<enum print_what>
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);
}
/* See stack.h. */
void
get_user_print_what_frame_info (gdb::optional<enum print_what> *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 +959,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 +1029,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);
@ -1258,7 +1343,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;
@ -1281,7 +1366,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));
@ -1891,8 +1977,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,

View File

@ -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<enum print_what> *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);