[RFA,1/3] Implement 'set print frame-info|frame-arguments presence'.

Message ID 20190504215538.29821-2-philippe.waroquiers@skynet.be
State New, archived
Headers

Commit Message

Philippe Waroquiers May 4, 2019, 9:55 p.m. UTC
  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.

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_loc'.

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_loc
  (gdb) bt
  #0  break_me ()
  #1  call_me (...)
  #2  main ()
  (gdb)

This is handy in particular for big backtraces with functions having
many arguments.
---
 gdb/ChangeLog | 14 +++++++++
 gdb/frame.h   | 28 +++++++++++------
 gdb/stack.c   | 86 ++++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 104 insertions(+), 24 deletions(-)
  

Comments

Andreas Schwab May 5, 2019, 8:24 p.m. UTC | #1
On Mai 04 2019, Philippe Waroquiers <philippe.waroquiers@skynet.be> wrote:

> @@ -766,13 +779,42 @@ do_gdb_disassembly (struct gdbarch *gdbarch,
>      }
>  }
>  
> +/* The possible choices of "set print frame-info", and the value
> +   of this setting.  */
> +
> +static const char *const print_frame_info_choices[] =
> +  {"src_line", "location", "src_and_loc", "loc_and_address", "short_loc",
> +   "auto", NULL};

I think it would be nicer to use dashes instead of underscores, and not
abbreviate the words.

Andreas.
  
Tom Tromey May 6, 2019, 7:43 p.m. UTC | #2
>>>>> "Philippe" == Philippe Waroquiers <philippe.waroquiers@skynet.be> writes:

Philippe> New settings allow to better control what frame information is printed.
Philippe> 'set print frame-info' allows to override the default frame information
Philippe> printed when a GDB command prints a frame.

Philippe> It is now possible to have very short frame information by using the
Philippe> new 'set print frame-arguments presence' and 'set print frame-info short_loc'.

I didn't read the patch in detail yet, but I noticed this:

Philippe> +	* stack.c (print_frame_arguments_choices): New value 'presence'.
Philippe> +	(print_frame_args): Only print dots for args if print frame-arguments
Philippe> +	is 'presence'.
Philippe> +	(print_what_frame_info_string, print_what_frame_info)
Philippe> +	(set_print_frame_info_command): New variables and function.
Philippe> +	(print_frame_info): Update comment.  Use print_what_frame_info
Philippe> +	to decide what to print.

There's a whole separate set of frame-printing functions in
python/py-framefilter.c.  Those must be updated as well.

thanks,
Tom
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 09a4a0af5a..dd214b47fa 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -6297,3 +6297,17 @@  version-control: never
 coding: utf-8
 End:
 
+2019-05-04  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* NEWS: Mention 'set|show print frame-info'.  Mention new
+	'presence' value for 'frame-arguments'.
+	* frame.h (enum print_what): New value 'SHORT_LOCATION', update
+	comments.
+	* stack.c (print_frame_arguments_choices): New value 'presence'.
+	(print_frame_args): Only print dots for args if print frame-arguments
+	is 'presence'.
+	(print_what_frame_info_string, print_what_frame_info)
+	(set_print_frame_info_command): New variables and function.
+	(print_frame_info): Update comment.  Use print_what_frame_info
+	to decide what to print.
+	(_initialize_stack): Call add_setshow_enum_cmd for frame-info.
diff --git a/gdb/frame.h b/gdb/frame.h
index 0a0baf46a0..4c0ee4d53e 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -675,18 +675,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.
diff --git a/gdb/stack.c b/gdb/stack.c
index e5de10949d..495642a83b 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -57,7 +57,7 @@ 
    of this setting.  */
 
 static const char *const print_frame_arguments_choices[] =
-  {"all", "scalars", "none", NULL};
+  {"all", "scalars", "none", "presence", NULL};
 static const char *print_frame_arguments = "scalars";
 
 /* If non-zero, don't invoke pretty-printers for frame arguments.  */
