Push thread->control.command_interp to the struct thread_fsm
authorPedro Alves <palves@redhat.com>
Tue, 21 Jun 2016 00:11:53 +0000 (01:11 +0100)
committerPedro Alves <palves@redhat.com>
Tue, 21 Jun 2016 00:11:53 +0000 (01:11 +0100)
I noticed that if we step into an inline function, step_1 never
reaches proceed, and thus nevers sets the thread's
tp->control.command_interp.  Because of that,
should_print_stop_to_console fails to determine that is should print
stop output to the console.

The fix is to set the thread's command_interp earlier.  However, I
realized that we can move that field to the thread_fsm, given that its
lifetime is exactly the same as thread_fsm.  So the patch plumbs all
fsms constructors to take the command interp and store it in the
thread_fsm.

We can see the fix in action, with e.g., the gdb.opt/inline-cmds.exp
test, and issuing a step when stopped at line 67:

 &"s\n"
 ^running
 *running,thread-id="all"
 (gdb)
 ~"67\t  result = func2 ();\n"
 *stopped,reason="end-stepping-range",frame={addr="0x00000000004004d0",func="main",args=[],file="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",line="67"},thread-id="1",stopped-threads="all",core="0"
 (gdb)
 s
 &"s\n"
 ^running
 *running,thread-id="all"
 (gdb)
+ ~"func2 () at /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c:67\n"
+ ~"67\t  result = func2 ();\n"
 *stopped,reason="end-stepping-range",frame={addr="0x00000000004004d0",func="func2",args=[],file="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",fullname="/home/pedro/gdb/mygit/src/gdb/testsuite/gdb.opt/inline-cmds.c",line="67"},thread-id="1",stopped-threads="all",core="0"
 (gdb)

(The inline-cmds.exp command is adjusted to exercise this.)

(Due to the follow_fork change, this also fixes "next N" across a fork
with "set follow-fork child" with "set detach-on-fork on".  Commands
that rely on internal breakpoints, like "finish" will still require
more work to migrate breakpoints etc. to the child thread.)

gdb/ChangeLog:
2016-06-21  Pedro Alves  <palves@redhat.com>

* breakpoint.c (new_until_break_fsm): Add 'cmd_interp' parameter.
(until_break_fsm_should_stop, until_break_fsm_clean_up): Add
thread parameter.
(until_break_command): Pass command interpreter to thread fsm
ctor.
* cli/cli-interp.c (should_print_stop_to_console): Adjust.
* gdbthread.h (struct thread_control_state) <command_interp>:
Delete field.
* infcall.c (new_call_thread_fsm): Add 'cmd_interp' parameter.
Pass it down.
(call_thread_fsm_should_stop): Add thread parameter.
(call_function_by_hand_dummy): Pass command interpreter to thread
fsm ctor.  Pass thread pointer to fsm clean up method.
* infcmd.c: Include interps.h.
(struct step_command_fsm) <thread>: Delete field.
(new_step_command_fsm): Add 'cmd_interp' parameter.  Pass it down.
(step_command_fsm_prepare): Remove references to fsm's thread
field.
(step_1): Pass command interpreter to thread
fsm ctor.  Pass thread pointer to fsm clean up method.
(step_command_fsm_should_stop, step_command_fsm_clean_up): Add
thread parameter and use it.
(new_until_next_fsm): Add 'cmd_interp' parameter.  Pass it down.
(until_next_fsm_should_stop, until_next_fsm_clean_up): Add thread
parameter and use it.
(until_next_command): Pass command interpreter to thread fsm ctor.
(struct finish_command_fsm) <thread>: Delete field.
(finish_command_fsm_ops): Add NULL slot for should_notify_stop.
(new_finish_command_fsm): Add 'cmd_interp' parameter and pass it
down.  Remove thread parameter and adjust.
(finish_command_fsm_should_stop, finish_command_fsm_clean_up): Add
thread parameter and use it.
(finish_command): Pass command interpreter to thread fsm ctor.
Don't pass thread.
* infrun.c (follow_fork): Move thread fsm to child fork instead of
command interpreter, only.
(clear_proceed_status_thread): Remove reference to command_interp.
(proceed): Don't record the thread's command interpreter.
(clean_up_just_stopped_threads_fsms): Pass thread to fsm clean_up
method.
(fetch_inferior_event): Pass thread to fsm should_stop method.
* thread-fsm.c (thread_fsm_ctor): Add 'cmd_interp' parameter.
Store it.
(thread_fsm_clean_up, thread_fsm_should_stop): Add thread
parameter and pass it down.
* thread-fsm.h (struct thread_fsm) <command_interp>: New field.
(struct thread_fsm_ops) <clean_up, should_stop>: Add thread
parameter.
(thread_fsm_ctor): Add 'cmd_interp' parameter.
(thread_fsm_clean_up, thread_fsm_should_stop): Add thread
parameter.
* thread.c (thread_cancel_execution_command): Pass thread to
thread fsm clean_up method.

