PR gdb/13860: make "-exec-foo"'s MI output equal to "foo"'s MI output.
authorPedro Alves <palves@redhat.com>
Tue, 18 Mar 2014 17:50:28 +0000 (17:50 +0000)
committerPedro Alves <palves@redhat.com>
Tue, 18 Mar 2014 17:50:28 +0000 (17:50 +0000)
Part of PR gdb/13860 is about the mi-solib.exp test's output being
different in sync vs async modes.

sync:

  >./gdb -nx -q ./testsuite/gdb.mi/solib-main -ex "set stop-on-solib-events 1" -ex "set target-async off" -i=mi
  =thread-group-added,id="i1"
  ~"Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main..."
  ~"done.\n"
  (gdb)
  &"start\n"
  ~"Temporary breakpoint 1 at 0x400608: file ../../../src/gdb/testsuite/gdb.mi/solib-main.c, line 21.\n"
  =breakpoint-created,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x0000000000400608",func="main",file="../../../src/gdb/testsuite/gdb.mi/solib-main.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/solib-main.c",line="21",times="0",original-location="main"}
  ~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
  =thread-group-started,id="i1",pid="17724"
  =thread-created,id="1",group-id="i1"
  ^running
  *running,thread-id="all"
  (gdb)
  =library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
  ~"Stopped due to shared library event (no libraries added or removed)\n"
  *stopped,reason="solib-event",frame={addr="0x000000379180f990",func="_dl_debug_state",args=[],from="/lib64/ld-linux-x86-64.so.2"},thread-id="1",stopped-threads="all",core="3"
  (gdb)

async:

  >./gdb -nx -q ./testsuite/gdb.mi/solib-main -ex "set stop-on-solib-events 1" -ex "set target-async on" -i=mi
  =thread-group-added,id="i1"
  ~"Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main..."
  ~"done.\n"
  (gdb)
  start
  &"start\n"
  ~"Temporary breakpoint 1 at 0x400608: file ../../../src/gdb/testsuite/gdb.mi/solib-main.c, line 21.\n"
  =breakpoint-created,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x0000000000400608",func="main",file="../../../src/gdb/testsuite/gdb.mi/solib-main.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.mi/solib-main.c",line="21",times="0",original-location="main"}
  ~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
  =thread-group-started,id="i1",pid="17729"
  =thread-created,id="1",group-id="i1"
  ^running
  *running,thread-id="all"
  =library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
  (gdb)
  *stopped,reason="solib-event",thread-id="1",stopped-threads="all",core="1"

For now, let's focus only on the *stopped event.  We see that the
async output is missing frame info.  And this causes a test failure in
async mode, as "mi_expect_stop solib-event" wants to see the frame
info.

However, if we compare the event output when a real MI execution
command is used, compared to a CLI command (e.g., run vs -exec-run,
next vs -exec-next, etc.), we see:

  >./gdb -nx -q ./testsuite/gdb.mi/solib-main -ex "set stop-on-solib-events 1" -ex "set target-async off" -i=mi
  =thread-group-added,id="i1"
  ~"Reading symbols from /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main..."
  ~"done.\n"
  (gdb)
  r
  &"r\n"
  ~"Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.mi/solib-main \n"
  =thread-group-started,id="i1",pid="17751"
  =thread-created,id="1",group-id="i1"
  ^running
  *running,thread-id="all"
  (gdb)
  =library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
  ~"Stopped due to shared library event (no libraries added or removed)\n"
  *stopped,reason="solib-event",frame={addr="0x000000379180f990",func="_dl_debug_state",args=[],from="/lib64/ld-linux-x86-64.so.2"},thread-id="1",stopped-threads="all",core="3"
  (gdb)
  -exec-run
  =thread-exited,id="1",group-id="i1"
  =thread-group-exited,id="i1"
  =library-unloaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",thread-group="i1"
  =thread-group-started,id="i1",pid="17754"
  =thread-created,id="1",group-id="i1"
  ^running
  *running,thread-id="all"
  (gdb)
  =library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
  *stopped,reason="solib-event",thread-id="1",stopped-threads="all",core="1"
  =thread-selected,id="1"
  (gdb)

