| Index: gdb/mi/mi-interp.c
|
| diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
|
| index b48713676e12470b69e7a8bedca3d4fdd694e09b..2ed1726837b502aeab48c5ab7248a74e18737b8a 100644
|
| --- a/gdb/mi/mi-interp.c
|
| +++ b/gdb/mi/mi-interp.c
|
| @@ -1,6 +1,6 @@
|
| /* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
|
|
|
| - Copyright (C) 2002-2005, 2007-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 2002-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -18,7 +18,7 @@
|
| along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
| #include "defs.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "interps.h"
|
| #include "event-top.h"
|
| #include "event-loop.h"
|
| @@ -35,13 +35,15 @@
|
| #include "gdbthread.h"
|
| #include "solist.h"
|
| #include "gdb.h"
|
| +#include "objfiles.h"
|
| +#include "tracepoint.h"
|
|
|
| /* These are the interpreter setup, etc. functions for the MI
|
| interpreter. */
|
|
|
| -static void mi_execute_command_wrapper (char *cmd);
|
| +static void mi_execute_command_wrapper (const char *cmd);
|
| static void mi_execute_command_input_handler (char *cmd);
|
| -static void mi_command_loop (int mi_version);
|
| +static void mi_command_loop (void *data);
|
|
|
| /* These are hooks that we put in place while doing interpreter_exec
|
| so we can report interesting things that happened "behind the MI's
|
| @@ -50,16 +52,13 @@ static void mi_command_loop (int mi_version);
|
| static int mi_interp_query_hook (const char *ctlstr, va_list ap)
|
| ATTRIBUTE_PRINTF (1, 0);
|
|
|
| -static void mi3_command_loop (void);
|
| -static void mi2_command_loop (void);
|
| -static void mi1_command_loop (void);
|
| -
|
| static void mi_insert_notify_hooks (void);
|
| static void mi_remove_notify_hooks (void);
|
| static void mi_on_normal_stop (struct bpstats *bs, int print_frame);
|
|
|
| static void mi_new_thread (struct thread_info *t);
|
| static void mi_thread_exit (struct thread_info *t, int silent);
|
| +static void mi_record_changed (struct inferior*, int);
|
| static void mi_inferior_added (struct inferior *inf);
|
| static void mi_inferior_appeared (struct inferior *inf);
|
| static void mi_inferior_exit (struct inferior *inf);
|
| @@ -68,9 +67,16 @@ static void mi_on_resume (ptid_t ptid);
|
| static void mi_solib_loaded (struct so_list *solib);
|
| static void mi_solib_unloaded (struct so_list *solib);
|
| static void mi_about_to_proceed (void);
|
| +static void mi_traceframe_changed (int tfnum, int tpnum);
|
| +static void mi_tsv_created (const struct trace_state_variable *tsv);
|
| +static void mi_tsv_deleted (const struct trace_state_variable *tsv);
|
| +static void mi_tsv_modified (const struct trace_state_variable *tsv);
|
| static void mi_breakpoint_created (struct breakpoint *b);
|
| static void mi_breakpoint_deleted (struct breakpoint *b);
|
| static void mi_breakpoint_modified (struct breakpoint *b);
|
| +static void mi_command_param_changed (const char *param, const char *value);
|
| +static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr,
|
| + ssize_t len, const bfd_byte *myaddr);
|
|
|
| static int report_initial_inferior (struct inferior *inf, void *closure);
|
|
|
| @@ -120,14 +126,21 @@ mi_interpreter_init (struct interp *interp, int top_level)
|
| observer_attach_inferior_appeared (mi_inferior_appeared);
|
| observer_attach_inferior_exit (mi_inferior_exit);
|
| observer_attach_inferior_removed (mi_inferior_removed);
|
| + observer_attach_record_changed (mi_record_changed);
|
| observer_attach_normal_stop (mi_on_normal_stop);
|
| observer_attach_target_resumed (mi_on_resume);
|
| observer_attach_solib_loaded (mi_solib_loaded);
|
| observer_attach_solib_unloaded (mi_solib_unloaded);
|
| observer_attach_about_to_proceed (mi_about_to_proceed);
|
| + observer_attach_traceframe_changed (mi_traceframe_changed);
|
| + observer_attach_tsv_created (mi_tsv_created);
|
| + observer_attach_tsv_deleted (mi_tsv_deleted);
|
| + observer_attach_tsv_modified (mi_tsv_modified);
|
| observer_attach_breakpoint_created (mi_breakpoint_created);
|
| observer_attach_breakpoint_deleted (mi_breakpoint_deleted);
|
| observer_attach_breakpoint_modified (mi_breakpoint_modified);
|
| + observer_attach_command_param_changed (mi_command_param_changed);
|
| + observer_attach_memory_changed (mi_memory_changed);
|
|
|
| /* The initial inferior is created before this function is
|
| called, so we need to report it explicitly. Use iteration in
|
| @@ -152,7 +165,6 @@ mi_interpreter_resume (void *data)
|
| _intialize_event_loop. */
|
| call_readline = gdb_readline2;
|
| input_handler = mi_execute_command_input_handler;
|
| - add_file_handler (input_fd, stdin_event_handler, 0);
|
| async_command_editing_p = 0;
|
| /* FIXME: This is a total hack for now. PB's use of the MI
|
| implicitly relies on a bug in the async support which allows
|
| @@ -177,16 +189,6 @@ mi_interpreter_resume (void *data)
|
|
|
| deprecated_show_load_progress = mi_load_progress;
|
|
|
| - /* If we're _the_ interpreter, take control. */
|
| - if (current_interp_named_p (INTERP_MI1))
|
| - deprecated_command_loop_hook = mi1_command_loop;
|
| - else if (current_interp_named_p (INTERP_MI2))
|
| - deprecated_command_loop_hook = mi2_command_loop;
|
| - else if (current_interp_named_p (INTERP_MI3))
|
| - deprecated_command_loop_hook = mi3_command_loop;
|
| - else
|
| - deprecated_command_loop_hook = mi2_command_loop;
|
| -
|
| return 1;
|
| }
|
|
|
| @@ -200,10 +202,7 @@ mi_interpreter_suspend (void *data)
|
| static struct gdb_exception
|
| mi_interpreter_exec (void *data, const char *command)
|
| {
|
| - char *tmp = alloca (strlen (command) + 1);
|
| -
|
| - strcpy (tmp, command);
|
| - mi_execute_command_wrapper (tmp);
|
| + mi_execute_command_wrapper (command);
|
| return exception_none;
|
| }
|
|
|
| @@ -232,11 +231,6 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
|
| error (_("-interpreter-exec: could not find interpreter \"%s\""),
|
| argv[0]);
|
|
|
| - if (!interp_exec_p (interp_to_use))
|
| - error (_("-interpreter-exec: interpreter \"%s\" "
|
| - "does not support command execution"),
|
| - argv[0]);
|
| -
|
| /* Insert the MI out hooks, making sure to also call the
|
| interpreter's hooks if it has any. */
|
| /* KRS: We shouldn't need this... Events should be installed and
|
| @@ -292,7 +286,7 @@ mi_interp_query_hook (const char *ctlstr, va_list ap)
|
| }
|
|
|
| static void
|
| -mi_execute_command_wrapper (char *cmd)
|
| +mi_execute_command_wrapper (const char *cmd)
|
| {
|
| mi_execute_command (cmd, stdin == instream);
|
| }
|
| @@ -309,25 +303,7 @@ mi_execute_command_input_handler (char *cmd)
|
| }
|
|
|
| static void
|
| -mi1_command_loop (void)
|
| -{
|
| - mi_command_loop (1);
|
| -}
|
| -
|
| -static void
|
| -mi2_command_loop (void)
|
| -{
|
| - mi_command_loop (2);
|
| -}
|
| -
|
| -static void
|
| -mi3_command_loop (void)
|
| -{
|
| - mi_command_loop (3);
|
| -}
|
| -
|
| -static void
|
| -mi_command_loop (int mi_version)
|
| +mi_command_loop (void *data)
|
| {
|
| /* Turn off 8 bit strings in quoted output. Any character with the
|
| high bit set is printed using C's octal format. */
|
| @@ -373,6 +349,19 @@ mi_thread_exit (struct thread_info *t, int silent)
|
| gdb_flush (mi->event_channel);
|
| }
|
|
|
| +/* Emit notification on changing the state of record. */
|
| +
|
| +static void
|
| +mi_record_changed (struct inferior *inferior, int started)
|
| +{
|
| + struct mi_interp *mi = top_level_interpreter_data ();
|
| +
|
| + fprintf_unfiltered (mi->event_channel, "record-%s,thread-group=\"i%d\"",
|
| + started ? "started" : "stopped", inferior->num);
|
| +
|
| + gdb_flush (mi->event_channel);
|
| +}
|
| +
|
| static void
|
| mi_inferior_added (struct inferior *inf)
|
| {
|
| @@ -454,7 +443,7 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame)
|
| get_last_target_status (&last_ptid, &last);
|
| bpstat_print (bs, last.kind);
|
|
|
| - print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC);
|
| + print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
|
| current_uiout = saved_uiout;
|
| }
|
|
|
| @@ -501,10 +490,97 @@ mi_about_to_proceed (void)
|
| mi_proceeded = 1;
|
| }
|
|
|
| -/* When non-zero, no MI notifications will be emitted in
|
| - response to breakpoint change observers. */
|
| +/* When the element is non-zero, no MI notifications will be emitted in
|
| + response to the corresponding observers. */
|
| +
|
| +struct mi_suppress_notification mi_suppress_notification =
|
| + {
|
| + 0,
|
| + 0,
|
| + 0,
|
| + };
|
| +
|
| +/* Emit notification on changing a traceframe. */
|
| +
|
| +static void
|
| +mi_traceframe_changed (int tfnum, int tpnum)
|
| +{
|
| + struct mi_interp *mi = top_level_interpreter_data ();
|
|
|
| -int mi_suppress_breakpoint_notifications = 0;
|
| + if (mi_suppress_notification.traceframe)
|
| + return;
|
| +
|
| + target_terminal_ours ();
|
| +
|
| + if (tfnum >= 0)
|
| + fprintf_unfiltered (mi->event_channel, "traceframe-changed,"
|
| + "num=\"%d\",tracepoint=\"%d\"\n",
|
| + tfnum, tpnum);
|
| + else
|
| + fprintf_unfiltered (mi->event_channel, "traceframe-changed,end");
|
| +
|
| + gdb_flush (mi->event_channel);
|
| +}
|
| +
|
| +/* Emit notification on creating a trace state variable. */
|
| +
|
| +static void
|
| +mi_tsv_created (const struct trace_state_variable *tsv)
|
| +{
|
| + struct mi_interp *mi = top_level_interpreter_data ();
|
| +
|
| + target_terminal_ours ();
|
| +
|
| + fprintf_unfiltered (mi->event_channel, "tsv-created,"
|
| + "name=\"%s\",initial=\"%s\"\n",
|
| + tsv->name, plongest (tsv->initial_value));
|
| +
|
| + gdb_flush (mi->event_channel);
|
| +}
|
| +
|
| +/* Emit notification on deleting a trace state variable. */
|
| +
|
| +static void
|
| +mi_tsv_deleted (const struct trace_state_variable *tsv)
|
| +{
|
| + struct mi_interp *mi = top_level_interpreter_data ();
|
| +
|
| + target_terminal_ours ();
|
| +
|
| + if (tsv != NULL)
|
| + fprintf_unfiltered (mi->event_channel, "tsv-deleted,"
|
| + "name=\"%s\"\n", tsv->name);
|
| + else
|
| + fprintf_unfiltered (mi->event_channel, "tsv-deleted\n");
|
| +
|
| + gdb_flush (mi->event_channel);
|
| +}
|
| +
|
| +/* Emit notification on modifying a trace state variable. */
|
| +
|
| +static void
|
| +mi_tsv_modified (const struct trace_state_variable *tsv)
|
| +{
|
| + struct mi_interp *mi = top_level_interpreter_data ();
|
| + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
|
| +
|
| + target_terminal_ours ();
|
| +
|
| + fprintf_unfiltered (mi->event_channel,
|
| + "tsv-modified");
|
| +
|
| + ui_out_redirect (mi_uiout, mi->event_channel);
|
| +
|
| + ui_out_field_string (mi_uiout, "name", tsv->name);
|
| + ui_out_field_string (mi_uiout, "initial",
|
| + plongest (tsv->initial_value));
|
| + if (tsv->value_known)
|
| + ui_out_field_string (mi_uiout, "current", plongest (tsv->value));
|
| +
|
| + ui_out_redirect (mi_uiout, NULL);
|
| +
|
| + gdb_flush (mi->event_channel);
|
| +}
|
|
|
| /* Emit notification about a created breakpoint. */
|
|
|
| @@ -515,7 +591,7 @@ mi_breakpoint_created (struct breakpoint *b)
|
| struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
|
| volatile struct gdb_exception e;
|
|
|
| - if (mi_suppress_breakpoint_notifications)
|
| + if (mi_suppress_notification.breakpoint)
|
| return;
|
|
|
| if (b->number <= 0)
|
| @@ -546,7 +622,7 @@ mi_breakpoint_deleted (struct breakpoint *b)
|
| {
|
| struct mi_interp *mi = top_level_interpreter_data ();
|
|
|
| - if (mi_suppress_breakpoint_notifications)
|
| + if (mi_suppress_notification.breakpoint)
|
| return;
|
|
|
| if (b->number <= 0)
|
| @@ -569,7 +645,7 @@ mi_breakpoint_modified (struct breakpoint *b)
|
| struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
|
| volatile struct gdb_exception e;
|
|
|
| - if (mi_suppress_breakpoint_notifications)
|
| + if (mi_suppress_notification.breakpoint)
|
| return;
|
|
|
| if (b->number <= 0)
|
| @@ -646,7 +722,7 @@ mi_on_resume (ptid_t ptid)
|
| current_token ? current_token : "");
|
| }
|
|
|
| - if (PIDGET (ptid) == -1)
|
| + if (ptid_get_pid (ptid) == -1)
|
| fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
|
| else if (ptid_is_pid (ptid))
|
| {
|
| @@ -690,7 +766,7 @@ mi_solib_loaded (struct so_list *solib)
|
| struct mi_interp *mi = top_level_interpreter_data ();
|
|
|
| target_terminal_ours ();
|
| - if (gdbarch_has_global_solist (target_gdbarch))
|
| + if (gdbarch_has_global_solist (target_gdbarch ()))
|
| fprintf_unfiltered (mi->event_channel,
|
| "library-loaded,id=\"%s\",target-name=\"%s\","
|
| "host-name=\"%s\",symbols-loaded=\"%d\"",
|
| @@ -714,7 +790,7 @@ mi_solib_unloaded (struct so_list *solib)
|
| struct mi_interp *mi = top_level_interpreter_data ();
|
|
|
| target_terminal_ours ();
|
| - if (gdbarch_has_global_solist (target_gdbarch))
|
| + if (gdbarch_has_global_solist (target_gdbarch ()))
|
| fprintf_unfiltered (mi->event_channel,
|
| "library-unloaded,id=\"%s\",target-name=\"%s\","
|
| "host-name=\"%s\"",
|
| @@ -730,6 +806,73 @@ mi_solib_unloaded (struct so_list *solib)
|
| gdb_flush (mi->event_channel);
|
| }
|
|
|
| +/* Emit notification about the command parameter change. */
|
| +
|
| +static void
|
| +mi_command_param_changed (const char *param, const char *value)
|
| +{
|
| + struct mi_interp *mi = top_level_interpreter_data ();
|
| + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
|
| +
|
| + if (mi_suppress_notification.cmd_param_changed)
|
| + return;
|
| +
|
| + target_terminal_ours ();
|
| +
|
| + fprintf_unfiltered (mi->event_channel,
|
| + "cmd-param-changed");
|
| +
|
| + ui_out_redirect (mi_uiout, mi->event_channel);
|
| +
|
| + ui_out_field_string (mi_uiout, "param", param);
|
| + ui_out_field_string (mi_uiout, "value", value);
|
| +
|
| + ui_out_redirect (mi_uiout, NULL);
|
| +
|
| + gdb_flush (mi->event_channel);
|
| +}
|
| +
|
| +/* Emit notification about the target memory change. */
|
| +
|
| +static void
|
| +mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
|
| + ssize_t len, const bfd_byte *myaddr)
|
| +{
|
| + struct mi_interp *mi = top_level_interpreter_data ();
|
| + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
|
| + struct obj_section *sec;
|
| +
|
| + if (mi_suppress_notification.memory)
|
| + return;
|
| +
|
| + target_terminal_ours ();
|
| +
|
| + fprintf_unfiltered (mi->event_channel,
|
| + "memory-changed");
|
| +
|
| + ui_out_redirect (mi_uiout, mi->event_channel);
|
| +
|
| + ui_out_field_fmt (mi_uiout, "thread-group", "i%d", inferior->num);
|
| + ui_out_field_core_addr (mi_uiout, "addr", target_gdbarch (), memaddr);
|
| + ui_out_field_fmt (mi_uiout, "len", "0x%zx", len);
|
| +
|
| + /* Append 'type=code' into notification if MEMADDR falls in the range of
|
| + sections contain code. */
|
| + sec = find_pc_section (memaddr);
|
| + if (sec != NULL && sec->objfile != NULL)
|
| + {
|
| + flagword flags = bfd_get_section_flags (sec->objfile->obfd,
|
| + sec->the_bfd_section);
|
| +
|
| + if (flags & SEC_CODE)
|
| + ui_out_field_string (mi_uiout, "type", "code");
|
| + }
|
| +
|
| + ui_out_redirect (mi_uiout, NULL);
|
| +
|
| + gdb_flush (mi->event_channel);
|
| +}
|
| +
|
| static int
|
| report_initial_inferior (struct inferior *inf, void *closure)
|
| {
|
| @@ -816,7 +959,8 @@ _initialize_mi_interp (void)
|
| mi_interpreter_exec, /* exec_proc */
|
| mi_interpreter_prompt_p, /* prompt_proc_p */
|
| mi_ui_out, /* ui_out_proc */
|
| - mi_set_logging /* set_logging_proc */
|
| + mi_set_logging, /* set_logging_proc */
|
| + mi_command_loop /* command_loop_proc */
|
| };
|
|
|
| /* The various interpreter levels. */
|
|
|