gdb/testsuite/ChangeLog:
2016-06-21  Pedro Alves  <palves@redhat.com>

* gdb.opt/inline-cmds.c: Add "set mi break here" marker.
* gdb.opt/inline-cmds.exp: Add MI tests.

13 files changed:
gdb/ChangeLog
gdb/breakpoint.c
gdb/cli/cli-interp.c
gdb/gdbthread.h
gdb/infcall.c
gdb/infcmd.c
gdb/infrun.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.opt/inline-cmds.c
gdb/testsuite/gdb.opt/inline-cmds.exp
gdb/thread-fsm.c
gdb/thread-fsm.h
gdb/thread.c

index 49ea003c8ed8f259e9633d87253b0dffa950fcbc..cf50f9dd6881ce3f61522f5a1650de61a435ed74 100644 (file)
@@ -1,3 +1,59 @@
+2016-06-21  Pedro Alves  <palves@redhat.com>
+
+       * breakpoint.c (new_until_break_fsm): Add 'cmd_interp' parameter.
+       (until_break_fsm_should_stop, until_break_fsm_clean_up): Add
+       thread parameter.
+       (until_break_command): Pass command interpreter to thread fsm
+       ctor.
+       * cli/cli-interp.c (should_print_stop_to_console): Adjust.
+       * gdbthread.h (struct thread_control_state) <command_interp>:
+       Delete field.
+       * infcall.c (new_call_thread_fsm): Add 'cmd_interp' parameter.
+       Pass it down.
+       (call_thread_fsm_should_stop): Add thread parameter.
+       (call_function_by_hand_dummy): Pass command interpreter to thread
+       fsm ctor.  Pass thread pointer to fsm clean up method.
+       * infcmd.c: Include interps.h.
+       (struct step_command_fsm) <thread>: Delete field.
+       (new_step_command_fsm): Add 'cmd_interp' parameter.  Pass it down.
+       (step_command_fsm_prepare): Remove references to fsm's thread
+       field.
+       (step_1): Pass command interpreter to thread
+       fsm ctor.  Pass thread pointer to fsm clean up method.
+       (step_command_fsm_should_stop, step_command_fsm_clean_up): Add
+       thread parameter and use it.
+       (new_until_next_fsm): Add 'cmd_interp' parameter.  Pass it down.
+       (until_next_fsm_should_stop, until_next_fsm_clean_up): Add thread
+       parameter and use it.
+       (until_next_command): Pass command interpreter to thread fsm ctor.
+       (struct finish_command_fsm) <thread>: Delete field.
+       (finish_command_fsm_ops): Add NULL slot for should_notify_stop.
+       (new_finish_command_fsm): Add 'cmd_interp' parameter and pass it
+       down.  Remove thread parameter and adjust.
+       (finish_command_fsm_should_stop, finish_command_fsm_clean_up): Add
+       thread parameter and use it.
+       (finish_command): Pass command interpreter to thread fsm ctor.
+       Don't pass thread.
+       * infrun.c (follow_fork): Move thread fsm to child fork instead of
+       command interpreter, only.
+       (clear_proceed_status_thread): Remove reference to command_interp.
+       (proceed): Don't record the thread's command interpreter.
+       (clean_up_just_stopped_threads_fsms): Pass thread to fsm clean_up
+       method.
+       (fetch_inferior_event): Pass thread to fsm should_stop method.
+       * thread-fsm.c (thread_fsm_ctor): Add 'cmd_interp' parameter.
+       Store it.
+       (thread_fsm_clean_up, thread_fsm_should_stop): Add thread
+       parameter and pass it down.
+       * thread-fsm.h (struct thread_fsm) <command_interp>: New field.
+       (struct thread_fsm_ops) <clean_up, should_stop>: Add thread
+       parameter.
+       (thread_fsm_ctor): Add 'cmd_interp' parameter.
+       (thread_fsm_clean_up, thread_fsm_should_stop): Add thread
+       parameter.
+       * thread.c (thread_cancel_execution_command): Pass thread to
+       thread fsm clean_up method.
+
 2016-06-21  Pedro Alves  <palves@redhat.com>
 
        * cli/cli-interp.c: Include gdbthread.h and thread-fsm.h.
index 5bad16d8dc2ce6714dd2439963910119803022f9..27ca2040dbc379e3f9ecf51197725aaaa45d1059 100644 (file)
@@ -11605,8 +11605,10 @@ struct until_break_fsm
   struct breakpoint *caller_breakpoint;
 };
 
