diff options
Diffstat (limited to 'gdb/mi')
-rw-r--r-- | gdb/mi/mi-cmds.c | 2 | ||||
-rw-r--r-- | gdb/mi/mi-cmds.h | 2 | ||||
-rw-r--r-- | gdb/mi/mi-interp.c | 117 | ||||
-rw-r--r-- | gdb/mi/mi-main.c | 249 | ||||
-rw-r--r-- | gdb/mi/mi-parse.c | 31 | ||||
-rw-r--r-- | gdb/mi/mi-parse.h | 2 |
6 files changed, 323 insertions, 80 deletions
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 1acd54c..7f18d94 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -33,6 +33,7 @@ static void build_table (struct mi_cmd *commands); struct mi_cmd mi_cmds[] = { + { "add-inferior", { NULL, 0 }, mi_cmd_add_inferior }, { "break-after", { "ignore", 1 }, NULL }, { "break-condition", { "cond", 1 }, NULL }, { "break-commands", { NULL, 0 }, mi_cmd_break_commands }, @@ -84,6 +85,7 @@ struct mi_cmd mi_cmds[] = { "list-features", { NULL, 0 }, mi_cmd_list_features}, { "list-target-features", { NULL, 0 }, mi_cmd_list_target_features}, { "list-thread-groups", { NULL, 0 }, mi_cmd_list_thread_groups }, + { "remove-inferior", { NULL, 0 }, mi_cmd_remove_inferior }, { "stack-info-depth", { NULL, 0 }, mi_cmd_stack_info_depth}, { "stack-info-frame", { NULL, 0 }, mi_cmd_stack_info_frame}, { "stack-list-arguments", { NULL, 0 }, mi_cmd_stack_list_args}, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 7feb1c2..20bdbfd 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -36,6 +36,7 @@ extern const char mi_all_values[]; typedef void (mi_cmd_argv_ftype) (char *command, char **argv, int argc); /* Function implementing each command */ +extern mi_cmd_argv_ftype mi_cmd_add_inferior; extern mi_cmd_argv_ftype mi_cmd_break_insert; extern mi_cmd_argv_ftype mi_cmd_break_commands; extern mi_cmd_argv_ftype mi_cmd_break_watch; @@ -71,6 +72,7 @@ extern mi_cmd_argv_ftype mi_cmd_interpreter_exec; extern mi_cmd_argv_ftype mi_cmd_list_features; extern mi_cmd_argv_ftype mi_cmd_list_target_features; extern mi_cmd_argv_ftype mi_cmd_list_thread_groups; +extern mi_cmd_argv_ftype mi_cmd_remove_inferior; extern mi_cmd_argv_ftype mi_cmd_stack_info_depth; extern mi_cmd_argv_ftype mi_cmd_stack_info_frame; extern mi_cmd_argv_ftype mi_cmd_stack_list_args; diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 41388bb..af225e7 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -56,13 +56,17 @@ 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_inferior_appeared (int pid); -static void mi_inferior_exit (int pid); +static void mi_inferior_added (struct inferior *inf); +static void mi_inferior_appeared (struct inferior *inf); +static void mi_inferior_exit (struct inferior *inf); +static void mi_inferior_removed (struct inferior *inf); 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 int report_initial_inferior (struct inferior *inf, void *closure); + static void * mi_interpreter_init (int top_level) { @@ -86,13 +90,20 @@ mi_interpreter_init (int top_level) { observer_attach_new_thread (mi_new_thread); observer_attach_thread_exit (mi_thread_exit); + observer_attach_inferior_added (mi_inferior_added); observer_attach_inferior_appeared (mi_inferior_appeared); observer_attach_inferior_exit (mi_inferior_exit); + observer_attach_inferior_removed (mi_inferior_removed); 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); + + /* The initial inferior is created before this function is called, so we + need to report it explicitly. Use iteration in case future version + of GDB creates more than one inferior up-front. */ + iterate_over_inferiors (report_initial_inferior, mi); } return mi; @@ -285,10 +296,13 @@ static void mi_new_thread (struct thread_info *t) { struct mi_interp *mi = top_level_interpreter_data (); + struct inferior *inf = find_inferior_pid (ptid_get_pid (t->ptid)); + + gdb_assert (inf); fprintf_unfiltered (mi->event_channel, - "thread-created,id=\"%d\",group-id=\"%d\"", - t->num, t->ptid.pid); + "thread-created,id=\"%d\",group-id=\"i%d\"", + t->num, inf->num); gdb_flush (mi->event_channel); } @@ -296,39 +310,65 @@ static void mi_thread_exit (struct thread_info *t, int silent) { struct mi_interp *mi; + struct inferior *inf; if (silent) return; + inf = find_inferior_pid (ptid_get_pid (t->ptid)); + mi = top_level_interpreter_data (); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, - "thread-exited,id=\"%d\",group-id=\"%d\"", - t->num,t->ptid.pid); + "thread-exited,id=\"%d\",group-id=\"i%d\"", + t->num, inf->num); gdb_flush (mi->event_channel); } -void -mi_inferior_appeared (int pid) +static void +mi_inferior_added (struct inferior *inf) +{ + struct mi_interp *mi = top_level_interpreter_data (); + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "thread-group-added,id=\"i%d\"", + inf->num); + gdb_flush (mi->event_channel); +} + +static void +mi_inferior_appeared (struct inferior *inf) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); - fprintf_unfiltered (mi->event_channel, "thread-group-created,id=\"%d\"", - pid); + fprintf_unfiltered (mi->event_channel, + "thread-group-started,id=\"i%d\",pid=\"%d\"", + inf->num, inf->pid); gdb_flush (mi->event_channel); } static void -mi_inferior_exit (int pid) +mi_inferior_exit (struct inferior *inf) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); - fprintf_unfiltered (mi->event_channel, "thread-group-exited,id=\"%d\"", - pid); + fprintf_unfiltered (mi->event_channel, "thread-group-exited,id=\"i%d\"", + inf->num); gdb_flush (mi->event_channel); } static void +mi_inferior_removed (struct inferior *inf) +{ + struct mi_interp *mi = top_level_interpreter_data (); + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "thread-group-removed,id=\"i%d\"", + inf->num); + gdb_flush (mi->event_channel); +} + +static void mi_on_normal_stop (struct bpstats *bs, int print_frame) { /* Since this can be called when CLI command is executing, @@ -489,10 +529,21 @@ mi_solib_loaded (struct so_list *solib) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); - fprintf_unfiltered (mi->event_channel, - "library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded=\"%d\"", - solib->so_original_name, solib->so_original_name, - solib->so_name, solib->symbols_loaded); + 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\"", + solib->so_original_name, solib->so_original_name, + solib->so_name, solib->symbols_loaded); + else + fprintf_unfiltered (mi->event_channel, + "library-loaded,id=\"%s\",target-name=\"%s\"," + "host-name=\"%s\",symbols-loaded=\"%d\"," + "thread-group=\"i%d\"", + solib->so_original_name, solib->so_original_name, + solib->so_name, solib->symbols_loaded, + current_inferior ()->num); + gdb_flush (mi->event_channel); } @@ -501,13 +552,37 @@ mi_solib_unloaded (struct so_list *solib) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); - fprintf_unfiltered (mi->event_channel, - "library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\"", - solib->so_original_name, solib->so_original_name, - solib->so_name); + if (gdbarch_has_global_solist (target_gdbarch)) + fprintf_unfiltered (mi->event_channel, + "library-unloaded,id=\"%s\",target-name=\"%s\"," + "host-name=\"%s\"", + solib->so_original_name, solib->so_original_name, + solib->so_name); + else + fprintf_unfiltered (mi->event_channel, + "library-unloaded,id=\"%s\",target-name=\"%s\"," + "host-name=\"%s\",thread-group=\"i%d\"", + solib->so_original_name, solib->so_original_name, + solib->so_name, current_inferior ()->num); + gdb_flush (mi->event_channel); } +static int +report_initial_inferior (struct inferior *inf, void *closure) +{ + /* This function is called from mi_intepreter_init, and since + mi_inferior_added assumes that inferior is fully initialized + and top_level_interpreter_data is set, we cannot call + it here. */ + struct mi_interp *mi = closure; + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "thread-group-added,id=\"i%d\"", + inf->num); + gdb_flush (mi->event_channel); + return 0; +} extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */ diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index f1b745c..51a9da8 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -78,6 +78,11 @@ static struct mi_timestamp *current_command_ts; static int do_timings = 0; char *current_token; +/* Few commands would like to know if options like --thread-group + were explicitly specified. This variable keeps the current + parsed command including all option, and make it possible. */ +static struct mi_parse *current_context; + int running_result_record_printed = 1; /* Flag indicating that the target has proceeded since the last @@ -193,55 +198,79 @@ mi_cmd_exec_jump (char *args, char **argv, int argc) mi_execute_async_cli_command ("jump", argv, argc); } -static int -proceed_thread_callback (struct thread_info *thread, void *arg) +static void +proceed_thread (struct thread_info *thread, int pid) { - int pid = *(int *)arg; - if (!is_stopped (thread->ptid)) - return 0; + return; - if (PIDGET (thread->ptid) != pid) - return 0; + if (pid != 0 && PIDGET (thread->ptid) != pid) + return; switch_to_thread (thread->ptid); clear_proceed_status (); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); +} + + +static int +proceed_thread_callback (struct thread_info *thread, void *arg) +{ + int pid = *(int *)arg; + proceed_thread (thread, pid); return 0; } static void exec_continue (char **argv, int argc) { - if (argc == 0) - continue_1 (0); - else if (argc == 1 && strcmp (argv[0], "--all") == 0) - continue_1 (1); - else if (argc == 2 && strcmp (argv[0], "--thread-group") == 0) + if (non_stop) { - struct cleanup *old_chain; - int pid; - if (argv[1] == NULL || argv[1] == '\0') - error ("Thread group id not specified"); - pid = atoi (argv[1]); - if (!in_inferior_list (pid)) - error ("Invalid thread group id '%s'", argv[1]); + /* In non-stop mode, 'resume' always resumes a single thread. Therefore, + to resume all threads of the current inferior, or all threads in all + inferiors, we need to iterate over threads. - old_chain = make_cleanup_restore_current_thread (); - iterate_over_threads (proceed_thread_callback, &pid); - do_cleanups (old_chain); + See comment on infcmd.c:proceed_thread_callback for rationale. */ + if (current_context->all || current_context->thread_group != -1) + { + int pid = 0; + struct cleanup *back_to = make_cleanup_restore_current_thread (); + + if (!current_context->all) + { + struct inferior *inf = find_inferior_id (current_context->thread_group); + pid = inf->pid; + } + iterate_over_threads (proceed_thread_callback, &pid); + do_cleanups (back_to); + } + else + { + continue_1 (0); + } } else - error ("Usage: -exec-continue [--reverse] [--all|--thread-group id]"); + { + struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi); + if (current_context->all) + { + sched_multi = 1; + continue_1 (0); + } + else + { + /* In all-stop mode, -exec-continue traditionally resumed either + all threads, or one thread, depending on the 'scheduler-locking' + variable. Let's continue to do the same. */ + continue_1 (1); + } + do_cleanups (back_to); + } } -/* continue in reverse direction: - XXX: code duplicated from reverse.c */ - static void -exec_direction_default (void *notused) +exec_direction_forward (void *notused) { - /* Return execution direction to default state. */ execution_direction = EXEC_FORWARD; } @@ -260,7 +289,7 @@ exec_reverse_continue (char **argv, int argc) if (!target_can_execute_reverse) error (_("Target %s does not support this command."), target_shortname); - old_chain = make_cleanup (exec_direction_default, NULL); + old_chain = make_cleanup (exec_direction_forward, NULL); execution_direction = EXEC_REVERSE; exec_continue (argv, argc); do_cleanups (old_chain); @@ -269,7 +298,7 @@ exec_reverse_continue (char **argv, int argc) void mi_cmd_exec_continue (char *command, char **argv, int argc) { - if (argc > 0 && strcmp(argv[0], "--reverse") == 0) + if (argc > 0 && strcmp (argv[0], "--reverse") == 0) exec_reverse_continue (argv + 1, argc - 1); else exec_continue (argv, argc); @@ -298,45 +327,79 @@ interrupt_thread_callback (struct thread_info *thread, void *arg) void mi_cmd_exec_interrupt (char *command, char **argv, int argc) { - if (argc == 0) + /* In all-stop mode, everything stops, so we don't need to try + anything specific. */ + if (!non_stop) { - if (!is_running (inferior_ptid)) - error ("Current thread is not running."); - interrupt_target_1 (0); + return; } - else if (argc == 1 && strcmp (argv[0], "--all") == 0) + + if (current_context->all) { - if (!any_running ()) - error ("Inferior not running."); - + /* This will interrupt all threads in all inferiors. */ interrupt_target_1 (1); } - else if (argc == 2 && strcmp (argv[0], "--thread-group") == 0) + else if (current_context->thread_group != -1) { - struct cleanup *old_chain; - int pid; - if (argv[1] == NULL || argv[1] == '\0') - error ("Thread group id not specified"); - pid = atoi (argv[1]); - if (!in_inferior_list (pid)) - error ("Invalid thread group id '%s'", argv[1]); + struct inferior *inf = find_inferior_id (current_context->thread_group); + iterate_over_threads (interrupt_thread_callback, &inf->pid); + } + else + { + /* Interrupt just the current thread -- either explicitly + specified via --thread or whatever was current before + MI command was sent. */ + interrupt_target_1 (0); + } +} + +static int +run_one_inferior (struct inferior *inf, void *arg) +{ + struct thread_info *tp = 0; - old_chain = make_cleanup_restore_current_thread (); - iterate_over_threads (interrupt_thread_callback, &pid); - do_cleanups (old_chain); + if (inf->pid != 0) + { + if (inf->pid != ptid_get_pid (inferior_ptid)) + { + struct thread_info *tp; + + tp = any_thread_of_process (inf->pid); + if (!tp) + error (_("Inferior has no threads.")); + + switch_to_thread (tp->ptid); + } } else - error ("Usage: -exec-interrupt [--all|--thread-group id]"); + { + set_current_inferior (inf); + switch_to_thread (null_ptid); + set_current_program_space (inf->pspace); + } + mi_execute_cli_command ("run", target_can_async_p (), + target_can_async_p () ? "&" : NULL); + return 0; } void mi_cmd_exec_run (char *command, char **argv, int argc) { - mi_execute_cli_command ("run", target_can_async_p (), - target_can_async_p () ? "&" : NULL); + if (current_context->all) + { + struct cleanup *back_to = save_current_space_and_thread (); + iterate_over_inferiors (run_one_inferior, NULL); + do_cleanups (back_to); + } + else + { + mi_execute_cli_command ("run", target_can_async_p (), + target_can_async_p () ? "&" : NULL); + } } + static int find_thread_of_process (struct thread_info *ti, void *p) { @@ -475,13 +538,23 @@ print_one_inferior (struct inferior *inferior, void *xdata) struct cleanup *back_to = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); - ui_out_field_fmt (uiout, "id", "%d", inferior->pid); + ui_out_field_fmt (uiout, "id", "i%d", inferior->num); ui_out_field_string (uiout, "type", "process"); - ui_out_field_int (uiout, "pid", inferior->pid); + if (inferior->pid != 0) + ui_out_field_int (uiout, "pid", inferior->pid); + + if (inferior->pspace->ebfd) + { + ui_out_field_string (uiout, "executable", + bfd_get_filename (inferior->pspace->ebfd)); + } - data.pid = inferior->pid; data.cores = 0; - iterate_over_threads (collect_cores, &data); + if (inferior->pid != 0) + { + data.pid = inferior->pid; + iterate_over_threads (collect_cores, &data); + } if (!VEC_empty (int, data.cores)) { @@ -1492,6 +1565,40 @@ mi_cmd_list_target_features (char *command, char **argv, int argc) error ("-list-target-features should be passed no arguments"); } +void +mi_cmd_add_inferior (char *command, char **argv, int argc) +{ + struct inferior *inf; + + if (argc != 0) + error (_("-add-inferior should be passed no arguments")); + + inf = add_inferior_with_spaces (); + + ui_out_field_fmt (uiout, "inferior", "i%d", inf->num); +} + +void +mi_cmd_remove_inferior (char *command, char **argv, int argc) +{ + int id; + struct inferior *inf; + + if (argc != 1) + error ("-remove-inferior should be passed a single argument"); + + if (sscanf (argv[1], "i%d", &id) != 1) + error ("the thread group id is syntactically invalid"); + + inf = find_inferior_id (id); + if (!inf) + error ("the specified thread group does not exist"); + + delete_inferior_1 (inf, 1 /* silent */); +} + + + /* Execute a command within a safe environment. Return <0 for error; >=0 for ok. @@ -1693,9 +1800,37 @@ mi_cmd_execute (struct mi_parse *parse) cleanup = make_cleanup (null_cleanup, NULL); + if (parse->all && parse->thread_group != -1) + error (_("Cannot specify --thread-group together with --all")); + + if (parse->all && parse->thread != -1) + error (_("Cannot specify --thread together with --all")); + + if (parse->thread_group != -1 && parse->thread != -1) + error (_("Cannot specify --thread together with --thread-group")); + if (parse->frame != -1 && parse->thread == -1) error (_("Cannot specify --frame without --thread")); + if (parse->thread_group != -1) + { + struct inferior *inf = find_inferior_id (parse->thread_group); + struct thread_info *tp = 0; + + if (!inf) + error (_("Invalid thread group for the --tread-group option")); + + set_current_inferior (inf); + /* This behaviour means that if --thread-group option identifies + an inferior with multiple threads, then a random one will be picked. + This is not a problem -- frontend should always provide --thread if + it wishes to operate on a specific thread. */ + if (inf->pid != 0) + tp = any_thread_of_process (inf->pid); + switch_to_thread (tp ? tp->ptid : null_ptid); + set_current_program_space (inf->pspace); + } + if (parse->thread != -1) { struct thread_info *tp = find_thread_id (parse->thread); @@ -1720,6 +1855,8 @@ mi_cmd_execute (struct mi_parse *parse) error (_("Invalid frame id: %d"), frame); } + current_context = parse; + if (parse->cmd->argv_func != NULL) parse->cmd->argv_func (parse->command, parse->argv, parse->argc); else if (parse->cmd->cli.cmd != 0) diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c index 4ff70ef..8548b67 100644 --- a/gdb/mi/mi-parse.c +++ b/gdb/mi/mi-parse.c @@ -151,6 +151,8 @@ mi_parse (char *cmd) char *chp; struct mi_parse *parse = XMALLOC (struct mi_parse); memset (parse, 0, sizeof (*parse)); + parse->all = 0; + parse->thread_group = -1; parse->thread = -1; parse->frame = -1; @@ -210,19 +212,42 @@ mi_parse (char *cmd) for (;;) { char *start = chp; + size_t as = sizeof ("--all ") - 1; + size_t tgs = sizeof ("--thread-group ") - 1; size_t ts = sizeof ("--thread ") - 1; size_t fs = sizeof ("--frame ") - 1; + if (strncmp (chp, "--all ", as) == 0) + { + parse->all = 1; + chp += as; + } + /* See if --all is the last token in the input. */ + if (strcmp (chp, "--all") == 0) + { + parse->all = 1; + chp += strlen (chp); + } + if (strncmp (chp, "--thread-group ", tgs) == 0) + { + if (parse->thread_group != -1) + error (_("Duplicate '--thread-group' option")); + chp += tgs; + if (*chp != 'i') + error (_("Invalid thread group id")); + chp += 1; + parse->thread_group = strtol (chp, &chp, 10); + } if (strncmp (chp, "--thread ", ts) == 0) { if (parse->thread != -1) - error ("Duplicate '--thread' option"); + error (_("Duplicate '--thread' option")); chp += ts; parse->thread = strtol (chp, &chp, 10); } else if (strncmp (chp, "--frame ", fs) == 0) { if (parse->frame != -1) - error ("Duplicate '--frame' option"); + error (_("Duplicate '--frame' option")); chp += fs; parse->frame = strtol (chp, &chp, 10); } @@ -230,7 +255,7 @@ mi_parse (char *cmd) break; if (*chp != '\0' && !isspace (*chp)) - error ("Invalid value for the '%s' option", + error (_("Invalid value for the '%s' option"), start[2] == 't' ? "--thread" : "--frame"); while (isspace (*chp)) chp++; diff --git a/gdb/mi/mi-parse.h b/gdb/mi/mi-parse.h index a63ee8e..3c6cd9a 100644 --- a/gdb/mi/mi-parse.h +++ b/gdb/mi/mi-parse.h @@ -46,6 +46,8 @@ struct mi_parse char *args; char **argv; int argc; + int all; + int thread_group; /* At present, the same as inferior number. */ int thread; int frame; }; |