As seen above, with MI commands, the *stopped event _doesn't_ have
frame info.  This is because normal_stop, as commanded by the result
of bpstat_print, skips printing frame info in this case (it's an
"event", not a "breakpoint"), and when the interpreter is MI,
mi_on_normal_stop skips calling print_stack_frame, as the normal_stop
call was already done with the MI uiout.  This explains why the async
output is different even with a CLI command.  Its because in async
mode, the mi_on_normal_stop path is always taken; it is always reached
with the MI uiout, because the stop is handled from the event loop,
instead of from within `proceed -> wait_for_inferior -> normal_stop'
with the interpreter overridden, as in sync mode.

This patch fixes the issue by making all cases output the same
*stopped event, by factoring out the print code from normal_stop, and
using it from mi_on_normal_stop as well.  I chose the *stopped output
without a frame, mainly because that is what you already get if you
use MI execution commands, the commands frontends are supposed to use
(except when implementing a console).  This patch makes it simpler to
tweak the MI output differently if desired, as we only have to change
the centralized print_stop_event (taking into account whether the
uiout is MI-like), and all different modes will change accordingly.

Tested on x86_64 Fedora 17, no regressions.  The mi-solib.exp test no
longer fails in async mode with this patch, so the patch removes the
kfail.

2014-03-18  Pedro Alves  <palves@redhat.com>

PR gdb/13860
* inferior.h (print_stop_event): Declare.
* infrun.c (print_stop_event): New, factored out from ...
(normal_stop): ... this.
* mi/mi-interp.c (mi_on_normal_stop): Use print_stop_event instead
of bpstat_print/print_stack_frame.

2014-03-18  Pedro Alves  <palves@redhat.com>

PR gdb/13860
* gdb.mi/mi-solib.exp: Remove gdb/13860 kfail.
* lib/mi-support.exp (mi_expect_stop): Add special handling for
solib-event.

gdb/ChangeLog
gdb/inferior.h
gdb/infrun.c
gdb/mi/mi-interp.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.mi/mi-solib.exp
gdb/testsuite/lib/mi-support.exp

index 8b54b59d712737c94c192ead062a8be5df8f8b29..1c689378c9aaea04488fc5612e5fe708f3bfd35c 100644 (file)
@@ -1,3 +1,12 @@
+2014-03-18  Pedro Alves  <palves@redhat.com>
+
+       PR gdb/13860
+       * inferior.h (print_stop_event): Declare.
+       * infrun.c (print_stop_event): New, factored out from ...
+       (normal_stop): ... this.
+       * mi/mi-interp.c (mi_on_normal_stop): Use print_stop_event instead
+       of bpstat_print/print_stack_frame.
+
 2014-03-17  Tom Tromey  <tromey@redhat.com>
 
        * ui-out.c (clear_table, ui_out_new): Clear uiout->table.id.
index 6c0730af01624d5057358993b5288e21b85dc0d6..b15f692a654fbe110abb2ea399e5cbcda7e440b1 100644 (file)
@@ -195,6 +195,8 @@ extern void start_remote (int from_tty);
 
 extern void normal_stop (void);
 
+extern void print_stop_event (struct target_waitstatus *ws);
+
 extern int signal_stop_state (int);
 
 extern int signal_print_state (int);
index b7c09692ac53f39b3440304cea8f5c1423e3e71a..fe5d88bb3d7647f158054c6a71c42336b83b9fa1 100644 (file)
@@ -5996,6 +5996,68 @@ print_no_history_reason (void)
   ui_out_text (current_uiout, "\nNo more reverse-execution history.\n");
 }
 
+/* Print current location without a level number, if we have changed
+   functions or hit a breakpoint.  Print source line if we have one.
+   bpstat_print contains the logic deciding in detail what to print,
+   based on the event(s) that just occurred.  */
+
+void
+print_stop_event (struct target_waitstatus *ws)
+{
+  int bpstat_ret;
+  int source_flag;
+  int do_frame_printing = 1;
+  struct thread_info *tp = inferior_thread ();
+
+  bpstat_ret = bpstat_print (tp->control.stop_bpstat, ws->kind);
+  switch (bpstat_ret)
+    {
+    case PRINT_UNKNOWN:
+      /* FIXME: cagney/2002-12-01: Given that a frame ID does (or
+        should) carry around the function and does (or should) use
+        that when doing a frame comparison.  */
+      if (tp->control.stop_step
+         && frame_id_eq (tp->control.step_frame_id,
+                         get_frame_id (get_current_frame ()))
+         && step_start_function == find_pc_function (stop_pc))
+       {
+         /* Finished step, just print source line.  */
+         source_flag = SRC_LINE;
+       }
+      else
+       {
+         /* Print location and source line.  */
+         source_flag = SRC_AND_LOC;
+       }
+      break;
+    case PRINT_SRC_AND_LOC:
+      /* Print location and source line.  */
+      source_flag = SRC_AND_LOC;
+      break;
+    case PRINT_SRC_ONLY:
+      source_flag = SRC_LINE;
+      break;
+    case PRINT_NOTHING:
+      /* Something bogus.  */
+      source_flag = SRC_LINE;
+      do_frame_printing = 0;
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, _("Unknown value."));
+    }
+
+  /* The behavior of this routine with respect to the source
+     flag is:
+     SRC_LINE: Print only source line
+     LOCATION: Print only location
+     SRC_AND_LOC: Print location and source line.  */
+  if (do_frame_printing)
+    print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
+
+  /* Display the auto-display expressions.  */
+  do_displays ();
+}
+
 /* Here to return control to GDB when the inferior stops for real.
    Print appropriate messages, remove breakpoints, give terminal our modes.
 
@@ -6118,65 +6180,11 @@ normal_stop (void)
     {
       select_frame (get_current_frame ());
 
-      /* Print current location without a level number, if
-         we have changed functions or hit a breakpoint.
-         Print source line if we have one.
-         bpstat_print() contains the logic deciding in detail
-         what to print, based on the event(s) that just occurred.  */
-
       /* If --batch-silent is enabled then there's no need to print the current
         source location, and to try risks causing an error message about
         missing source files.  */
       if (stop_print_frame && !batch_silent)
-       {
-         int bpstat_ret;
-         int source_flag;
-         int do_frame_printing = 1;
-         struct thread_info *tp = inferior_thread ();
-
-         bpstat_ret = bpstat_print (tp->control.stop_bpstat, last.kind);
-         switch (bpstat_ret)
-           {
-           case PRINT_UNKNOWN:
-             /* FIXME: cagney/2002-12-01: Given that a frame ID does
-                (or should) carry around the function and does (or
-                should) use that when doing a frame comparison.  */
-             if (tp->control.stop_step
-                 && frame_id_eq (tp->control.step_frame_id,
-                                 get_frame_id (get_current_frame ()))
-                 && step_start_function == find_pc_function (stop_pc))
-               source_flag = SRC_LINE;         /* Finished step, just
-                                                  print source line.  */
-             else
-               source_flag = SRC_AND_LOC;      /* Print location and
-                                                  source line.  */
-             break;
-           case PRINT_SRC_AND_LOC:
-             source_flag = SRC_AND_LOC;        /* Print location and
-                                                  source line.  */
-             break;
-           case PRINT_SRC_ONLY:
-             source_flag = SRC_LINE;
-             break;
-           case PRINT_NOTHING:
-             source_flag = SRC_LINE;   /* something bogus */
-             do_frame_printing = 0;
-             break;
-           default:
-             internal_error (__FILE__, __LINE__, _("Unknown value."));
-           }
-
-         /* The behavior of this routine with respect to the source
-            flag is:
-            SRC_LINE: Print only source line
-            LOCATION: Print only location
-            SRC_AND_LOC: Print location and source line.  */
-         if (do_frame_printing)
-           print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
-
-         /* Display the auto-display expressions.  */
-         do_displays ();
-       }
+       print_stop_event (&last);
     }
 
   /* Save the function value return registers, if we care.
index 25bf0a12470a376200da34a399563c7b33339c88..862beafbaf4d27a1f8726c4922e5d2dac48e9519 100644 (file)
@@ -441,9 +441,8 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame)
          current_uiout = mi_uiout;
 
          get_last_target_status (&last_ptid, &last);
-         bpstat_print (bs, last.kind);
+         print_stop_event (&last);
 
-         print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
          current_uiout = saved_uiout;
        }
 
index 4e6e248fa1a4b5aeb9637b30059920190af01643..458e7954923d1bd27bcbd3317ff4b7c5eee00715 100644 (file)
@@ -1,3 +1,10 @@
+2014-03-18  Pedro Alves  <palves@redhat.com>
+
+       PR gdb/13860
+       * gdb.mi/mi-solib.exp: Remove gdb/13860 kfail.
+       * lib/mi-support.exp (mi_expect_stop): Add special handling for
+       solib-event.
+
 2014-03-17  Joel Brobecker  <brobecker@adacore.com>
 
        * gdb.ada/pckd_arr_ren: New testcase.
index 06fa26b4bca60f8d27524c5beb11a2ef19f3568f..608d2b783498441524b217a0f9a25a248eb2701d 100644 (file)
@@ -60,8 +60,4 @@ mi_gdb_test "777-gdb-set stop-on-solib-events 1" "777\\^done" \
 # commands still cause the correct MI output to be generated.
 mi_run_with_cli
 
-global async
-if { $async } {
-    setup_kfail gdb/13860 *-*-*
-}
 mi_expect_stop solib-event .* .* .* .* .* "check for solib event"
index 1e8fee66885c3dd4c9a9d820c1bd1b7eccac0671..213073acba9ad4e9559d975f8c972026483d65b7 100644 (file)
@@ -1028,6 +1028,8 @@ proc mi_expect_stop { reason func args file line extra test } {
     global thread_selected_re
     global breakpoint_re
 
+    set any "\[^\n\]*"
+
     set after_stopped ""
     set after_reason ""
     if { [llength $extra] == 2 } {
@@ -1070,6 +1072,20 @@ proc mi_expect_stop { reason func args file line extra test } {
        return
     }
 
+    if { $reason == "solib-event" } {
+       set pattern "\\*stopped,reason=\"solib-event\",thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re"
+       verbose -log "mi_expect_stop: expecting: $pattern"
+       gdb_expect {
+           -re "$pattern" {
+               pass "$test"
+           }
+           timeout {
+               fail "$test (unknown output after running)"
+           }
+       }
+       return
+    }
+
     set args "\\\[$args\\\]"
 
     set bn ""
@@ -1087,8 +1103,6 @@ proc mi_expect_stop { reason func args file line extra test } {
 
     set a $after_reason
 
-    set any "\[^\n\]*"
-
     verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,(?:file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"|from=\"$file\")\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re"
     gdb_expect {
        -re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,(?:file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"|from=\"$file\")\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re" {