mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-17 16:05:56 +08:00
Push thread->control.command_interp to the struct thread_fsm
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.
This commit is contained in:
@ -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>
|
2016-06-21 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* cli/cli-interp.c: Include gdbthread.h and thread-fsm.h.
|
* cli/cli-interp.c: Include gdbthread.h and thread-fsm.h.
|
||||||
|
@ -11605,8 +11605,10 @@ struct until_break_fsm
|
|||||||
struct breakpoint *caller_breakpoint;
|
struct breakpoint *caller_breakpoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void until_break_fsm_clean_up (struct thread_fsm *self);
|
static void until_break_fsm_clean_up (struct thread_fsm *self,
|
||||||
static int until_break_fsm_should_stop (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
|
static enum async_reply_reason
|
||||||
until_break_fsm_async_reply_reason (struct thread_fsm *self);
|
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. */
|
/* Allocate a new until_break_command_fsm. */
|
||||||
|
|
||||||
static struct until_break_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 *location_breakpoint,
|
||||||
struct breakpoint *caller_breakpoint)
|
struct breakpoint *caller_breakpoint)
|
||||||
{
|
{
|
||||||
struct until_break_fsm *sm;
|
struct until_break_fsm *sm;
|
||||||
|
|
||||||
sm = XCNEW (struct until_break_fsm);
|
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->thread = thread;
|
||||||
sm->location_breakpoint = location_breakpoint;
|
sm->location_breakpoint = location_breakpoint;
|
||||||
@ -11644,10 +11646,10 @@ new_until_break_fsm (int thread,
|
|||||||
until(location)/advance commands. */
|
until(location)/advance commands. */
|
||||||
|
|
||||||
static int
|
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 until_break_fsm *sm = (struct until_break_fsm *) self;
|
||||||
struct thread_info *tp = inferior_thread ();
|
|
||||||
|
|
||||||
if (bpstat_find_breakpoint (tp->control.stop_bpstat,
|
if (bpstat_find_breakpoint (tp->control.stop_bpstat,
|
||||||
sm->location_breakpoint) != NULL
|
sm->location_breakpoint) != NULL
|
||||||
@ -11663,7 +11665,8 @@ until_break_fsm_should_stop (struct thread_fsm *self)
|
|||||||
until(location)/advance commands. */
|
until(location)/advance commands. */
|
||||||
|
|
||||||
static void
|
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;
|
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);
|
stack_frame_id, bp_until);
|
||||||
make_cleanup_delete_breakpoint (location_breakpoint);
|
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);
|
location_breakpoint, caller_breakpoint);
|
||||||
tp->thread_fsm = &sm->thread_fsm;
|
tp->thread_fsm = &sm->thread_fsm;
|
||||||
|
|
||||||
|
@ -77,10 +77,9 @@ should_print_stop_to_console (struct interp *console_interp,
|
|||||||
{
|
{
|
||||||
if ((bpstat_what (tp->control.stop_bpstat).main_action
|
if ((bpstat_what (tp->control.stop_bpstat).main_action
|
||||||
== BPSTAT_WHAT_STOP_NOISY)
|
== BPSTAT_WHAT_STOP_NOISY)
|
||||||
|| !(tp->thread_fsm != NULL
|
|| tp->thread_fsm == NULL
|
||||||
&& thread_fsm_finished_p (tp->thread_fsm))
|
|| tp->thread_fsm->command_interp == console_interp
|
||||||
|| (tp->control.command_interp != NULL
|
|| !thread_fsm_finished_p (tp->thread_fsm))
|
||||||
&& tp->control.command_interp == console_interp))
|
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -136,11 +136,6 @@ struct thread_control_state
|
|||||||
at. */
|
at. */
|
||||||
bpstat stop_bpstat;
|
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
|
/* Whether the command that started the thread was a stepping
|
||||||
command. This is used to decide whether "set scheduler-locking
|
command. This is used to decide whether "set scheduler-locking
|
||||||
step" behaves like "on" or "off". */
|
step" behaves like "on" or "off". */
|
||||||
|
@ -470,7 +470,8 @@ struct call_thread_fsm
|
|||||||
struct ui *waiting_ui;
|
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);
|
static int call_thread_fsm_should_notify_stop (struct thread_fsm *self);
|
||||||
|
|
||||||
/* call_thread_fsm's vtable. */
|
/* 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. */
|
/* Allocate a new call_thread_fsm object. */
|
||||||
|
|
||||||
static struct call_thread_fsm *
|
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 gdbarch *gdbarch, struct value *function,
|
||||||
struct type *value_type,
|
struct type *value_type,
|
||||||
int struct_return_p, CORE_ADDR struct_addr)
|
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;
|
struct call_thread_fsm *sm;
|
||||||
|
|
||||||
sm = XCNEW (struct call_thread_fsm);
|
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.gdbarch = gdbarch;
|
||||||
sm->return_meta_info.function = function;
|
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. */
|
/* Implementation of should_stop method for infcalls. */
|
||||||
|
|
||||||
static int
|
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;
|
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
|
not report the stop to the user, and captures the return value
|
||||||
before the dummy frame is popped. run_inferior_call registers
|
before the dummy frame is popped. run_inferior_call registers
|
||||||
it with the thread ASAP. */
|
it with the thread ASAP. */
|
||||||
sm = new_call_thread_fsm (current_ui,
|
sm = new_call_thread_fsm (current_ui, command_interp (),
|
||||||
gdbarch, function,
|
gdbarch, function,
|
||||||
values_type,
|
values_type,
|
||||||
struct_return || hidden_first_param_p,
|
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
|
/* Clean up / destroy the call FSM, and restore the
|
||||||
original one. */
|
original one. */
|
||||||
thread_fsm_clean_up (tp->thread_fsm);
|
thread_fsm_clean_up (tp->thread_fsm, tp);
|
||||||
thread_fsm_delete (tp->thread_fsm);
|
thread_fsm_delete (tp->thread_fsm);
|
||||||
tp->thread_fsm = saved_sm;
|
tp->thread_fsm = saved_sm;
|
||||||
|
|
||||||
|
74
gdb/infcmd.c
74
gdb/infcmd.c
@ -57,6 +57,7 @@
|
|||||||
#include "infcall.h"
|
#include "infcall.h"
|
||||||
#include "thread-fsm.h"
|
#include "thread-fsm.h"
|
||||||
#include "top.h"
|
#include "top.h"
|
||||||
|
#include "interps.h"
|
||||||
|
|
||||||
/* Local functions: */
|
/* Local functions: */
|
||||||
|
|
||||||
@ -925,13 +926,12 @@ struct step_command_fsm
|
|||||||
|
|
||||||
/* If true, this is a stepi/nexti, otherwise a step/step. */
|
/* If true, this is a stepi/nexti, otherwise a step/step. */
|
||||||
int single_inst;
|
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 void step_command_fsm_clean_up (struct thread_fsm *self,
|
||||||
static int step_command_fsm_should_stop (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
|
static enum async_reply_reason
|
||||||
step_command_fsm_async_reply_reason (struct thread_fsm *self);
|
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. */
|
/* Allocate a new step_command_fsm. */
|
||||||
|
|
||||||
static struct 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;
|
struct step_command_fsm *sm;
|
||||||
|
|
||||||
sm = XCNEW (struct step_command_fsm);
|
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;
|
return sm;
|
||||||
}
|
}
|
||||||
@ -970,7 +970,6 @@ step_command_fsm_prepare (struct step_command_fsm *sm,
|
|||||||
sm->skip_subroutines = skip_subroutines;
|
sm->skip_subroutines = skip_subroutines;
|
||||||
sm->single_inst = single_inst;
|
sm->single_inst = single_inst;
|
||||||
sm->count = count;
|
sm->count = count;
|
||||||
sm->thread = thread->global_num;
|
|
||||||
|
|
||||||
/* Leave the si command alone. */
|
/* Leave the si command alone. */
|
||||||
if (!sm->single_inst || sm->skip_subroutines)
|
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
|
/* Setup the execution command state machine to handle all the COUNT
|
||||||
steps. */
|
steps. */
|
||||||
thr = inferior_thread ();
|
thr = inferior_thread ();
|
||||||
step_sm = new_step_command_fsm ();
|
step_sm = new_step_command_fsm (command_interp ());
|
||||||
thr->thread_fsm = &step_sm->thread_fsm;
|
thr->thread_fsm = &step_sm->thread_fsm;
|
||||||
|
|
||||||
step_command_fsm_prepare (step_sm, skip_subroutines,
|
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
|
/* Stepped into an inline frame. Pretend that we've
|
||||||
stopped. */
|
stopped. */
|
||||||
thread_fsm_clean_up (thr->thread_fsm);
|
thread_fsm_clean_up (thr->thread_fsm, thr);
|
||||||
proceeded = normal_stop ();
|
proceeded = normal_stop ();
|
||||||
if (!proceeded)
|
if (!proceeded)
|
||||||
inferior_event_handler (INF_EXEC_COMPLETE, NULL);
|
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. */
|
will need to keep going. */
|
||||||
|
|
||||||
static int
|
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 step_command_fsm *sm = (struct step_command_fsm *) self;
|
||||||
struct thread_info *tp = find_thread_global_id (sm->thread);
|
|
||||||
|
|
||||||
if (tp->control.stop_step)
|
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. */
|
/* Implementation of the 'clean_up' FSM method for stepping commands. */
|
||||||
|
|
||||||
static void
|
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;
|
struct step_command_fsm *sm = (struct step_command_fsm *) self;
|
||||||
|
|
||||||
if (!sm->single_inst || sm->skip_subroutines)
|
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
|
/* Implementation of the 'async_reply_reason' FSM method for stepping
|
||||||
@ -1411,8 +1409,10 @@ struct until_next_fsm
|
|||||||
int thread;
|
int thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int until_next_fsm_should_stop (struct thread_fsm *self);
|
static int until_next_fsm_should_stop (struct thread_fsm *self,
|
||||||
static void until_next_fsm_clean_up (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
|
static enum async_reply_reason
|
||||||
until_next_fsm_async_reply_reason (struct thread_fsm *self);
|
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. */
|
/* Allocate a new until_next_fsm. */
|
||||||
|
|
||||||
static struct 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;
|
struct until_next_fsm *sm;
|
||||||
|
|
||||||
sm = XCNEW (struct until_next_fsm);
|
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;
|
sm->thread = thread;
|
||||||
|
|
||||||
@ -1446,10 +1446,9 @@ new_until_next_fsm (int thread)
|
|||||||
no arg) command. */
|
no arg) command. */
|
||||||
|
|
||||||
static int
|
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)
|
if (tp->control.stop_step)
|
||||||
thread_fsm_set_finished (self);
|
thread_fsm_set_finished (self);
|
||||||
|
|
||||||
@ -1460,11 +1459,11 @@ until_next_fsm_should_stop (struct thread_fsm *self)
|
|||||||
arg) command. */
|
arg) command. */
|
||||||
|
|
||||||
static void
|
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;
|
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
|
/* 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));
|
set_longjmp_breakpoint (tp, get_frame_id (frame));
|
||||||
old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
|
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;
|
tp->thread_fsm = &sm->thread_fsm;
|
||||||
discard_cleanups (old_chain);
|
discard_cleanups (old_chain);
|
||||||
|
|
||||||
@ -1729,9 +1728,6 @@ struct finish_command_fsm
|
|||||||
/* The base class. */
|
/* The base class. */
|
||||||
struct thread_fsm thread_fsm;
|
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 momentary breakpoint set at the function's return address in
|
||||||
the caller. */
|
the caller. */
|
||||||
struct breakpoint *breakpoint;
|
struct breakpoint *breakpoint;
|
||||||
@ -1744,8 +1740,10 @@ struct finish_command_fsm
|
|||||||
struct return_value_info return_value;
|
struct return_value_info return_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int finish_command_fsm_should_stop (struct thread_fsm *self);
|
static int finish_command_fsm_should_stop (struct thread_fsm *self,
|
||||||
static void finish_command_fsm_clean_up (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 *
|
static struct return_value_info *
|
||||||
finish_command_fsm_return_value (struct thread_fsm *self);
|
finish_command_fsm_return_value (struct thread_fsm *self);
|
||||||
static enum async_reply_reason
|
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_should_stop,
|
||||||
finish_command_fsm_return_value,
|
finish_command_fsm_return_value,
|
||||||
finish_command_fsm_async_reply_reason,
|
finish_command_fsm_async_reply_reason,
|
||||||
|
NULL, /* should_notify_stop */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Allocate a new finish_command_fsm. */
|
/* Allocate a new finish_command_fsm. */
|
||||||
|
|
||||||
static struct 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;
|
struct finish_command_fsm *sm;
|
||||||
|
|
||||||
sm = XCNEW (struct finish_command_fsm);
|
sm = XCNEW (struct finish_command_fsm);
|
||||||
thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops);
|
thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops, cmd_interp);
|
||||||
|
|
||||||
sm->thread = thread;
|
|
||||||
|
|
||||||
return sm;
|
return sm;
|
||||||
}
|
}
|
||||||
@ -1783,11 +1780,11 @@ new_finish_command_fsm (int thread)
|
|||||||
marks the FSM finished. */
|
marks the FSM finished. */
|
||||||
|
|
||||||
static int
|
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 finish_command_fsm *f = (struct finish_command_fsm *) self;
|
||||||
struct return_value_info *rv = &f->return_value;
|
struct return_value_info *rv = &f->return_value;
|
||||||
struct thread_info *tp = find_thread_global_id (f->thread);
|
|
||||||
|
|
||||||
if (f->function != NULL
|
if (f->function != NULL
|
||||||
&& bpstat_find_breakpoint (tp->control.stop_bpstat,
|
&& bpstat_find_breakpoint (tp->control.stop_bpstat,
|
||||||
@ -1825,7 +1822,8 @@ finish_command_fsm_should_stop (struct thread_fsm *self)
|
|||||||
commands. */
|
commands. */
|
||||||
|
|
||||||
static void
|
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;
|
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);
|
delete_breakpoint (f->breakpoint);
|
||||||
f->breakpoint = NULL;
|
f->breakpoint = NULL;
|
||||||
}
|
}
|
||||||
delete_longjmp_breakpoint (f->thread);
|
delete_longjmp_breakpoint (thread->global_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implementation of the 'return_value' FSM method for the finish
|
/* Implementation of the 'return_value' FSM method for the finish
|
||||||
@ -2002,7 +2000,7 @@ finish_command (char *arg, int from_tty)
|
|||||||
|
|
||||||
tp = inferior_thread ();
|
tp = inferior_thread ();
|
||||||
|
|
||||||
sm = new_finish_command_fsm (tp->global_num);
|
sm = new_finish_command_fsm (command_interp ());
|
||||||
|
|
||||||
tp->thread_fsm = &sm->thread_fsm;
|
tp->thread_fsm = &sm->thread_fsm;
|
||||||
|
|
||||||
|
23
gdb/infrun.c
23
gdb/infrun.c
@ -681,7 +681,7 @@ follow_fork (void)
|
|||||||
CORE_ADDR step_range_start = 0;
|
CORE_ADDR step_range_start = 0;
|
||||||
CORE_ADDR step_range_end = 0;
|
CORE_ADDR step_range_end = 0;
|
||||||
struct frame_id step_frame_id = { 0 };
|
struct frame_id step_frame_id = { 0 };
|
||||||
struct interp *command_interp = NULL;
|
struct thread_fsm *thread_fsm = NULL;
|
||||||
|
|
||||||
if (!non_stop)
|
if (!non_stop)
|
||||||
{
|
{
|
||||||
@ -733,7 +733,7 @@ follow_fork (void)
|
|||||||
step_frame_id = tp->control.step_frame_id;
|
step_frame_id = tp->control.step_frame_id;
|
||||||
exception_resume_breakpoint
|
exception_resume_breakpoint
|
||||||
= clone_momentary_breakpoint (tp->control.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,
|
/* For now, delete the parent's sr breakpoint, otherwise,
|
||||||
parent/child sr breakpoints are considered duplicates,
|
parent/child sr breakpoints are considered duplicates,
|
||||||
@ -745,7 +745,7 @@ follow_fork (void)
|
|||||||
tp->control.step_range_end = 0;
|
tp->control.step_range_end = 0;
|
||||||
tp->control.step_frame_id = null_frame_id;
|
tp->control.step_frame_id = null_frame_id;
|
||||||
delete_exception_resume_breakpoint (tp);
|
delete_exception_resume_breakpoint (tp);
|
||||||
tp->control.command_interp = NULL;
|
tp->thread_fsm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = inferior_ptid;
|
parent = inferior_ptid;
|
||||||
@ -791,7 +791,7 @@ follow_fork (void)
|
|||||||
tp->control.step_frame_id = step_frame_id;
|
tp->control.step_frame_id = step_frame_id;
|
||||||
tp->control.exception_resume_breakpoint
|
tp->control.exception_resume_breakpoint
|
||||||
= exception_resume_breakpoint;
|
= exception_resume_breakpoint;
|
||||||
tp->control.command_interp = command_interp;
|
tp->thread_fsm = thread_fsm;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2849,7 +2849,6 @@ clear_proceed_status_thread (struct thread_info *tp)
|
|||||||
|
|
||||||
tp->control.proceed_to_finish = 0;
|
tp->control.proceed_to_finish = 0;
|
||||||
|
|
||||||
tp->control.command_interp = NULL;
|
|
||||||
tp->control.stepping_command = 0;
|
tp->control.stepping_command = 0;
|
||||||
|
|
||||||
/* Discard any remaining commands or status from previous stop. */
|
/* 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)
|
if (siggnal != GDB_SIGNAL_DEFAULT)
|
||||||
tp->suspend.stop_signal = siggnal;
|
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);
|
resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
|
||||||
|
|
||||||
/* If an exception is thrown from this point on, make sure to
|
/* 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;
|
struct thread_info *thr = ecs->event_thread;
|
||||||
|
|
||||||
if (thr != NULL && thr->thread_fsm != NULL)
|
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)
|
if (!non_stop)
|
||||||
{
|
{
|
||||||
@ -3835,7 +3826,7 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch_to_thread (thr->ptid);
|
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)
|
if (ecs->event_thread != NULL)
|
||||||
@ -3993,7 +3984,7 @@ fetch_inferior_event (void *client_data)
|
|||||||
struct thread_fsm *thread_fsm = thr->thread_fsm;
|
struct thread_fsm *thread_fsm = thr->thread_fsm;
|
||||||
|
|
||||||
if (thread_fsm != NULL)
|
if (thread_fsm != NULL)
|
||||||
should_stop = thread_fsm_should_stop (thread_fsm);
|
should_stop = thread_fsm_should_stop (thread_fsm, thr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!should_stop)
|
if (!should_stop)
|
||||||
|
@ -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>
|
2016-06-21 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* gdb.gdb/selftest.exp (do_steps_and_nexts): Add new regexp.
|
* gdb.gdb/selftest.exp (do_steps_and_nexts): Add new regexp.
|
||||||
|
@ -61,7 +61,7 @@ int main (void)
|
|||||||
int val;
|
int val;
|
||||||
|
|
||||||
x = 7;
|
x = 7;
|
||||||
y = 8;
|
y = 8; /* set mi break here */
|
||||||
|
|
||||||
result = func1 ();
|
result = func1 ();
|
||||||
result = func2 ();
|
result = func2 ();
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# 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
|
standard_testfile .c inline-markers.c
|
||||||
|
|
||||||
if {[prepare_for_testing $testfile.exp $testfile \
|
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 "info frame" ".*inlined into frame.*" "outer_inline2 inlined"
|
||||||
gdb_test "up" "#4 main.*" "up from outer_inline2"
|
gdb_test "up" "#4 main.*" "up from outer_inline2"
|
||||||
gdb_test "info frame" ".*\n caller of frame.*" "main not inlined"
|
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"
|
||||||
|
}
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
/* See thread-fsm.h. */
|
/* See thread-fsm.h. */
|
||||||
|
|
||||||
void
|
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->finished = 0;
|
||||||
self->ops = ops;
|
self->ops = ops;
|
||||||
}
|
}
|
||||||
@ -44,18 +46,18 @@ thread_fsm_delete (struct thread_fsm *self)
|
|||||||
/* See thread-fsm.h. */
|
/* See thread-fsm.h. */
|
||||||
|
|
||||||
void
|
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)
|
if (self->ops->clean_up != NULL)
|
||||||
self->ops->clean_up (self);
|
self->ops->clean_up (self, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See thread-fsm.h. */
|
/* See thread-fsm.h. */
|
||||||
|
|
||||||
int
|
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. */
|
/* See thread-fsm.h. */
|
||||||
|
@ -35,6 +35,14 @@ struct thread_fsm
|
|||||||
|
|
||||||
/* Whether the FSM is done successfully. */
|
/* Whether the FSM is done successfully. */
|
||||||
int finished;
|
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. */
|
/* 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
|
/* Called to clean up target resources after the FSM. E.g., if the
|
||||||
FSM created internal breakpoints, this is where they should be
|
FSM created internal breakpoints, this is where they should be
|
||||||
deleted. */
|
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
|
/* Called after handle_inferior_event decides the target is done
|
||||||
(that is, after stop_waiting). The FSM is given a chance to
|
(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
|
should be re-resumed. This is a good place to cache target data
|
||||||
too. For example, the "finish" command saves the just-finished
|
too. For example, the "finish" command saves the just-finished
|
||||||
function's return value here. */
|
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
|
/* If this FSM saved a function's return value, you can use this
|
||||||
method to retrieve it. Otherwise, this returns NULL. */
|
method to retrieve it. Otherwise, this returns NULL. */
|
||||||
@ -72,17 +80,20 @@ struct thread_fsm_ops
|
|||||||
int (*should_notify_stop) (struct thread_fsm *self);
|
int (*should_notify_stop) (struct thread_fsm *self);
|
||||||
};
|
};
|
||||||
/* Initialize FSM. */
|
/* Initialize FSM. */
|
||||||
extern void thread_fsm_ctor (struct thread_fsm *fsm,
|
extern void thread_fsm_ctor (struct thread_fsm *self,
|
||||||
struct thread_fsm_ops *ops);
|
struct thread_fsm_ops *ops,
|
||||||
|
struct interp *cmd_interp);
|
||||||
|
|
||||||
/* Calls the FSM's dtor method, and then frees FSM. */
|
/* Calls the FSM's dtor method, and then frees FSM. */
|
||||||
extern void thread_fsm_delete (struct thread_fsm *fsm);
|
extern void thread_fsm_delete (struct thread_fsm *fsm);
|
||||||
|
|
||||||
/* Calls the FSM's clean_up method. */
|
/* 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. */
|
/* 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. */
|
/* Calls the FSM's return_value method. */
|
||||||
extern struct return_value_info *
|
extern struct return_value_info *
|
||||||
|
@ -166,7 +166,7 @@ thread_cancel_execution_command (struct thread_info *thr)
|
|||||||
{
|
{
|
||||||
if (thr->thread_fsm != NULL)
|
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);
|
thread_fsm_delete (thr->thread_fsm);
|
||||||
thr->thread_fsm = NULL;
|
thr->thread_fsm = NULL;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user