diff mbox

[RFC] Make sure verbose output is on single line

Message ID 20200301201224.GA17072@delia
State New
Headers show

Commit Message

Tom de Vries March 1, 2020, 8:12 p.m. UTC
Hi,

Consider the following test-case:
...
$ gcc -g src/gdb/testsuite/gdb.base/break-interp-*.c
...

When using:
- "set language c" to avoid loading the full symbol table for
  break-interb-main.c, and
- using "set verbose" to be verbose about symbol table expansion:
...
$ gdb -batch \
    -iex "set verbose" \
    -iex "set language c" \
    -ex r \
    -ex bt \
    --args ./a.out segv
Reading symbols from ./a.out...
Reading symbols from /lib64/ld-linux-x86-64.so.2...
(No debugging symbols found in /lib64/ld-linux-x86-64.so.2)
Reading symbols from system-supplied DSO at 0x7ffff7ffa000...
(No debugging symbols found in system-supplied DSO at 0x7ffff7ffa000)
Reading symbols from /lib64/libc.so.6...
(No debugging symbols found in /lib64/libc.so.6)

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a53160 in raise () from /lib64/libc.so.6
Reading in symbols for src/gdb/testsuite/gdb.base/break-interp-lib.c...done.
\#0  0x00007ffff7a53160 in raise () from /lib64/libc.so.6
\#1  0x0000000000400712 in libfunc (Reading in symbols for \
  src/gdb/testsuite/gdb.base/break-interp-main.c...done.
action=0x7fffffffe0d6 "segv") at src/gdb/testsuite/gdb.base/break-interp-lib.c:34
\#2  0x00000000004007a4 in main (argc=2, argv=0x7fffffffdbd8) at \
  src/gdb/testsuite/gdb.base/break-interp-main.c:27
...
we get the "Reading in symbols for break-interp-main.c...done" message
(triggered by verbose) in the middle of the libfunc backtrace line.

This patch attempts to get that message on its own line, like so:
...
\#0  0x00007ffff7a53160 in raise () from /lib64/libc.so.6
Reading in symbols for src/gdb/testsuite/gdb.base/break-interp-main.c...done.
\#1  0x0000000000400712 in libfunc (action=0x7fffffffe0d6 "segv") at \
  src/gdb/testsuite/gdb.base/break-interp-lib.c:34
\#2  0x00000000004007a4 in main (argc=2, argv=0x7fffffffdbd8) at \
  src/gdb/testsuite/gdb.base/break-interp-main.c:27...

It tries to achieve that by:
- printing the verbose message to gdb_stdlog instead of gdb_stdout
- capturing print_frame output in a string_file temporary, which is then
  output as a single line

The latter caused regressions in annotate test-cases, which has been fixed by
replacing printf_filtered by current_uiout->message in the relevant annotate
functions.

The patch contains a test-case that passes.

The patch has been build and reg-tested on x86_64-linux, with the following
regressions:
...
FAIL: gdb.base/style-logging.exp: frame
FAIL: gdb.base/style.exp: frame
FAIL: gdb.base/style.exp: frame when width=20
FAIL: gdb.base/style.exp: frame when width=30
FAIL: gdb.opt/inline-cmds.exp: mi: step into inline call (timeout)
...

The gdb.opt/inline-cmds.exp failure probably means that the
current_uiout->is_mi_like_p () test in print_frame_info needs tweaking.

The first gdb.base/style.exp failure is related to missing styling, and I
assume to the other failures are likewise.

Any ideas on how to fix the FAILs?

Any other comments?

Thanks,
- Tom

[gdb] Make sure verbose output is on single line

---
 gdb/annotate.c                               | 48 ++++++++++++++--------------
 gdb/psymtab.c                                |  8 ++---
 gdb/stack.c                                  | 17 +++++++++-
 gdb/testsuite/gdb.base/verbose-backtrace.exp | 38 ++++++++++++++++++++++
 4 files changed, 82 insertions(+), 29 deletions(-)
diff mbox

Patch

diff --git a/gdb/annotate.c b/gdb/annotate.c
index cf9e88cee5..0406cc5215 100644
--- a/gdb/annotate.c
+++ b/gdb/annotate.c
@@ -52,9 +52,9 @@  static void
 print_value_flags (struct type *t)
 {
   if (can_dereference (t))
-    printf_filtered (("*"));
+    current_uiout->message (("*"));
   else
-    printf_filtered (("-"));
+    current_uiout->message (("-"));
 }
 
 static void
@@ -104,7 +104,7 @@  void
 annotate_stopped (void)
 {
   if (annotation_level > 1)
-    printf_filtered (("\n\032\032stopped\n"));
+    current_uiout->message (("\n\032\032stopped\n"));
 }
 
 void
@@ -207,7 +207,7 @@  annotate_frames_invalid (void)
       target_terminal::scoped_restore_terminal_state term_state;
       target_terminal::ours_for_output ();
 
-      printf_unfiltered (("\n\032\032frames-invalid\n"));
+      current_uiout->message (("\n\032\032frames-invalid\n"));
       frames_invalid_emitted = 1;
     }
 }
@@ -237,9 +237,9 @@  annotate_thread_exited (struct thread_info *t, int silent)
 {
   if (annotation_level > 1)
     {
-      printf_filtered(("\n\032\032thread-exited,"
-                       "id=\"%d\",group-id=\"i%d\"\n"),
-                      t->global_num, t->inf->num);
+      current_uiout->message(("\n\032\032thread-exited,"
+			      "id=\"%d\",group-id=\"i%d\"\n"),
+			     t->global_num, t->inf->num);
     }
 }
 
