X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfcmd.c;h=49349c169e5b524a685df7bb68523e065bb7ab12;hb=52eab766df54915f8d3d71475235868285c4ca82;hp=a80bf0a2ceb33309e702ec4742b89a03273e178b;hpb=33b4777ca1b7b456af8201b98eda27d1b272cbab;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infcmd.c b/gdb/infcmd.c index a80bf0a2ce..49349c169e 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1,6 +1,6 @@ /* Memory-access and commands for "inferior" process, for GDB. - Copyright (C) 1986-2016 Free Software Foundation, Inc. + Copyright (C) 1986-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -56,32 +56,25 @@ #include "cli/cli-utils.h" #include "infcall.h" #include "thread-fsm.h" +#include "top.h" +#include "interps.h" +#include "common/gdb_optional.h" /* Local functions: */ -static void nofp_registers_info (char *, int); +static void info_registers_command (char *, int); static void until_next_command (int); static void until_command (char *, int); -static void path_info (char *, int); - static void path_command (char *, int); -static void unset_command (char *, int); - -static void float_info (char *, int); +static void info_float_command (char *, int); static void disconnect_command (char *, int); -static void unset_environment_command (char *, int); - -static void set_environment_command (char *, int); - -static void environment_info (char *, int); - -static void program_info (char *, int); +static void info_program_command (char *, int); static void finish_command (char *, int); @@ -97,8 +90,6 @@ static void step_command (char *, int); static void run_command (char *, int); -void _initialize_infcmd (void); - #define ERROR_NO_INFERIOR \ if (!target_has_execution) error (_("The program is not being run.")); @@ -110,6 +101,10 @@ void _initialize_infcmd (void); static char *inferior_args_scratch; +/* Scratch area where the new cwd will be stored by 'set cwd'. */ + +static char *inferior_cwd_scratch; + /* Scratch area where 'set inferior-tty' will store user-provided value. We'll immediate copy it into per-inferior storage. */ @@ -149,7 +144,11 @@ void set_inferior_io_terminal (const char *terminal_name) { xfree (current_inferior ()->terminal); - current_inferior ()->terminal = terminal_name ? xstrdup (terminal_name) : 0; + + if (terminal_name != NULL && *terminal_name != '\0') + current_inferior ()->terminal = xstrdup (terminal_name); + else + current_inferior ()->terminal = NULL; } const char * @@ -241,6 +240,60 @@ show_args_command (struct ui_file *file, int from_tty, deprecated_show_value_hack (file, from_tty, c, get_inferior_args ()); } +/* See common/common-inferior.h. */ + +void +set_inferior_cwd (const char *cwd) +{ + struct inferior *inf = current_inferior (); + + gdb_assert (inf != NULL); + + if (cwd == NULL) + inf->cwd.reset (); + else + inf->cwd.reset (xstrdup (cwd)); +} + +/* See common/common-inferior.h. */ + +const char * +get_inferior_cwd () +{ + return current_inferior ()->cwd.get (); +} + +/* Handle the 'set cwd' command. */ + +static void +set_cwd_command (char *args, int from_tty, struct cmd_list_element *c) +{ + if (*inferior_cwd_scratch == '\0') + set_inferior_cwd (NULL); + else + set_inferior_cwd (inferior_cwd_scratch); +} + +/* Handle the 'show cwd' command. */ + +static void +show_cwd_command (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + const char *cwd = get_inferior_cwd (); + + if (cwd == NULL) + fprintf_filtered (gdb_stdout, + _("\ +You have not set the inferior's current working directory.\n\ +The inferior will inherit GDB's cwd if native debugging, or the remote\n\ +server's cwd if remote debugging.\n")); + else + fprintf_filtered (gdb_stdout, + _("Current working directory that will be used " + "when starting the inferior is \"%s\".\n"), cwd); +} + /* Compute command-line string given argument vector. This does the same shell processing as fork_inferior. */ @@ -255,14 +308,14 @@ construct_inferior_arguments (int argc, char **argv) #ifdef __MINGW32__ /* This holds all the characters considered special to the Windows shells. */ - char *special = "\"!&*|[]{}<>?`~^=;, \t\n"; - const char quote = '"'; + static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n"; + static const char quote = '"'; #else /* This holds all the characters considered special to the typical Unix shells. We include `^' because the SunOS /bin/sh treats it as a synonym for `|'. */ - char *special = "\"!#$&*()\\|[]{}<>?'`~^; \t\n"; - const char quote = '\''; + static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n"; + static const char quote = '\''; #endif int i; int length = 0; @@ -406,7 +459,7 @@ post_create_inferior (struct target_ops *target, int from_tty) { /* Be sure we own the terminal in case write operations are performed. */ - target_terminal_ours (); + target_terminal::ours_for_output (); /* If the target hasn't taken care of this already, do it now. Targets which need to access registers during to_open, @@ -452,7 +505,7 @@ post_create_inferior (struct target_ops *target, int from_tty) /* If the solist is global across processes, there's no need to refetch it here. */ if (!gdbarch_has_global_solist (target_gdbarch ())) - solib_add (NULL, 0, target, auto_solib_add); + solib_add (NULL, 0, auto_solib_add); } } @@ -509,24 +562,38 @@ prepare_execution_command (struct target_ops *target, int background) simulate synchronous (fg) execution. Note no cleanup is necessary for this. stdin is re-enabled whenever an error reaches the top level. */ - async_disable_stdin (); + all_uis_on_sync_execution_starting (); } } -/* Implement the "run" command. If TBREAK_AT_MAIN is set, then insert - a temporary breakpoint at the begining of the main program before - running the program. */ +/* Determine how the new inferior will behave. */ + +enum run_how + { + /* Run program without any explicit stop during startup. */ + RUN_NORMAL, + + /* Stop at the beginning of the program's main function. */ + RUN_STOP_AT_MAIN, + + /* Stop at the first instruction of the program. */ + RUN_STOP_AT_FIRST_INSN + }; + +/* Implement the "run" command. Force a stop during program start if + requested by RUN_HOW. */ static void -run_command_1 (char *args, int from_tty, int tbreak_at_main) +run_command_1 (char *args, int from_tty, enum run_how run_how) { - char *exec_file; + const char *exec_file; struct cleanup *old_chain; ptid_t ptid; struct ui_out *uiout = current_uiout; struct target_ops *run_target; int async_exec; struct cleanup *args_chain; + CORE_ADDR pc; dont_repeat (); @@ -564,11 +631,11 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) /* Done. Can now set breakpoints, change inferior args, etc. */ - /* Insert the temporary breakpoint if a location was specified. */ - if (tbreak_at_main) + /* Insert temporary breakpoint in main function if requested. */ + if (run_how == RUN_STOP_AT_MAIN) tbreak_command (main_name (), 0); - exec_file = (char *) get_exec_file (0); + exec_file = get_exec_file (0); /* We keep symbols from add-symbol-file, on the grounds that the user might want to add some symbols before running the program @@ -584,16 +651,16 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) if (from_tty) { - ui_out_field_string (uiout, NULL, "Starting program"); - ui_out_text (uiout, ": "); + uiout->field_string (NULL, "Starting program"); + uiout->text (": "); if (exec_file) - ui_out_field_string (uiout, "execfile", exec_file); - ui_out_spaces (uiout, 1); + uiout->field_string ("execfile", exec_file); + uiout->spaces (1); /* We call get_inferior_args() because we might need to compute the value now. */ - ui_out_field_string (uiout, "infargs", get_inferior_args ()); - ui_out_text (uiout, "\n"); - ui_out_flush (uiout); + uiout->field_string ("infargs", get_inferior_args ()); + uiout->text ("\n"); + uiout->flush (); } /* Done with ARGS. */ @@ -601,8 +668,9 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) /* We call get_inferior_args() because we might need to compute the value now. */ - run_target->to_create_inferior (run_target, exec_file, get_inferior_args (), - environ_vector (current_inferior ()->environment), + run_target->to_create_inferior (run_target, exec_file, + std::string (get_inferior_args ()), + current_inferior ()->environment.envp (), from_tty); /* to_create_inferior should push the target, so after this point we shouldn't refer to run_target again. */ @@ -624,6 +692,15 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) has done its thing; now we are setting up the running program. */ post_create_inferior (¤t_target, 0); + /* Queue a pending event so that the program stops immediately. */ + if (run_how == RUN_STOP_AT_FIRST_INSN) + { + thread_info *thr = inferior_thread (); + thr->suspend.waitstatus_pending_p = 1; + thr->suspend.waitstatus.kind = TARGET_WAITKIND_STOPPED; + thr->suspend.waitstatus.value.sig = GDB_SIGNAL_0; + } + /* Start the target running. Do not use -1 continuation as it would skip breakpoint right at the entry point. */ proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0); @@ -636,7 +713,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) static void run_command (char *args, int from_tty) { - run_command_1 (args, from_tty, 0); + run_command_1 (args, from_tty, RUN_NORMAL); } /* Start the execution of the program up until the beginning of the main @@ -652,7 +729,16 @@ start_command (char *args, int from_tty) error (_("No symbol table loaded. Use the \"file\" command.")); /* Run the program until reaching the main procedure... */ - run_command_1 (args, from_tty, 1); + run_command_1 (args, from_tty, RUN_STOP_AT_MAIN); +} + +/* Start the execution of the program stopping at the first + instruction. */ + +static void +starti_command (char *args, int from_tty) +{ + run_command_1 (args, from_tty, RUN_STOP_AT_FIRST_INSN); } static int @@ -723,14 +809,14 @@ continue_1 (int all_threads) { /* Don't error out if the current thread is running, because there may be other stopped threads. */ - struct cleanup *old_chain; - /* Backup current thread and selected frame. */ - old_chain = make_cleanup_restore_current_thread (); + /* Backup current thread and selected frame and restore on scope + exit. */ + scoped_restore_current_thread restore_thread; iterate_over_threads (proceed_thread_callback, NULL); - if (sync_execution) + if (current_ui->prompt_state == PROMPT_BLOCKED) { /* If all threads in the target were already running, proceed_thread_callback ends up never calling proceed, @@ -745,11 +831,8 @@ continue_1 (int all_threads) Continuing. */ - target_terminal_inferior (); + target_terminal::inferior (); } - - /* Restore selected ptid. */ - do_cleanups (old_chain); } else { @@ -775,8 +858,6 @@ continue_command (char *args, int from_tty) args = strip_bg_char (args, &async_exec); args_chain = make_cleanup (xfree, args); - prepare_execution_command (¤t_target, async_exec); - if (args != NULL) { if (startswith (args, "-a")) @@ -840,6 +921,17 @@ continue_command (char *args, int from_tty) /* Done with ARGS. */ do_cleanups (args_chain); + ERROR_NO_INFERIOR; + ensure_not_tfind_mode (); + + if (!non_stop || !all_threads) + { + ensure_valid_thread (); + ensure_not_running (); + } + + prepare_execution_command (¤t_target, async_exec); + if (from_tty) printf_filtered (_("Continuing.\n")); @@ -851,14 +943,13 @@ continue_command (char *args, int from_tty) static void set_step_frame (void) { - struct symtab_and_line sal; - CORE_ADDR pc; - struct frame_info *frame = get_current_frame (); - struct thread_info *tp = inferior_thread (); + frame_info *frame = get_current_frame (); - find_frame_sal (frame, &sal); + symtab_and_line sal = find_frame_sal (frame); set_step_info (frame, sal); - pc = get_frame_pc (frame); + + CORE_ADDR pc = get_frame_pc (frame); + thread_info *tp = inferior_thread (); tp->control.step_start_function = find_pc_function (pc); } @@ -915,13 +1006,12 @@ struct step_command_fsm /* If true, this is a stepi/nexti, otherwise a step/step. */ int single_inst; - - /* The thread that the command was run on. */ - int thread; }; -static void step_command_fsm_clean_up (struct thread_fsm *self); -static int step_command_fsm_should_stop (struct thread_fsm *self); +static void step_command_fsm_clean_up (struct thread_fsm *self, + struct thread_info *thread); +static int step_command_fsm_should_stop (struct thread_fsm *self, + struct thread_info *thread); static enum async_reply_reason step_command_fsm_async_reply_reason (struct thread_fsm *self); @@ -939,12 +1029,12 @@ static struct thread_fsm_ops step_command_fsm_ops = /* Allocate a new step_command_fsm. */ static struct step_command_fsm * -new_step_command_fsm (void) +new_step_command_fsm (struct interp *cmd_interp) { struct step_command_fsm *sm; sm = XCNEW (struct step_command_fsm); - thread_fsm_ctor (&sm->thread_fsm, &step_command_fsm_ops); + thread_fsm_ctor (&sm->thread_fsm, &step_command_fsm_ops, cmd_interp); return sm; } @@ -960,7 +1050,6 @@ step_command_fsm_prepare (struct step_command_fsm *sm, sm->skip_subroutines = skip_subroutines; sm->single_inst = single_inst; sm->count = count; - sm->thread = thread->global_num; /* Leave the si command alone. */ if (!sm->single_inst || sm->skip_subroutines) @@ -1000,7 +1089,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) /* Setup the execution command state machine to handle all the COUNT steps. */ thr = inferior_thread (); - step_sm = new_step_command_fsm (); + step_sm = new_step_command_fsm (command_interp ()); thr->thread_fsm = &step_sm->thread_fsm; step_command_fsm_prepare (step_sm, skip_subroutines, @@ -1014,11 +1103,15 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); else { + int proceeded; + /* Stepped into an inline frame. Pretend that we've stopped. */ - thread_fsm_clean_up (thr->thread_fsm); - normal_stop (); - inferior_event_handler (INF_EXEC_COMPLETE, NULL); + thread_fsm_clean_up (thr->thread_fsm, thr); + proceeded = normal_stop (); + if (!proceeded) + inferior_event_handler (INF_EXEC_COMPLETE, NULL); + all_uis_check_sync_execution_done (); } } @@ -1029,10 +1122,9 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) will need to keep going. */ static int -step_command_fsm_should_stop (struct thread_fsm *self) +step_command_fsm_should_stop (struct thread_fsm *self, struct thread_info *tp) { struct step_command_fsm *sm = (struct step_command_fsm *) self; - struct thread_info *tp = find_thread_global_id (sm->thread); if (tp->control.stop_step) { @@ -1050,12 +1142,12 @@ step_command_fsm_should_stop (struct thread_fsm *self) /* Implementation of the 'clean_up' FSM method for stepping commands. */ static void -step_command_fsm_clean_up (struct thread_fsm *self) +step_command_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread) { struct step_command_fsm *sm = (struct step_command_fsm *) self; if (!sm->single_inst || sm->skip_subroutines) - delete_longjmp_breakpoint (sm->thread); + delete_longjmp_breakpoint (thread->global_num); } /* Implementation of the 'async_reply_reason' FSM method for stepping @@ -1128,7 +1220,7 @@ prepare_one_step (struct step_command_fsm *sm) &tp->control.step_range_end) == 0) error (_("Cannot find bounds of current function")); - target_terminal_ours (); + target_terminal::ours_for_output (); printf_filtered (_("Single stepping until exit from function %s," "\nwhich has no line number information.\n"), name); @@ -1164,8 +1256,6 @@ jump_command (char *arg, int from_tty) { struct gdbarch *gdbarch = get_current_arch (); CORE_ADDR addr; - struct symtabs_and_lines sals; - struct symtab_and_line sal; struct symbol *fn; struct symbol *sfn; int async_exec; @@ -1185,18 +1275,16 @@ jump_command (char *arg, int from_tty) if (!arg) error_no_arg (_("starting address")); - sals = decode_line_with_last_displayed (arg, DECODE_LINE_FUNFIRSTLINE); - if (sals.nelts != 1) - { - error (_("Unreasonable jump request")); - } - - sal = sals.sals[0]; - xfree (sals.sals); + std::vector sals + = decode_line_with_last_displayed (arg, DECODE_LINE_FUNFIRSTLINE); + if (sals.size () != 1) + error (_("Unreasonable jump request")); /* Done with ARGS. */ do_cleanups (args_chain); + symtab_and_line &sal = sals[0]; + if (sal.symtab == 0 && sal.pc == 0) error (_("No source file has been specified.")); @@ -1397,8 +1485,10 @@ struct until_next_fsm int thread; }; -static int until_next_fsm_should_stop (struct thread_fsm *self); -static void until_next_fsm_clean_up (struct thread_fsm *self); +static int until_next_fsm_should_stop (struct thread_fsm *self, + struct thread_info *thread); +static void until_next_fsm_clean_up (struct thread_fsm *self, + struct thread_info *thread); static enum async_reply_reason until_next_fsm_async_reply_reason (struct thread_fsm *self); @@ -1416,12 +1506,12 @@ static struct thread_fsm_ops until_next_fsm_ops = /* Allocate a new until_next_fsm. */ static struct until_next_fsm * -new_until_next_fsm (int thread) +new_until_next_fsm (struct interp *cmd_interp, int thread) { struct until_next_fsm *sm; sm = XCNEW (struct until_next_fsm); - thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops); + thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops, cmd_interp); sm->thread = thread; @@ -1432,10 +1522,9 @@ new_until_next_fsm (int thread) no arg) command. */ static int -until_next_fsm_should_stop (struct thread_fsm *self) +until_next_fsm_should_stop (struct thread_fsm *self, + struct thread_info *tp) { - struct thread_info *tp = inferior_thread (); - if (tp->control.stop_step) thread_fsm_set_finished (self); @@ -1446,11 +1535,11 @@ until_next_fsm_should_stop (struct thread_fsm *self) arg) command. */ static void -until_next_fsm_clean_up (struct thread_fsm *self) +until_next_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread) { struct until_next_fsm *sm = (struct until_next_fsm *) self; - delete_longjmp_breakpoint (sm->thread); + delete_longjmp_breakpoint (thread->global_num); } /* Implementation of the 'async_reply_reason' FSM method for the until @@ -1520,7 +1609,7 @@ until_next_command (int from_tty) set_longjmp_breakpoint (tp, get_frame_id (frame)); old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread); - sm = new_until_next_fsm (tp->global_num); + sm = new_until_next_fsm (command_interp (), tp->global_num); tp->thread_fsm = &sm->thread_fsm; discard_cleanups (old_chain); @@ -1586,15 +1675,9 @@ advance_command (char *arg, int from_tty) struct value * get_return_value (struct value *function, struct type *value_type) { - struct regcache *stop_regs; - struct gdbarch *gdbarch; + regcache stop_regs (regcache::readonly, *get_current_regcache ()); + struct gdbarch *gdbarch = stop_regs.arch (); struct value *value; - struct cleanup *cleanup; - - stop_regs = regcache_dup (get_current_regcache ()); - cleanup = make_cleanup_regcache_xfree (stop_regs); - - gdbarch = get_regcache_arch (stop_regs); value_type = check_typedef (value_type); gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID); @@ -1613,7 +1696,7 @@ get_return_value (struct value *function, struct type *value_type) case RETURN_VALUE_ABI_RETURNS_ADDRESS: case RETURN_VALUE_ABI_PRESERVES_ADDRESS: value = allocate_value (value_type); - gdbarch_return_value (gdbarch, function, value_type, stop_regs, + gdbarch_return_value (gdbarch, function, value_type, &stop_regs, value_contents_raw (value), NULL); break; case RETURN_VALUE_STRUCT_CONVENTION: @@ -1623,8 +1706,6 @@ get_return_value (struct value *function, struct type *value_type) internal_error (__FILE__, __LINE__, _("bad switch")); } - do_cleanups (cleanup); - return value; } @@ -1653,34 +1734,27 @@ print_return_value_1 (struct ui_out *uiout, struct return_value_info *rv) if (rv->value != NULL) { struct value_print_options opts; - struct ui_file *stb; - struct cleanup *old_chain; /* Print it. */ - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); - ui_out_text (uiout, "Value returned is "); - ui_out_field_fmt (uiout, "gdb-result-var", "$%d", - rv->value_history_index); - ui_out_text (uiout, " = "); + uiout->text ("Value returned is "); + uiout->field_fmt ("gdb-result-var", "$%d", + rv->value_history_index); + uiout->text (" = "); get_no_prettyformat_print_options (&opts); - value_print (rv->value, stb, &opts); - ui_out_field_stream (uiout, "return-value", stb); - ui_out_text (uiout, "\n"); - do_cleanups (old_chain); + + string_file stb; + + value_print (rv->value, &stb, &opts); + uiout->field_stream ("return-value", stb); + uiout->text ("\n"); } else { - struct cleanup *oldchain; - char *type_name; - - type_name = type_to_string (rv->type); - oldchain = make_cleanup (xfree, type_name); - ui_out_text (uiout, "Value returned has type: "); - ui_out_field_string (uiout, "return-type", type_name); - ui_out_text (uiout, "."); - ui_out_text (uiout, " Cannot determine contents\n"); - do_cleanups (oldchain); + std::string type_name = type_to_string (rv->type); + uiout->text ("Value returned has type: "); + uiout->field_string ("return-type", type_name.c_str ()); + uiout->text ("."); + uiout->text (" Cannot determine contents\n"); } } @@ -1715,9 +1789,6 @@ struct finish_command_fsm /* The base class. */ struct thread_fsm thread_fsm; - /* The thread that was current when the command was executed. */ - int thread; - /* The momentary breakpoint set at the function's return address in the caller. */ struct breakpoint *breakpoint; @@ -1730,8 +1801,10 @@ struct finish_command_fsm struct return_value_info return_value; }; -static int finish_command_fsm_should_stop (struct thread_fsm *self); -static void finish_command_fsm_clean_up (struct thread_fsm *self); +static int finish_command_fsm_should_stop (struct thread_fsm *self, + struct thread_info *thread); +static void finish_command_fsm_clean_up (struct thread_fsm *self, + struct thread_info *thread); static struct return_value_info * finish_command_fsm_return_value (struct thread_fsm *self); static enum async_reply_reason @@ -1746,19 +1819,18 @@ static struct thread_fsm_ops finish_command_fsm_ops = finish_command_fsm_should_stop, finish_command_fsm_return_value, finish_command_fsm_async_reply_reason, + NULL, /* should_notify_stop */ }; /* Allocate a new finish_command_fsm. */ static struct finish_command_fsm * -new_finish_command_fsm (int thread) +new_finish_command_fsm (struct interp *cmd_interp) { struct finish_command_fsm *sm; sm = XCNEW (struct finish_command_fsm); - thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops); - - sm->thread = thread; + thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops, cmd_interp); return sm; } @@ -1769,11 +1841,11 @@ new_finish_command_fsm (int thread) marks the FSM finished. */ static int -finish_command_fsm_should_stop (struct thread_fsm *self) +finish_command_fsm_should_stop (struct thread_fsm *self, + struct thread_info *tp) { struct finish_command_fsm *f = (struct finish_command_fsm *) self; struct return_value_info *rv = &f->return_value; - struct thread_info *tp = find_thread_global_id (f->thread); if (f->function != NULL && bpstat_find_breakpoint (tp->control.stop_bpstat, @@ -1811,7 +1883,8 @@ finish_command_fsm_should_stop (struct thread_fsm *self) commands. */ static void -finish_command_fsm_clean_up (struct thread_fsm *self) +finish_command_fsm_clean_up (struct thread_fsm *self, + struct thread_info *thread) { struct finish_command_fsm *f = (struct finish_command_fsm *) self; @@ -1820,7 +1893,7 @@ finish_command_fsm_clean_up (struct thread_fsm *self) delete_breakpoint (f->breakpoint); f->breakpoint = NULL; } - delete_longjmp_breakpoint (f->thread); + delete_longjmp_breakpoint (thread->global_num); } /* Implementation of the 'return_value' FSM method for the finish @@ -1840,8 +1913,6 @@ finish_command_fsm_return_value (struct thread_fsm *self) static enum async_reply_reason finish_command_fsm_async_reply_reason (struct thread_fsm *self) { - struct finish_command_fsm *f = (struct finish_command_fsm *) self; - if (execution_direction == EXEC_REVERSE) return EXEC_ASYNC_END_STEPPING_RANGE; else @@ -1879,11 +1950,10 @@ finish_backward (struct finish_command_fsm *sm) { struct frame_info *frame = get_selected_frame (NULL); struct gdbarch *gdbarch = get_frame_arch (frame); - struct symtab_and_line sr_sal; /* Set a step-resume at the function's entry point. Once that's hit, we'll do one more step backwards. */ - init_sal (&sr_sal); + symtab_and_line sr_sal; sr_sal.pc = sal.pc; sr_sal.pspace = get_frame_program_space (frame); insert_step_resume_breakpoint_at_sal (gdbarch, @@ -1916,7 +1986,7 @@ finish_forward (struct finish_command_fsm *sm, struct frame_info *frame) sm->breakpoint = set_momentary_breakpoint (gdbarch, sal, get_stack_frame_id (frame), - bp_finish); + bp_finish).release (); /* set_momentary_breakpoint invalidates FRAME. */ frame = NULL; @@ -1929,6 +1999,30 @@ finish_forward (struct finish_command_fsm *sm, struct frame_info *frame) proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); } +/* Skip frames for "finish". */ + +static struct frame_info * +skip_finish_frames (struct frame_info *frame) +{ + struct frame_info *start; + + do + { + start = frame; + + frame = skip_tailcall_frames (frame); + if (frame == NULL) + break; + + frame = skip_unwritable_frames (frame); + if (frame == NULL) + break; + } + while (start != frame); + + return frame; +} + /* "finish": Set a temporary breakpoint at the place the selected frame will return to, then continue. */ @@ -1966,7 +2060,7 @@ finish_command (char *arg, int from_tty) tp = inferior_thread (); - sm = new_finish_command_fsm (tp->global_num); + sm = new_finish_command_fsm (command_interp ()); tp->thread_fsm = &sm->thread_fsm; @@ -1980,10 +2074,7 @@ finish_command (char *arg, int from_tty) called by that frame. We don't use the magic "1" value for step_range_end, because then infrun will think this is nexti, and not step over the rest of this inlined function call. */ - struct symtab_and_line empty_sal; - - init_sal (&empty_sal); - set_step_info (frame, empty_sal); + set_step_info (frame, {}); tp->control.step_range_start = get_frame_pc (frame); tp->control.step_range_end = tp->control.step_range_start; tp->control.step_over_calls = STEP_OVER_ALL; @@ -2027,9 +2118,7 @@ finish_command (char *arg, int from_tty) finish_backward (sm); else { - /* Ignore TAILCALL_FRAME type frames, they were executed already before - entering THISFRAME. */ - frame = skip_tailcall_frames (frame); + frame = skip_finish_frames (frame); if (frame == NULL) error (_("Cannot find the caller frame.")); @@ -2040,7 +2129,7 @@ finish_command (char *arg, int from_tty) static void -program_info (char *args, int from_tty) +info_program_command (char *args, int from_tty) { bpstat bs; int num, stat; @@ -2107,11 +2196,11 @@ program_info (char *args, int from_tty) } static void -environment_info (char *var, int from_tty) +environment_info (const char *var, int from_tty) { if (var) { - char *val = get_in_environ (current_inferior ()->environment, var); + const char *val = current_inferior ()->environment.get (var); if (val) { @@ -2129,20 +2218,20 @@ environment_info (char *var, int from_tty) } else { - char **vector = environ_vector (current_inferior ()->environment); + char **envp = current_inferior ()->environment.envp (); - while (*vector) + for (int idx = 0; envp[idx] != NULL; ++idx) { - puts_filtered (*vector++); + puts_filtered (envp[idx]); puts_filtered ("\n"); } } } static void -set_environment_command (char *arg, int from_tty) +set_environment_command (const char *arg, int from_tty) { - char *p, *val, *var; + const char *p, *val; int nullset = 0; if (arg == 0) @@ -2189,34 +2278,30 @@ set_environment_command (char *arg, int from_tty) while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--; - var = savestring (arg, p - arg); + std::string var (arg, p - arg); if (nullset) { printf_filtered (_("Setting environment variable " "\"%s\" to null value.\n"), - var); - set_in_environ (current_inferior ()->environment, var, ""); + var.c_str ()); + current_inferior ()->environment.set (var.c_str (), ""); } else - set_in_environ (current_inferior ()->environment, var, val); - xfree (var); + current_inferior ()->environment.set (var.c_str (), val); } static void -unset_environment_command (char *var, int from_tty) +unset_environment_command (const char *var, int from_tty) { if (var == 0) { /* If there is no argument, delete all environment variables. Ask for confirmation if reading from the terminal. */ if (!from_tty || query (_("Delete all environment variables? "))) - { - free_environ (current_inferior ()->environment); - current_inferior ()->environment = make_environ (); - } + current_inferior ()->environment.clear (); } else - unset_in_environ (current_inferior ()->environment, var); + current_inferior ()->environment.unset (var); } /* Handle the execution path (PATH variable). */ @@ -2224,11 +2309,10 @@ unset_environment_command (char *var, int from_tty) static const char path_var_name[] = "PATH"; static void -path_info (char *args, int from_tty) +path_info (const char *args, int from_tty) { puts_filtered ("Executable and object file path: "); - puts_filtered (get_in_environ (current_inferior ()->environment, - path_var_name)); + puts_filtered (current_inferior ()->environment.get (path_var_name)); puts_filtered ("\n"); } @@ -2238,16 +2322,16 @@ static void path_command (char *dirname, int from_tty) { char *exec_path; - char *env; + const char *env; dont_repeat (); - env = get_in_environ (current_inferior ()->environment, path_var_name); + env = current_inferior ()->environment.get (path_var_name); /* Can be null if path is not set. */ if (!env) env = ""; exec_path = xstrdup (env); mod_path (dirname, &exec_path); - set_in_environ (current_inferior ()->environment, path_var_name, exec_path); + current_inferior ()->environment.set (path_var_name, exec_path); xfree (exec_path); if (from_tty) path_info ((char *) NULL, from_tty); @@ -2276,7 +2360,6 @@ default_print_one_register_info (struct ui_file *file, if (TYPE_CODE (regtype) == TYPE_CODE_FLT || TYPE_CODE (regtype) == TYPE_CODE_DECFLOAT) { - int j; struct value_print_options opts; const gdb_byte *valaddr = value_contents_for_printing (val); enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype)); @@ -2285,14 +2368,14 @@ default_print_one_register_info (struct ui_file *file, opts.deref_ref = 1; val_print (regtype, - value_contents_for_printing (val), value_embedded_offset (val), 0, file, 0, val, &opts, current_language); if (print_raw_format) { fprintf_filtered (file, "\t(raw "); - print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order); + print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order, + true); fprintf_filtered (file, ")"); } } @@ -2304,7 +2387,6 @@ default_print_one_register_info (struct ui_file *file, get_formatted_print_options (&opts, 'x'); opts.deref_ref = 1; val_print (regtype, - value_contents_for_printing (val), value_embedded_offset (val), 0, file, 0, val, &opts, current_language); /* If not a vector register, print it also according to its @@ -2315,7 +2397,6 @@ default_print_one_register_info (struct ui_file *file, opts.deref_ref = 1; fprintf_filtered (file, "\t"); val_print (regtype, - value_contents_for_printing (val), value_embedded_offset (val), 0, file, 0, val, &opts, current_language); } @@ -2489,13 +2570,13 @@ registers_info (char *addr_exp, int fpregs) } static void -all_registers_info (char *addr_exp, int from_tty) +info_all_registers_command (char *addr_exp, int from_tty) { registers_info (addr_exp, 1); } static void -nofp_registers_info (char *addr_exp, int from_tty) +info_registers_command (char *addr_exp, int from_tty) { registers_info (addr_exp, 0); } @@ -2530,7 +2611,7 @@ print_vector_info (struct ui_file *file, } static void -vector_info (char *args, int from_tty) +info_vector_command (char *args, int from_tty) { if (!target_has_registers) error (_("The program has no registers now.")); @@ -2541,7 +2622,7 @@ vector_info (char *args, int from_tty) /* Kill the inferior process. Make us have no inferior. */ static void -kill_command (char *arg, int from_tty) +kill_command (const char *arg, int from_tty) { /* FIXME: This should not really be inferior_ptid (or target_has_execution). It should be a distinct flag that indicates that a target is active, cuz @@ -2601,15 +2682,11 @@ proceed_after_attach (int pid) { /* Don't error out if the current thread is running, because there may be other stopped threads. */ - struct cleanup *old_chain; /* Backup current thread and selected frame. */ - old_chain = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; iterate_over_threads (proceed_after_attach_callback, &pid); - - /* Restore selected ptid. */ - do_cleanups (old_chain); } /* See inferior.h. */ @@ -2625,7 +2702,7 @@ setup_inferior (int from_tty) /* If no exec file is yet known, try to determine it from the process itself. */ if (get_exec_file (0) == NULL) - exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty); + exec_file_locate_attach (ptid_get_pid (inferior_ptid), 1, from_tty); else { reopen_exec_file (); @@ -2656,7 +2733,7 @@ enum attach_post_wait_mode should be running. Else if ATTACH, */ static void -attach_post_wait (char *args, int from_tty, enum attach_post_wait_mode mode) +attach_post_wait (const char *args, int from_tty, enum attach_post_wait_mode mode) { struct inferior *inferior; @@ -2691,8 +2768,6 @@ attach_post_wait (char *args, int from_tty, enum attach_post_wait_mode mode) /* The user requested a plain `attach', so be sure to leave the inferior stopped. */ - async_enable_stdin (); - /* At least the current thread is already stopped. */ /* In all-stop, by definition, all threads have to be already @@ -2811,7 +2886,7 @@ attach_command (char *args, int from_tty) /* Set up the "saved terminal modes" of the inferior based on what modes we are starting it with. */ - target_terminal_init (); + target_terminal::init (); /* Install inferior's terminal modes. This may look like a no-op, as we've just saved them above, however, this does more than @@ -2827,7 +2902,7 @@ attach_command (char *args, int from_tty) while we're in the event loop waiting for that stop. That is, before the attach continuation runs and the command is really finished. */ - target_terminal_inferior (); + target_terminal::inferior (); /* Set up execution context to know that we should return from wait_for_inferior as soon as the target reports a stop. */ @@ -2866,7 +2941,7 @@ attach_command (char *args, int from_tty) STOP_QUIETLY_NO_SIGSTOP is for. */ inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP; - /* sync_execution mode. Wait for stop. */ + /* Wait for stop. */ a = XNEW (struct attach_command_continuation_args); a->args = xstrdup (args); a->from_tty = from_tty; @@ -2898,19 +2973,13 @@ attach_command (char *args, int from_tty) void notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) { - struct cleanup* old_chain; - enum attach_post_wait_mode mode; + enum attach_post_wait_mode mode + = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING; - old_chain = make_cleanup (null_cleanup, NULL); + gdb::optional restore_thread; - /* If in non-stop, leave threads as running as they were. If - they're stopped for some reason other than us telling it to, the - target reports a signal != GDB_SIGNAL_0. We don't try to - resume threads with such a stop signal. */ - mode = non_stop ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING; - - if (!ptid_equal (inferior_ptid, null_ptid)) - make_cleanup_restore_current_thread (); + if (inferior_ptid != null_ptid) + restore_thread.emplace (); /* Avoid reading registers -- we haven't fetched the target description yet. */ @@ -2939,14 +3008,10 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) add_inferior_continuation (attach_command_continuation, a, attach_command_continuation_free_args); - do_cleanups (old_chain); return; } - mode = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING; attach_post_wait ("" /* args */, from_tty, mode); - - do_cleanups (old_chain); } /* @@ -2961,7 +3026,7 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) */ void -detach_command (char *args, int from_tty) +detach_command (const char *args, int from_tty) { dont_repeat (); /* Not for the faint of heart. */ @@ -2974,6 +3039,13 @@ detach_command (char *args, int from_tty) target_detach (args, from_tty); + /* The current inferior process was just detached successfully. Get + rid of breakpoints that no longer make sense. Note we don't do + this within target_detach because that is also used when + following child forks, and in that case we will want to transfer + breakpoints to the child, not delete them. */ + breakpoint_init_inferior (inf_exited); + /* If the solist is global across inferiors, don't clear it when we detach from a single inferior. */ if (!gdbarch_has_global_solist (target_gdbarch ())) @@ -3018,7 +3090,11 @@ interrupt_target_1 (int all_threads) ptid = minus_one_ptid; else ptid = inferior_ptid; - target_interrupt (ptid); + + if (non_stop) + target_stop (ptid); + else + target_interrupt (ptid); /* Tag the thread as having been explicitly requested to stop, so other parts of gdb know not to resume this thread automatically, @@ -3032,7 +3108,7 @@ interrupt_target_1 (int all_threads) /* interrupt [-a] Stop the execution of the target while running in async mode, in - the backgound. In all-stop, stop the whole process. In non-stop + the background. In all-stop, stop the whole process. In non-stop mode, stop the current thread only by default, or stop all threads if the `-a' switch is used. */ @@ -3082,7 +3158,7 @@ default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, } static void -float_info (char *args, int from_tty) +info_float_command (char *args, int from_tty) { struct frame_info *frame; @@ -3094,7 +3170,7 @@ float_info (char *args, int from_tty) } static void -unset_command (char *args, int from_tty) +unset_command (const char *args, int from_tty) { printf_filtered (_("\"unset\" must be followed by the " "name of an unset subcommand.\n")); @@ -3104,7 +3180,7 @@ unset_command (char *args, int from_tty) /* Implement `info proc' family of commands. */ static void -info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) +info_proc_cmd_1 (const char *args, enum info_proc_what what, int from_tty) { struct gdbarch *gdbarch = get_current_arch (); @@ -3120,7 +3196,7 @@ info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) /* Implement `info proc' when given without any futher parameters. */ static void -info_proc_cmd (char *args, int from_tty) +info_proc_cmd (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_MINIMAL, from_tty); } @@ -3128,7 +3204,7 @@ info_proc_cmd (char *args, int from_tty) /* Implement `info proc mappings'. */ static void -info_proc_cmd_mappings (char *args, int from_tty) +info_proc_cmd_mappings (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_MAPPINGS, from_tty); } @@ -3136,7 +3212,7 @@ info_proc_cmd_mappings (char *args, int from_tty) /* Implement `info proc stat'. */ static void -info_proc_cmd_stat (char *args, int from_tty) +info_proc_cmd_stat (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_STAT, from_tty); } @@ -3144,7 +3220,7 @@ info_proc_cmd_stat (char *args, int from_tty) /* Implement `info proc status'. */ static void -info_proc_cmd_status (char *args, int from_tty) +info_proc_cmd_status (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_STATUS, from_tty); } @@ -3152,7 +3228,7 @@ info_proc_cmd_status (char *args, int from_tty) /* Implement `info proc cwd'. */ static void -info_proc_cmd_cwd (char *args, int from_tty) +info_proc_cmd_cwd (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_CWD, from_tty); } @@ -3160,7 +3236,7 @@ info_proc_cmd_cwd (char *args, int from_tty) /* Implement `info proc cmdline'. */ static void -info_proc_cmd_cmdline (char *args, int from_tty) +info_proc_cmd_cmdline (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_CMDLINE, from_tty); } @@ -3168,7 +3244,7 @@ info_proc_cmd_cmdline (char *args, int from_tty) /* Implement `info proc exe'. */ static void -info_proc_cmd_exe (char *args, int from_tty) +info_proc_cmd_exe (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_EXE, from_tty); } @@ -3176,11 +3252,27 @@ info_proc_cmd_exe (char *args, int from_tty) /* Implement `info proc all'. */ static void -info_proc_cmd_all (char *args, int from_tty) +info_proc_cmd_all (const char *args, int from_tty) { info_proc_cmd_1 (args, IP_ALL, from_tty); } +/* This help string is used for the run, start, and starti commands. + It is defined as a macro to prevent duplication. */ + +#define RUN_ARGS_HELP \ +"You may specify arguments to give it.\n\ +Args may include \"*\", or \"[...]\"; they are expanded using the\n\ +shell that will start the program (specified by the \"$SHELL\" environment\n\ +variable). Input and output redirection with \">\", \"<\", or \">>\"\n\ +are also allowed.\n\ +\n\ +With no arguments, uses arguments last specified (with \"run\" or \n\ +\"set args\"). To cancel previous arguments and run with no arguments,\n\ +use \"set args\" without arguments.\n\ +\n\ +To start the inferior without using a shell, use \"set startup-with-shell off\"." + void _initialize_infcmd (void) { @@ -3189,15 +3281,20 @@ _initialize_infcmd (void) const char *cmd_name; /* Add the filename of the terminal connected to inferior I/O. */ - add_setshow_filename_cmd ("inferior-tty", class_run, - &inferior_io_terminal_scratch, _("\ + add_setshow_optional_filename_cmd ("inferior-tty", class_run, + &inferior_io_terminal_scratch, _("\ Set terminal for future runs of program being debugged."), _("\ Show terminal for future runs of program being debugged."), _("\ -Usage: set inferior-tty /dev/pts/1"), - set_inferior_tty_command, - show_inferior_tty_command, - &setlist, &showlist); - add_com_alias ("tty", "set inferior-tty", class_alias, 0); +Usage: set inferior-tty [TTY]\n\n\ +If TTY is omitted, the default behavior of using the same terminal as GDB\n\ +is restored."), + set_inferior_tty_command, + show_inferior_tty_command, + &setlist, &showlist); + cmd_name = "inferior-tty"; + c = lookup_cmd (&cmd_name, setlist, "", -1, 1); + gdb_assert (c != NULL); + add_alias_cmd ("tty", c, class_alias, 0, &cmdlist); cmd_name = "args"; add_setshow_string_noescape_cmd (cmd_name, class_run, @@ -3212,6 +3309,25 @@ Follow this command with any number of args, to be passed to the program."), gdb_assert (c != NULL); set_cmd_completer (c, filename_completer); + cmd_name = "cwd"; + add_setshow_string_noescape_cmd (cmd_name, class_run, + &inferior_cwd_scratch, _("\ +Set the current working directory to be used when the inferior is started.\n\ +Changing this setting does not have any effect on inferiors that are\n\ +already running."), + _("\ +Show the current working directory that is used when the inferior is started."), + _("\ +Use this command to change the current working directory that will be used\n\ +when the inferior is started. This setting does not affect GDB's current\n\ +working directory."), + set_cwd_command, + show_cwd_command, + &setlist, &showlist); + c = lookup_cmd (&cmd_name, setlist, "", -1, 1); + gdb_assert (c != NULL); + set_cmd_completer (c, filename_completer); + c = add_cmd ("environment", no_class, environment_info, _("\ The environment to give the program, or one variable's value.\n\ With an argument VAR, prints the value of environment variable VAR to\n\ @@ -3382,21 +3498,19 @@ Specifying -a and an ignore count simultaneously is an error.")); add_com_alias ("fg", "cont", class_run, 1); c = add_com ("run", class_run, run_command, _("\ -Start debugged program. You may specify arguments to give it.\n\ -Args may include \"*\", or \"[...]\"; they are expanded using \"sh\".\n\ -Input and output redirection with \">\", \"<\", or \">>\" are also \ -allowed.\n\n\ -With no arguments, uses arguments last specified (with \"run\" \ -or \"set args\").\n\ -To cancel previous arguments and run with no arguments,\n\ -use \"set args\" without arguments.")); +Start debugged program.\n" +RUN_ARGS_HELP)); set_cmd_completer (c, filename_completer); add_com_alias ("r", "run", class_run, 1); c = add_com ("start", class_run, start_command, _("\ -Run the debugged program until the beginning of the main procedure.\n\ -You may specify arguments to give to your program, just as with the\n\ -\"run\" command.")); +Start the debugged program stopping at the beginning of the main procedure.\n" +RUN_ARGS_HELP)); + set_cmd_completer (c, filename_completer); + + c = add_com ("starti", class_run, starti_command, _("\ +Start the debugged program stopping at the first instruction.\n" +RUN_ARGS_HELP)); set_cmd_completer (c, filename_completer); add_com ("interrupt", class_run, interrupt_command, @@ -3405,24 +3519,24 @@ If non-stop mode is enabled, interrupt only the current thread,\n\ otherwise all the threads in the program are stopped. To \n\ interrupt all running threads in non-stop mode, use the -a option.")); - c = add_info ("registers", nofp_registers_info, _("\ + c = add_info ("registers", info_registers_command, _("\ List of integer registers and their contents, for selected stack frame.\n\ Register name as argument means describe only that register.")); add_info_alias ("r", "registers", 1); set_cmd_completer (c, reg_or_group_completer); - c = add_info ("all-registers", all_registers_info, _("\ + c = add_info ("all-registers", info_all_registers_command, _("\ List of all registers and their contents, for selected stack frame.\n\ Register name as argument means describe only that register.")); set_cmd_completer (c, reg_or_group_completer); - add_info ("program", program_info, + add_info ("program", info_program_command, _("Execution status of the program.")); - add_info ("float", float_info, + add_info ("float", info_float_command, _("Print the status of the floating point unit\n")); - add_info ("vector", vector_info, + add_info ("vector", info_vector_command, _("Print the status of the vector unit\n")); add_prefix_cmd ("proc", class_info, info_proc_cmd,