-static void until_break_fsm_clean_up (struct thread_fsm *self);
-static int until_break_fsm_should_stop (struct thread_fsm *self);
+static void until_break_fsm_clean_up (struct thread_fsm *self,
+                                     struct thread_info *thread);
+static int until_break_fsm_should_stop (struct thread_fsm *self,
+                                       struct thread_info *thread);
 static enum async_reply_reason
   until_break_fsm_async_reply_reason (struct thread_fsm *self);
 
@@ -11624,14 +11626,14 @@ static struct thread_fsm_ops until_break_fsm_ops =
 /* Allocate a new until_break_command_fsm.  */
 
 static struct until_break_fsm *
-new_until_break_fsm (int thread,
+new_until_break_fsm (struct interp *cmd_interp, int thread,
                     struct breakpoint *location_breakpoint,
                     struct breakpoint *caller_breakpoint)
 {
   struct until_break_fsm *sm;
 
   sm = XCNEW (struct until_break_fsm);
-  thread_fsm_ctor (&sm->thread_fsm, &until_break_fsm_ops);
+  thread_fsm_ctor (&sm->thread_fsm, &until_break_fsm_ops, cmd_interp);
 
   sm->thread = thread;
   sm->location_breakpoint = location_breakpoint;
@@ -11644,10 +11646,10 @@ new_until_break_fsm (int thread,
    until(location)/advance commands.  */
 
 static int
-until_break_fsm_should_stop (struct thread_fsm *self)
+until_break_fsm_should_stop (struct thread_fsm *self,
+                            struct thread_info *tp)
 {
   struct until_break_fsm *sm = (struct until_break_fsm *) self;
-  struct thread_info *tp = inferior_thread ();
 
   if (bpstat_find_breakpoint (tp->control.stop_bpstat,
                              sm->location_breakpoint) != NULL
@@ -11663,7 +11665,8 @@ until_break_fsm_should_stop (struct thread_fsm *self)
    until(location)/advance commands.  */
 
 static void
-until_break_fsm_clean_up (struct thread_fsm *self)
+until_break_fsm_clean_up (struct thread_fsm *self,
+                         struct thread_info *thread)
 {
   struct until_break_fsm *sm = (struct until_break_fsm *) self;
 
@@ -11785,7 +11788,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
                                                    stack_frame_id, bp_until);
   make_cleanup_delete_breakpoint (location_breakpoint);
 
-  sm = new_until_break_fsm (tp->global_num,
+  sm = new_until_break_fsm (command_interp (), tp->global_num,
                            location_breakpoint, caller_breakpoint);
   tp->thread_fsm = &sm->thread_fsm;
 
index b0eef293971f4c391c8281d608b1a25f1e79dd63..97fd713ccd3e9a78c2af2f77db21b9b7ab6e41ee 100644 (file)
@@ -77,10 +77,9 @@ should_print_stop_to_console (struct interp *console_interp,
 {
   if ((bpstat_what (tp->control.stop_bpstat).main_action
        == BPSTAT_WHAT_STOP_NOISY)
-      || !(tp->thread_fsm != NULL
-          && thread_fsm_finished_p (tp->thread_fsm))
-      || (tp->control.command_interp != NULL
-         && tp->control.command_interp == console_interp))
+      || tp->thread_fsm == NULL
+      || tp->thread_fsm->command_interp == console_interp
+      || !thread_fsm_finished_p (tp->thread_fsm))
     return 1;
   return 0;
 }
index bdd2bb0d49a038d3a77e60e53d525416700f255d..af2dc860d1a405902b569bf042c60620b4d69eb8 100644 (file)
@@ -136,11 +136,6 @@ struct thread_control_state
      at.  */
   bpstat stop_bpstat;
 
-  /* The interpreter that issued the execution command.  NULL if the
-     thread was resumed as a result of a command applied to some other
-     thread (e.g., "next" with scheduler-locking off).  */
-  struct interp *command_interp;
-
   /* Whether the command that started the thread was a stepping
      command.  This is used to decide whether "set scheduler-locking
      step" behaves like "on" or "off".  */
index d491f9526fa98da5fa5d37f1420674581a91b17b..8199bdd38d3baf9083c1c4fd2037434716f7cdac 100644 (file)
@@ -470,7 +470,8 @@ struct call_thread_fsm
   struct ui *waiting_ui;
 };
 
-static int call_thread_fsm_should_stop (struct thread_fsm *self);
+static int call_thread_fsm_should_stop (struct thread_fsm *self,
+                                       struct thread_info *thread);
 static int call_thread_fsm_should_notify_stop (struct thread_fsm *self);
 
 /* call_thread_fsm's vtable.  */
@@ -488,7 +489,7 @@ static struct thread_fsm_ops call_thread_fsm_ops =
 /* Allocate a new call_thread_fsm object.  */
 
 static struct call_thread_fsm *
-new_call_thread_fsm (struct ui *waiting_ui,
+new_call_thread_fsm (struct ui *waiting_ui, struct interp *cmd_interp,
                     struct gdbarch *gdbarch, struct value *function,
                     struct type *value_type,
                     int struct_return_p, CORE_ADDR struct_addr)
@@ -496,7 +497,7 @@ new_call_thread_fsm (struct ui *waiting_ui,
   struct call_thread_fsm *sm;
 
   sm = XCNEW (struct call_thread_fsm);
-  thread_fsm_ctor (&sm->thread_fsm, &call_thread_fsm_ops);
+  thread_fsm_ctor (&sm->thread_fsm, &call_thread_fsm_ops, cmd_interp);
 
   sm->return_meta_info.gdbarch = gdbarch;
   sm->return_meta_info.function = function;
@@ -512,7 +513,8 @@ new_call_thread_fsm (struct ui *waiting_ui,
 /* Implementation of should_stop method for infcalls.  */
 
 static int
-call_thread_fsm_should_stop (struct thread_fsm *self)
+call_thread_fsm_should_stop (struct thread_fsm *self,
+                            struct thread_info *thread)
 {
   struct call_thread_fsm *f = (struct call_thread_fsm *) self;
 
@@ -1135,7 +1137,7 @@ call_function_by_hand_dummy (struct value *function,
        not report the stop to the user, and captures the return value
        before the dummy frame is popped.  run_inferior_call registers
        it with the thread ASAP.  */
-    sm = new_call_thread_fsm (current_ui,
+    sm = new_call_thread_fsm (current_ui, command_interp (),
                              gdbarch, function,
                              values_type,
                              struct_return || hidden_first_param_p,
@@ -1167,7 +1169,7 @@ call_function_by_hand_dummy (struct value *function,
 
            /* Clean up / destroy the call FSM, and restore the
               original one.  */
-           thread_fsm_clean_up (tp->thread_fsm);
+           thread_fsm_clean_up (tp->thread_fsm, tp);
            thread_fsm_delete (tp->thread_fsm);
            tp->thread_fsm = saved_sm;
 
index e229d03d9ffd3a670e42c13ad96427d920e6bff3..e9dcb46f6e3c696b4b07e907933850c5c9961f7c 100644 (file)
@@ -57,6 +57,7 @@
 #include "infcall.h"
 #include "thread-fsm.h"
 #include "top.h"
+#include "interps.h"
 
 /* Local functions: */
 
@@ -925,13 +926,12 @@ struct step_command_fsm
 
   /* If true, this is a stepi/nexti, otherwise a step/step.  */
   int single_inst;
-
-  /* The thread that the command was run on.  */
-  int thread;
 };
 
-static void step_command_fsm_clean_up (struct thread_fsm *self);
-static int step_command_fsm_should_stop (struct thread_fsm *self);
+static void step_command_fsm_clean_up (struct thread_fsm *self,
+                                      struct thread_info *thread);
+static int step_command_fsm_should_stop (struct thread_fsm *self,
+                                        struct thread_info *thread);
 static enum async_reply_reason
   step_command_fsm_async_reply_reason (struct thread_fsm *self);
 
@@ -949,12 +949,12 @@ static struct thread_fsm_ops step_command_fsm_ops =
 /* Allocate a new step_command_fsm.  */
 
 static struct step_command_fsm *
-new_step_command_fsm (void)
+new_step_command_fsm (struct interp *cmd_interp)
 {
   struct step_command_fsm *sm;
 
   sm = XCNEW (struct step_command_fsm);
-  thread_fsm_ctor (&sm->thread_fsm, &step_command_fsm_ops);
+  thread_fsm_ctor (&sm->thread_fsm, &step_command_fsm_ops, cmd_interp);
 
   return sm;
 }
@@ -970,7 +970,6 @@ step_command_fsm_prepare (struct step_command_fsm *sm,
   sm->skip_subroutines = skip_subroutines;
   sm->single_inst = single_inst;
   sm->count = count;
-  sm->thread = thread->global_num;
 
   /* Leave the si command alone.  */
   if (!sm->single_inst || sm->skip_subroutines)
@@ -1010,7 +1009,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
   /* Setup the execution command state machine to handle all the COUNT
      steps.  */
   thr = inferior_thread ();
-  step_sm = new_step_command_fsm ();
+  step_sm = new_step_command_fsm (command_interp ());
   thr->thread_fsm = &step_sm->thread_fsm;
 
   step_command_fsm_prepare (step_sm, skip_subroutines,
@@ -1028,7 +1027,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
 
       /* Stepped into an inline frame.  Pretend that we've
         stopped.  */
-      thread_fsm_clean_up (thr->thread_fsm);
+      thread_fsm_clean_up (thr->thread_fsm, thr);
       proceeded = normal_stop ();
       if (!proceeded)
        inferior_event_handler (INF_EXEC_COMPLETE, NULL);
@@ -1043,10 +1042,9 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
    will need to keep going.  */
 
 static int
-step_command_fsm_should_stop (struct thread_fsm *self)
+step_command_fsm_should_stop (struct thread_fsm *self, struct thread_info *tp)
 {
   struct step_command_fsm *sm = (struct step_command_fsm *) self;
-  struct thread_info *tp = find_thread_global_id (sm->thread);
 
   if (tp->control.stop_step)
     {
@@ -1064,12 +1062,12 @@ step_command_fsm_should_stop (struct thread_fsm *self)
 /* Implementation of the 'clean_up' FSM method for stepping commands.  */
 
 static void
-step_command_fsm_clean_up (struct thread_fsm *self)
+step_command_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread)
 {
   struct step_command_fsm *sm = (struct step_command_fsm *) self;
 
   if (!sm->single_inst || sm->skip_subroutines)
-    delete_longjmp_breakpoint (sm->thread);
+    delete_longjmp_breakpoint (thread->global_num);
 }
 
 /* Implementation of the 'async_reply_reason' FSM method for stepping
@@ -1411,8 +1409,10 @@ struct until_next_fsm
   int thread;
 };
 
-static int until_next_fsm_should_stop (struct thread_fsm *self);
-static void until_next_fsm_clean_up (struct thread_fsm *self);
+static int until_next_fsm_should_stop (struct thread_fsm *self,
+                                      struct thread_info *thread);
+static void until_next_fsm_clean_up (struct thread_fsm *self,
+                                    struct thread_info *thread);
 static enum async_reply_reason
   until_next_fsm_async_reply_reason (struct thread_fsm *self);
 
@@ -1430,12 +1430,12 @@ static struct thread_fsm_ops until_next_fsm_ops =
 /* Allocate a new until_next_fsm.  */
 
 static struct until_next_fsm *
-new_until_next_fsm (int thread)
+new_until_next_fsm (struct interp *cmd_interp, int thread)
 {
   struct until_next_fsm *sm;
 
   sm = XCNEW (struct until_next_fsm);
-  thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops);
+  thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops, cmd_interp);
 
   sm->thread = thread;
 
@@ -1446,10 +1446,9 @@ new_until_next_fsm (int thread)
    no arg) command.  */
 
 static int
-until_next_fsm_should_stop (struct thread_fsm *self)
+until_next_fsm_should_stop (struct thread_fsm *self,
+                           struct thread_info *tp)
 {
-  struct thread_info *tp = inferior_thread ();
-
   if (tp->control.stop_step)
     thread_fsm_set_finished (self);
 
@@ -1460,11 +1459,11 @@ until_next_fsm_should_stop (struct thread_fsm *self)
    arg) command.  */
 
 static void
-until_next_fsm_clean_up (struct thread_fsm *self)
+until_next_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread)
 {
   struct until_next_fsm *sm = (struct until_next_fsm *) self;
 
-  delete_longjmp_breakpoint (sm->thread);
+  delete_longjmp_breakpoint (thread->global_num);
 }
 
 /* Implementation of the 'async_reply_reason' FSM method for the until
@@ -1534,7 +1533,7 @@ until_next_command (int from_tty)
   set_longjmp_breakpoint (tp, get_frame_id (frame));
   old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
 
-  sm = new_until_next_fsm (tp->global_num);
+  sm = new_until_next_fsm (command_interp (), tp->global_num);
   tp->thread_fsm = &sm->thread_fsm;
   discard_cleanups (old_chain);
 
@@ -1729,9 +1728,6 @@ struct finish_command_fsm
   /* The base class.  */
   struct thread_fsm thread_fsm;
 
-  /* The thread that was current when the command was executed.  */
-  int thread;
-
   /* The momentary breakpoint set at the function's return address in
      the caller.  */
   struct breakpoint *breakpoint;
@@ -1744,8 +1740,10 @@ struct finish_command_fsm
   struct return_value_info return_value;
 };
 
-static int finish_command_fsm_should_stop (struct thread_fsm *self);
-static void finish_command_fsm_clean_up (struct thread_fsm *self);
+static int finish_command_fsm_should_stop (struct thread_fsm *self,
+                                          struct thread_info *thread);
+static void finish_command_fsm_clean_up (struct thread_fsm *self,
+                                        struct thread_info *thread);
 static struct return_value_info *
   finish_command_fsm_return_value (struct thread_fsm *self);
 static enum async_reply_reason
@@ -1760,19 +1758,18 @@ static struct thread_fsm_ops finish_command_fsm_ops =
   finish_command_fsm_should_stop,
   finish_command_fsm_return_value,
   finish_command_fsm_async_reply_reason,
+  NULL, /* should_notify_stop */
 };
 
 /* Allocate a new finish_command_fsm.  */
 
 static struct finish_command_fsm *
-new_finish_command_fsm (int thread)
+new_finish_command_fsm (struct interp *cmd_interp)
 {
   struct finish_command_fsm *sm;
 
   sm = XCNEW (struct finish_command_fsm);
-  thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops);
-
-  sm->thread = thread;
+  thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops, cmd_interp);
 
   return sm;
 }
@@ -1783,11 +1780,11 @@ new_finish_command_fsm (int thread)
    marks the FSM finished.  */
 
 static int
-finish_command_fsm_should_stop (struct thread_fsm *self)
+finish_command_fsm_should_stop (struct thread_fsm *self,
+                               struct thread_info *tp)
 {
   struct finish_command_fsm *f = (struct finish_command_fsm *) self;
   struct return_value_info *rv = &f->return_value;
-  struct thread_info *tp = find_thread_global_id (f->thread);
 
   if (f->function != NULL
       && bpstat_find_breakpoint (tp->control.stop_bpstat,
@@ -1825,7 +1822,8 @@ finish_command_fsm_should_stop (struct thread_fsm *self)
    commands.  */
 
 static void
-finish_command_fsm_clean_up (struct thread_fsm *self)
+finish_command_fsm_clean_up (struct thread_fsm *self,
+                            struct thread_info *thread)
 {
   struct finish_command_fsm *f = (struct finish_command_fsm *) self;
 
@@ -1834,7 +1832,7 @@ finish_command_fsm_clean_up (struct thread_fsm *self)
       delete_breakpoint (f->breakpoint);
       f->breakpoint = NULL;
     }
-  delete_longjmp_breakpoint (f->thread);
+  delete_longjmp_breakpoint (thread->global_num);
 }
 
 /* Implementation of the 'return_value' FSM method for the finish
@@ -2002,7 +2000,7 @@ finish_command (char *arg, int from_tty)
 
   tp = inferior_thread ();
 
-  sm = new_finish_command_fsm (tp->global_num);
+  sm = new_finish_command_fsm (command_interp ());
 
   tp->thread_fsm = &sm->thread_fsm;
 
index 06ec00fce3af5d12c1950635598f4b7236528090..70a0790b9ac6c52340d41da5da55e06ac9124366 100644 (file)
@@ -681,7 +681,7 @@ follow_fork (void)
   CORE_ADDR step_range_start = 0;
   CORE_ADDR step_range_end = 0;
   struct frame_id step_frame_id = { 0 };
-  struct interp *command_interp = NULL;
+  struct thread_fsm *thread_fsm = NULL;
 
   if (!non_stop)
     {
@@ -733,7 +733,7 @@ follow_fork (void)
            step_frame_id = tp->control.step_frame_id;
            exception_resume_breakpoint
              = clone_momentary_breakpoint (tp->control.exception_resume_breakpoint);
-           command_interp = tp->control.command_interp;
+           thread_fsm = tp->thread_fsm;
 
            /* For now, delete the parent's sr breakpoint, otherwise,
               parent/child sr breakpoints are considered duplicates,
@@ -745,7 +745,7 @@ follow_fork (void)
            tp->control.step_range_end = 0;
            tp->control.step_frame_id = null_frame_id;
            delete_exception_resume_breakpoint (tp);
-           tp->control.command_interp = NULL;
+           tp->thread_fsm = NULL;
          }
 
        parent = inferior_ptid;
@@ -791,7 +791,7 @@ follow_fork (void)
                    tp->control.step_frame_id = step_frame_id;
                    tp->control.exception_resume_breakpoint
                      = exception_resume_breakpoint;
-                   tp->control.command_interp = command_interp;
+                   tp->thread_fsm = thread_fsm;
                  }
                else
                  {
@@ -2849,7 +2849,6 @@ clear_proceed_status_thread (struct thread_info *tp)
 
   tp->control.proceed_to_finish = 0;
 
-  tp->control.command_interp = NULL;
   tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
@@ -3042,14 +3041,6 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   if (siggnal != GDB_SIGNAL_DEFAULT)
     tp->suspend.stop_signal = siggnal;
 
-  /* Record the interpreter that issued the execution command that
-     caused this thread to resume.  If the top level interpreter is
-     MI/async, and the execution command was a CLI command
-     (next/step/etc.), we'll want to print stop event output to the MI
-     console channel (the stepped-to line, etc.), as if the user
-     entered the execution command on a real GDB console.  */
-  tp->control.command_interp = command_interp ();
-
   resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
 
   /* If an exception is thrown from this point on, make sure to
@@ -3823,7 +3814,7 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
   struct thread_info *thr = ecs->event_thread;
 
   if (thr != NULL && thr->thread_fsm != NULL)
-    thread_fsm_clean_up (thr->thread_fsm);
+    thread_fsm_clean_up (thr->thread_fsm, thr);
 
   if (!non_stop)
     {
@@ -3835,7 +3826,7 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
            continue;
 
          switch_to_thread (thr->ptid);
-         thread_fsm_clean_up (thr->thread_fsm);
+         thread_fsm_clean_up (thr->thread_fsm, thr);
        }
 
       if (ecs->event_thread != NULL)
@@ -3993,7 +3984,7 @@ fetch_inferior_event (void *client_data)
          struct thread_fsm *thread_fsm = thr->thread_fsm;
 
          if (thread_fsm != NULL)
-           should_stop = thread_fsm_should_stop (thread_fsm);
+           should_stop = thread_fsm_should_stop (thread_fsm, thr);
        }
 
       if (!should_stop)
index 3bd499a522bd5bc6a858c79ea76c2efff6afa74f..9ad93ebe916ff5c2269c9c361f902c64b17fbfe9 100644 (file)
@@ -1,3 +1,8 @@
+2016-06-21  Pedro Alves  <palves@redhat.com>
+
+       * gdb.opt/inline-cmds.c: Add "set mi break here" marker.
+       * gdb.opt/inline-cmds.exp: Add MI tests.
+
 2016-06-21  Pedro Alves  <palves@redhat.com>
 
        * gdb.gdb/selftest.exp (do_steps_and_nexts): Add new regexp.
index 20e1d0b7d0dd3114250f813790abec37b0a83ca4..59631d7caaee055ff9610aaae794a9355dd79959 100644 (file)
@@ -61,7 +61,7 @@ int main (void)
   int val;
 
   x = 7;
-  y = 8;
+  y = 8; /* set mi break here */
 
   result = func1 ();
   result = func2 ();
index d57a333f3b565b136e38c37d816227208b0b0a41..684f4dd0ea4a856df2b88046c4571945cab72921 100644 (file)
@@ -13,6 +13,9 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
 standard_testfile .c inline-markers.c
 
 if {[prepare_for_testing $testfile.exp $testfile \
@@ -315,3 +318,62 @@ gdb_test "up" "#3  .*outer_inline2.*" "up to outer_inline2"
 gdb_test "info frame" ".*inlined into frame.*" "outer_inline2 inlined"
 gdb_test "up" "#4  main.*" "up from outer_inline2"
 gdb_test "info frame" ".*\n caller of frame.*" "main not inlined"
+
+gdb_exit
+
+# Send a CLI "step" command over MI.  CLI_OUTPUT_RE is a regexp that
+# matches the expected CLI output.  MESSAGE is used as test message.
+
+proc mi_cli_step {cli_output_re message} {
+    global mi_gdb_prompt
+    global srcfile
+    global decimal
+
+    send_gdb "interpreter-exec console \"step\"\n"
+    gdb_expect {
+       -re "\\^running\r\n\\*running,thread-id=\"all\"\r\n${mi_gdb_prompt}${cli_output_re}" {
+           pass $message
+       }
+       timeout {
+           fail "$message (timeout)"
+       }
+       eof {
+           fail "$message (eof)"
+       }
+    }
+
+    # mi_expect_stop handles "set mi-async on/off" differences.
+    mi_expect_stop "end-stepping-range" "\[^\r\n\]*" "" ".*$srcfile" "$decimal" \
+       "" "got *stopped for $message"
+}
+
+# Test that stepping into an inlined function with the CLI "step"
+# command run while the top interpreter is MI results in the expected
+# CLI output sent to MI's console.
+with_test_prefix "mi" {
+    if [mi_gdb_start] {
+       continue
+    }
+    mi_gdb_load ${binfile}
+    mi_runto main
+
+    set line_number [gdb_get_line_number "set mi break here"]
+    mi_gdb_test "-break-insert ${srcfile}:${line_number}" \
+       {\^done,bkpt=.number="2",type="breakpoint".*\}} \
+       "set breakpoint"
+
+    mi_execute_to "exec-continue" "breakpoint-hit" "main" "" ".*" ".*" \
+       { "" "disp=\"keep\"" } "breakpoint hit"
+
+    incr line_number 2
+
+    # Step to the line that does an inline call.
+    set re "~\"$line_number\\\\t  result = func1 \\(\\);\\\\n\"\r\n"
+    mi_cli_step "${re}" "step to inline call"
+
+    # Step into the inlined function.
+    set re [multi_line \
+               "~\"func1 \\(\\) at .*$srcfile:$decimal\\\\n\"" \
+               "~\"$decimal\\\\t  bar \\(\\);\\\\n\"\r\n"]
+    mi_cli_step "${re}" "step into inline call"
+}
index 52b4eb8ba3a68338209d92e75d8acacd1064277e..5ba4d56574cc2db00391e871ec5b3ccc1fd6839a 100644 (file)
 /* See thread-fsm.h.  */
 
 void
-thread_fsm_ctor (struct thread_fsm *self, struct thread_fsm_ops *ops)
+thread_fsm_ctor (struct thread_fsm *self, struct thread_fsm_ops *ops,
+                struct interp *cmd_interp)
 {
+  self->command_interp = cmd_interp;
   self->finished = 0;
   self->ops = ops;
 }
@@ -44,18 +46,18 @@ thread_fsm_delete (struct thread_fsm *self)
 /* See thread-fsm.h.  */
 
 void
-thread_fsm_clean_up (struct thread_fsm *self)
+thread_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread)
 {
   if (self->ops->clean_up != NULL)
-    self->ops->clean_up (self);
+    self->ops->clean_up (self, thread);
 }
 
 /* See thread-fsm.h.  */
 
 int
-thread_fsm_should_stop (struct thread_fsm *self)
+thread_fsm_should_stop (struct thread_fsm *self, struct thread_info *thread)
 {
-  return self->ops->should_stop (self);
+  return self->ops->should_stop (self, thread);
 }
 
 /* See thread-fsm.h.  */
index b0f4c44c9a3fd97f8ed5385ac80c3f86626c50c1..86fb81fd3d37f4b3fd0c7208c34415b20447b66b 100644 (file)
@@ -35,6 +35,14 @@ struct thread_fsm
 
   /* Whether the FSM is done successfully.  */
   int finished;
+
+  /* The interpreter that issued the execution command that caused
+     this thread to resume.  If the top level interpreter is MI/async,
+     and the execution command was a CLI command (next/step/etc.),
+     we'll want to print stop event output to the MI console channel
+     (the stepped-to line, etc.), as if the user entered the execution
+     command on a real GDB console.  */
+  struct interp *command_interp;
 };
 
 /* The virtual table of a thread_fsm.  */
@@ -49,7 +57,7 @@ struct thread_fsm_ops
   /* Called to clean up target resources after the FSM.  E.g., if the
      FSM created internal breakpoints, this is where they should be
      deleted.  */
-  void (*clean_up) (struct thread_fsm *self);
+  void (*clean_up) (struct thread_fsm *self, struct thread_info *thread);
 
   /* Called after handle_inferior_event decides the target is done
      (that is, after stop_waiting).  The FSM is given a chance to
@@ -58,7 +66,7 @@ struct thread_fsm_ops
      should be re-resumed.  This is a good place to cache target data
      too.  For example, the "finish" command saves the just-finished
      function's return value here.  */
-  int (*should_stop) (struct thread_fsm *self);
+  int (*should_stop) (struct thread_fsm *self, struct thread_info *thread);
 
   /* If this FSM saved a function's return value, you can use this
      method to retrieve it.  Otherwise, this returns NULL.  */
@@ -72,17 +80,20 @@ struct thread_fsm_ops
   int (*should_notify_stop) (struct thread_fsm *self);
 };
 /* Initialize FSM.  */
-extern void thread_fsm_ctor (struct thread_fsm *fsm,
-                            struct thread_fsm_ops *ops);
+extern void thread_fsm_ctor (struct thread_fsm *self,
+                            struct thread_fsm_ops *ops,
+                            struct interp *cmd_interp);
 
 /* Calls the FSM's dtor method, and then frees FSM.  */
 extern void thread_fsm_delete (struct thread_fsm *fsm);
 
 /* Calls the FSM's clean_up method.  */
-extern void thread_fsm_clean_up (struct thread_fsm *fsm);
+extern void thread_fsm_clean_up (struct thread_fsm *fsm,
+                                struct thread_info *thread);
 
 /* Calls the FSM's should_stop method.  */
-extern int thread_fsm_should_stop (struct thread_fsm *fsm);
+extern int thread_fsm_should_stop (struct thread_fsm *fsm,
+                                  struct thread_info *thread);
 
 /* Calls the FSM's return_value method.  */
 extern struct return_value_info *
index 5c7d96c4a5a1ea12a93dab12fc6dd0ed23a20398..ab98777b44d7f204df90d36bfd10ea0fdc17befe 100644 (file)
@@ -166,7 +166,7 @@ thread_cancel_execution_command (struct thread_info *thr)
 {
   if (thr->thread_fsm != NULL)
     {
-      thread_fsm_clean_up (thr->thread_fsm);
+      thread_fsm_clean_up (thr->thread_fsm, thr);
       thread_fsm_delete (thr->thread_fsm);
       thr->thread_fsm = NULL;
     }