@@ -392,14 +392,14 @@  void
 annotate_arg_begin (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032arg-begin\n"));
+    current_uiout->message (("\n\032\032arg-begin\n"));
 }
 
 void
 annotate_arg_name_end (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032arg-name-end\n"));
+    current_uiout->message (("\n\032\032arg-name-end\n"));
 }
 
 void
@@ -407,9 +407,9 @@  annotate_arg_value (struct type *type)
 {
   if (annotation_level == 2)
     {
-      printf_filtered (("\n\032\032arg-value "));
+      current_uiout->message (("\n\032\032arg-value "));
       print_value_flags (type);
-      printf_filtered (("\n"));
+      current_uiout->message (("\n"));
     }
 }
 
@@ -417,7 +417,7 @@  void
 annotate_arg_end (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032arg-end\n"));
+    current_uiout->message (("\n\032\032arg-end\n"));
 }
 
 static void
@@ -460,8 +460,8 @@  void
 annotate_frame_begin (int level, struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   if (annotation_level > 1)
-    printf_filtered (("\n\032\032frame-begin %d %s\n"),
-		     level, paddress (gdbarch, pc));
+    current_uiout->message (("\n\032\032frame-begin %d %s\n"),
+			    level, paddress (gdbarch, pc));
 }
 
 void
@@ -482,70 +482,70 @@  void
 annotate_frame_address (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-address\n"));
+    current_uiout->message (("\n\032\032frame-address\n"));
 }
 
 void
 annotate_frame_address_end (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-address-end\n"));
+    current_uiout->message (("\n\032\032frame-address-end\n"));
 }
 
 void
 annotate_frame_function_name (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-function-name\n"));
+    current_uiout->message (("\n\032\032frame-function-name\n"));
 }
 
 void
 annotate_frame_args (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-args\n"));
+    current_uiout->message (("\n\032\032frame-args\n"));
 }
 
 void
 annotate_frame_source_begin (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-source-begin\n"));
+    current_uiout->message (("\n\032\032frame-source-begin\n"));
 }
 
 void
 annotate_frame_source_file (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-source-file\n"));
+    current_uiout->message (("\n\032\032frame-source-file\n"));
 }
 
 void
 annotate_frame_source_file_end (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-source-file-end\n"));
+    current_uiout->message (("\n\032\032frame-source-file-end\n"));
 }
 
 void
 annotate_frame_source_line (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-source-line\n"));
+    current_uiout->message (("\n\032\032frame-source-line\n"));
 }
 
 void
 annotate_frame_source_end (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-source-end\n"));
+    current_uiout->message (("\n\032\032frame-source-end\n"));
 }
 
 void
 annotate_frame_where (void)
 {
   if (annotation_level == 2)
-    printf_filtered (("\n\032\032frame-where\n"));
+    current_uiout->message (("\n\032\032frame-where\n"));
 }
 
 void
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index fd7fc8feff..1210a6564f 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -760,16 +760,16 @@  psymtab_to_symtab (struct objfile *objfile, struct partial_symtab *pst)
 
       if (info_verbose)
 	{
-	  printf_filtered (_("Reading in symbols for %s..."),
-			   pst->filename);
-	  gdb_flush (gdb_stdout);
+	  fprintf_filtered (gdb_stdlog, _("Reading in symbols for %s..."),
+			    pst->filename);
+	  gdb_flush (gdb_stdlog);
 	}
 
       pst->read_symtab (objfile);
 
       /* Finish up the debug error message.  */
       if (info_verbose)
-	printf_filtered (_("done.\n"));
+	fprintf_filtered (gdb_stdlog, _("done.\n"));
     }
 
   return pst->get_compunit_symtab ();
diff --git a/gdb/stack.c b/gdb/stack.c
index 266d771e35..2a063ad9b5 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1110,7 +1110,22 @@  print_frame_info (const frame_print_options &fp_opts,
 		    || print_what == LOC_AND_ADDRESS
 		    || print_what == SHORT_LOCATION);
   if (location_print || !sal.symtab)
-    print_frame (fp_opts, frame, print_level, print_what, print_args, sal);
+    {
+      if (current_uiout->is_mi_like_p ())
+	{
+	  print_frame (fp_opts, frame, print_level, print_what, print_args, sal);
+	}
+      else
+	{
+	  string_file tmp_stream (false);
+	  {
+	    current_uiout->redirect (&tmp_stream);
+	    print_frame (fp_opts, frame, print_level, print_what, print_args, sal);
+	    current_uiout->redirect (NULL);
+	  }
+	  gdb_stdout->printf ("%s", tmp_stream.string ().c_str());
+	}
+    }
 
   source_print = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
 
diff --git a/gdb/testsuite/gdb.base/verbose-backtrace.exp b/gdb/testsuite/gdb.base/verbose-backtrace.exp
new file mode 100644
index 0000000000..c81ff53382
--- /dev/null
+++ b/gdb/testsuite/gdb.base/verbose-backtrace.exp
@@ -0,0 +1,38 @@ 
+# Copyright 2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile "break-interp-main.c break-interp-lib.c"
+
+if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
+    return -1
+}
+
+clean_restart
+
+# Generate "Reading in symbols for" messages.
+gdb_test_no_output "set verbose"
+
+# Don't trigger psymtab expansion for break-interp-main.c
+gdb_test_no_output "set language c"
+
+gdb_load $binfile
+
+gdb_test "run segv"
+
+# Check that "Reading in symbols for" message has aline of its own.
+set filename "\[^\r\n\]*/gdb.base/break-interp-main.c"
+gdb_test "bt" \
+    "\r\nReading in symbols for $filename...done\.\r\n.*" \
+    "verbose message on own line"