aboutsummaryrefslogtreecommitdiff
path: root/gdb/mi/mi-interp.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2015-09-09 18:23:24 +0100
committerPedro Alves <palves@redhat.com>2015-09-09 18:24:00 +0100
commit243a925328f8e3184b2356bee497181049c0174f (patch)
treebc734266b2d89d35bd5ab6a43d27499d46f4483e /gdb/mi/mi-interp.c
parent0b333c5e7d6c3fc65d37ffa11bd21ba52c4adb25 (diff)
downloadgdb-243a925328f8e3184b2356bee497181049c0174f.zip
gdb-243a925328f8e3184b2356bee497181049c0174f.tar.gz
gdb-243a925328f8e3184b2356bee497181049c0174f.tar.bz2
Replace "struct continuation" mechanism by something more extensible
This adds an object oriented replacement for the "struct continuation" mechanism, and converts the stepping commands (step, next, stepi, nexti) and the "finish" commands to use it. It adds a new thread "class" (struct thread_fsm) that contains the necessary info and callbacks to manage the state machine of a thread's execution command. This allows getting rid of some hacks. E.g., in fetch_inferior_event and normal_stop we no longer need to know whether a thread is doing a multi-step (e.g., step N). This effectively makes the intermediate_continuations unused -- they'll be garbage collected in a separate patch. (They were never a proper abstraction, IMO. See how fetch_inferior_event needs to check step_multi before knowing whether to call INF_EXEC_CONTINUE or INF_EXEC_COMPLETE.) The target async vs !async uiout hacks in mi_on_normal_stop go away too. print_stop_event is no longer called from normal_stop. Instead it is now called from within each interpreter's normal_stop observer. This clears the path to make each interpreter print a stop event the way it sees fit. Currently we have some hacks in common code to differenciate CLI vs TUI vs MI around this area. The "finish" command's FSM class stores the return value plus that value's position in the value history, so that those can be printed to both MI and CLI's streams. This fixes the CLI "finish" command when run from MI -- it now also includes the function's return value in the CLI stream: (gdb) ~"callee3 (strarg=0x400730 \"A string argument.\") at src/gdb/testsuite/gdb.mi/basics.c:35\n" ~"35\t}\n" +~"Value returned is $1 = 0\n" *stopped,reason="function-finished",frame=...,gdb-result-var="$1",return-value="0",thread-id="1",stopped-threads="all",core="0" -FAIL: gdb.mi/mi-cli.exp: CLI finish: check CLI output +PASS: gdb.mi/mi-cli.exp: CLI finish: check CLI output gdb/ChangeLog: 2015-09-09 Pedro Alves <palves@redhat.com> * Makefile.in (COMMON_OBS): Add thread-fsm.o. * breakpoint.c (handle_jit_event): Print debug output. (bpstat_what): Split event callback handling to ... (bpstat_run_callbacks): ... this new function. (momentary_bkpt_print_it): No longer handle bp_finish here. * breakpoint.h (bpstat_run_callbacks): Declare. * gdbthread.h (struct thread_info) <step_multi>: Delete field. <thread_fsm>: New field. (thread_cancel_execution_command): Declare. * infcmd.c: Include thread-fsm.h. (struct step_command_fsm): New. (step_command_fsm_ops): New global. (new_step_command_fsm, step_command_fsm_prepare): New functions. (step_1): Adjust to use step_command_fsm_prepare and prepare_one_step. (struct step_1_continuation_args): Delete. (step_1_continuation): Delete. (step_command_fsm_should_stop): New function. (step_once): Delete. (step_command_fsm_clean_up, step_command_fsm_async_reply_reason) (prepare_one_step): New function, based on step_once. (until_next_command): Remove step_multi reference. (struct return_value_info): New. (print_return_value): Rename to ... (print_return_value_1): ... this. New struct return_value_info parameter. Adjust. (print_return_value): Reimplement as wrapper around print_return_value_1. (struct finish_command_fsm): New. (finish_command_continuation): Delete. (finish_command_fsm_ops): New global. (new_finish_command_fsm, finish_command_fsm_should_stop): New functions. (finish_command_fsm_clean_up, finish_command_fsm_return_value): New. (finish_command_continuation_free_arg): Delete. (finish_command_fsm_async_reply_reason): New. (finish_backward, finish_forward): Change symbol parameter to a finish_command_fsm. Adjust. (finish_command): Create a finish_command_fsm. Adjust. * infrun.c: Include "thread-fsm.h". (clear_proceed_status_thread): Delete the thread's FSM. (infrun_thread_stop_requested_callback): Cancel the thread's execution command. (clean_up_just_stopped_threads_fsms): New function. (fetch_inferior_event): Handle the event_thread's should_stop method saying the command isn't done yet. (process_event_stop_test): Run breakpoint callbacks here. (print_stop_event): Rename to ... (print_stop_location): ... this. (restore_current_uiout_cleanup): New function. (print_stop_event): Reimplement. (normal_stop): No longer notify the end_stepping_range observers here handle "step N" nor "finish" here. No longer call print_stop_event here. * infrun.h (struct return_value_info): Forward declare. (print_return_value): Declare. (print_stop_event): Change prototype. * thread-fsm.c: New file. * thread-fsm.h: New file. * thread.c: Include "thread-fsm.h". (thread_cancel_execution_command): New function. (clear_thread_inferior_resources): Call it. * cli/cli-interp.c (cli_on_normal_stop): New function. (cli_interpreter_init): Install cli_on_normal_stop as normal_stop observer. * mi/mi-interp.c: Include "thread-fsm.h". (restore_current_uiout_cleanup): Delete. (mi_on_normal_stop): If the thread has an FSM associated, and it finished, ask it for the async-reply-reason to print. Always call print_stop_event here, regardless of the top-level interpreter. Check bpstat_what to tell whether an asynchronous breakpoint hit triggered. * tui/tui-interp.c (tui_on_normal_stop): New function. (tui_init): Install tui_on_normal_stop as normal_stop observer. gdb/testsuite/ChangeLog: 2015-09-09 Pedro Alves <palves@redhat.com> * gdb.mi/mi-cli.exp: Add CLI finish tests.
Diffstat (limited to 'gdb/mi/mi-interp.c')
-rw-r--r--gdb/mi/mi-interp.c108
1 files changed, 37 insertions, 71 deletions
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 0935c8f..385b975 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -37,6 +37,7 @@
#include "objfiles.h"
#include "tracepoint.h"
#include "cli-out.h"
+#include "thread-fsm.h"
/* These are the interpreter setup, etc. functions for the MI
interpreter. */
@@ -454,16 +455,6 @@ mi_inferior_removed (struct inferior *inf)
gdb_flush (mi->event_channel);
}
-/* Cleanup that restores a previous current uiout. */
-
-static void
-restore_current_uiout_cleanup (void *arg)
-{
- struct ui_out *saved_uiout = arg;
-
- current_uiout = saved_uiout;
-}
-
/* Return the MI interpreter, if it is active -- either because it's
the top-level interpreter or the interpreter executing the current
command. Returns NULL if the MI interpreter is not being used. */
@@ -581,73 +572,48 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame)
if (print_frame)
{
+ struct thread_info *tp;
int core;
- if (current_uiout != mi_uiout)
- {
- /* The normal_stop function has printed frame information
- into CLI uiout, or some other non-MI uiout. There's no
- way we can extract proper fields from random uiout
- object, so we print the frame again. In practice, this
- can only happen when running a CLI command in MI. */
- struct ui_out *saved_uiout = current_uiout;
- struct target_waitstatus last;
- ptid_t last_ptid;
-
- current_uiout = mi_uiout;
+ tp = inferior_thread ();
- get_last_target_status (&last_ptid, &last);
- print_stop_event (&last);
+ if (tp->thread_fsm != NULL
+ && thread_fsm_finished_p (tp->thread_fsm))
+ {
+ enum async_reply_reason reason;
- current_uiout = saved_uiout;
+ reason = thread_fsm_async_reply_reason (tp->thread_fsm);
+ ui_out_field_string (mi_uiout, "reason",
+ async_reason_lookup (reason));
}
- /* Otherwise, frame information has already been printed by
- normal_stop. */
- else
+ print_stop_event (mi_uiout);
+
+ /* Breakpoint hits should always be mirrored to the console.
+ Deciding what to mirror to the console wrt to breakpoints and
+ random stops gets messy real fast. E.g., say "s" trips on a
+ breakpoint. We'd clearly want to mirror the event to the
+ console in this case. But what about more complicated cases
+ like "s&; thread n; s&", and one of those steps spawning a
+ new thread, and that thread hitting a breakpoint? It's
+ impossible in general to track whether the thread had any
+ relation to the commands that had been executed. So we just
+ simplify and always mirror breakpoints and random events to
+ the console.
+
+ OTOH, we should print the source line to the console when
+ stepping or other similar commands, iff the step was started
+ by a console command, but not if it was started with
+ -exec-step or similar. */
+ 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 != top_level_interpreter ()))
{
- /* Breakpoint hits should always be mirrored to the console.
- Deciding what to mirror to the console wrt to breakpoints
- and random stops gets messy real fast. E.g., say "s"
- trips on a breakpoint. We'd clearly want to mirror the
- event to the console in this case. But what about more
- complicated cases like "s&; thread n; s&", and one of
- those steps spawning a new thread, and that thread
- hitting a breakpoint? It's impossible in general to
- track whether the thread had any relation to the commands
- that had been executed. So we just simplify and always
- mirror breakpoints and random events to the console.
-
- Also, CLI execution commands (-interpreter-exec console
- "next", for example) in async mode have the opposite
- issue as described in the "then" branch above --
- normal_stop has already printed frame information to MI
- uiout, but nothing has printed the same information to
- the CLI channel. We should print the source line to the
- console when stepping or other similar commands, iff the
- step was started by a console command (but not if it was
- started with -exec-step or similar). */
- struct thread_info *tp = inferior_thread ();
-
- if ((!tp->control.stop_step
- && !tp->control.proceed_to_finish)
- || (tp->control.command_interp != NULL
- && tp->control.command_interp != top_level_interpreter ()))
- {
- struct mi_interp *mi = top_level_interpreter_data ();
- struct target_waitstatus last;
- ptid_t last_ptid;
- struct cleanup *old_chain;
-
- /* Set the current uiout to CLI uiout temporarily. */
- old_chain = make_cleanup (restore_current_uiout_cleanup,
- current_uiout);
- current_uiout = mi->cli_uiout;
-
- get_last_target_status (&last_ptid, &last);
- print_stop_event (&last);
-
- do_cleanups (old_chain);
- }
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ print_stop_event (mi->cli_uiout);
}
ui_out_field_int (mi_uiout, "thread-id",