@@ -539,8 +539,11 @@  print_frame_args (struct symbol *func, struct frame_info *frame,
   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.  */
+  int print_names = strcmp (print_frame_arguments, "presence");
   /* True if we should print arguments, false otherwise.  */
-  int print_args = strcmp (print_frame_arguments, "none");
+  int print_args = print_names && strcmp (print_frame_arguments, "none");
 
   if (func)
     {
@@ -560,6 +563,13 @@  print_frame_args (struct symbol *func, struct frame_info *frame,
 	  if (!SYMBOL_IS_ARGUMENT (sym))
 	    continue;
 
+	  if (!print_names)
+	    {
+	      uiout->text ("...");
+	      first = 0;
+	      break;
+	    }
+
 	  switch (SYMBOL_CLASS (sym))
 	    {
 	    case LOC_ARG:
@@ -708,8 +718,11 @@  print_frame_args (struct symbol *func, struct frame_info *frame,
       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);
     }
 }
 
@@ -766,13 +779,42 @@  do_gdb_disassembly (struct gdbarch *gdbarch,
     }
 }
 
+/* The possible choices of "set print frame-info", and the value
+   of this setting.  */
+
+static const char *const print_frame_info_choices[] =
+  {"src_line", "location", "src_and_loc", "loc_and_address", "short_loc",
+   "auto", NULL};
+static const char *print_what_frame_info_string = "auto";
+static gdb::optional<enum print_what> print_what_frame_info;
+
+/* Set command.  Change the current frame info to print.  */
+
+static void
+set_print_frame_info_command (const char *ignore,
+			      int from_tty, struct cmd_list_element *c)
+{
+  if (strcmp (print_what_frame_info_string, "src_line") == 0)
+    print_what_frame_info = SRC_LINE;
+  else if (strcmp (print_what_frame_info_string, "location") == 0)
+    print_what_frame_info = LOCATION;
+  else if (strcmp (print_what_frame_info_string, "src_and_loc") == 0)
+    print_what_frame_info = SRC_AND_LOC;
+  else if (strcmp (print_what_frame_info_string, "loc_and_address") == 0)
+    print_what_frame_info = LOC_AND_ADDRESS;
+  else if (strcmp (print_what_frame_info_string, "short_loc") == 0)
+    print_what_frame_info = SHORT_LOCATION;
+  else if (strcmp (print_what_frame_info_string, "auto") == 0)
+    print_what_frame_info.reset ();
+  else
+    internal_error (__FILE__, __LINE__,
+		    "Unexpected set print frame-info `%s'.",
+		    print_what_frame_info_string);
+}
+
 /* 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.
 
    Used in "where" output, and to emit breakpoint or step
    messages.  */
@@ -787,6 +829,12 @@  print_frame_info (struct frame_info *frame, int print_level,
   int location_print;
   struct ui_out *uiout = current_uiout;
 
+  if (!current_uiout->is_mi_like_p () && print_what_frame_info.has_value ())
+    {
+      /* Use the specific frame information desired by the user.  */
+      print_what = *print_what_frame_info;
+    }
+
   if (get_frame_type (frame) == DUMMY_FRAME
       || get_frame_type (frame) == SIGTRAMP_FRAME
       || get_frame_type (frame) == ARCH_FRAME)
@@ -850,10 +898,10 @@  print_frame_info (struct frame_info *frame, int print_level,
      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 (frame, print_level, print_what, print_args, sal);
 
@@ -1210,7 +1258,7 @@  print_frame (struct frame_info *frame, int print_level,
 	QUIT;
       }
     uiout->text (")");
-    if (sal.symtab)
+    if (print_what != SHORT_LOCATION && sal.symtab)
       {
 	const char *filename_display;
       
@@ -1233,7 +1281,8 @@  print_frame (struct frame_info *frame, int print_level,
 	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));
@@ -3106,6 +3155,13 @@  Usage: func NAME"));
 			_("Show printing of non-scalar frame arguments"),
 			NULL, NULL, NULL, &setprintlist, &showprintlist);
 
+  add_setshow_enum_cmd ("frame-info", class_stack,
+			print_frame_info_choices, &print_what_frame_info_string,
+			_("Set printing of frame information"),
+			_("Show printing of frame information"),
+			NULL, set_print_frame_info_command, NULL,
+			&setprintlist, &showprintlist);
+
   add_setshow_boolean_cmd ("frame-arguments", no_class,
 			   &print_raw_frame_arguments, _("\
 Set whether to print frame arguments in raw form."), _("\