| Index: gdb/infcmd.c
|
| diff --git a/gdb/infcmd.c b/gdb/infcmd.c
|
| index 4b31c9842e6fafbd01d484220756711dd273947c..7e31600219e6f555991966f826e551ff8048674e 100644
|
| --- a/gdb/infcmd.c
|
| +++ b/gdb/infcmd.c
|
| @@ -75,7 +75,7 @@ void interrupt_target_command (char *args, int from_tty);
|
|
|
| static void nofp_registers_info (char *, int);
|
|
|
| -static void print_return_value (struct type *func_type,
|
| +static void print_return_value (struct value *function,
|
| struct type *value_type);
|
|
|
| static void until_next_command (int);
|
| @@ -275,10 +275,18 @@ construct_inferior_arguments (int argc, char **argv)
|
|
|
| if (STARTUP_WITH_SHELL)
|
| {
|
| +#ifdef __MINGW32__
|
| + /* This holds all the characters considered special to the
|
| + Windows shells. */
|
| + char *special = "\"!&*|[]{}<>?`~^=;, \t\n";
|
| + 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";
|
| + char *special = "\"!#$&*()\\|[]{}<>?'`~^; \t\n";
|
| + const char quote = '\'';
|
| +#endif
|
| int i;
|
| int length = 0;
|
| char *out, *cp;
|
| @@ -298,11 +306,20 @@ construct_inferior_arguments (int argc, char **argv)
|
| /* Need to handle empty arguments specially. */
|
| if (argv[i][0] == '\0')
|
| {
|
| - *out++ = '\'';
|
| - *out++ = '\'';
|
| + *out++ = quote;
|
| + *out++ = quote;
|
| }
|
| else
|
| {
|
| +#ifdef __MINGW32__
|
| + int quoted = 0;
|
| +
|
| + if (strpbrk (argv[i], special))
|
| + {
|
| + quoted = 1;
|
| + *out++ = quote;
|
| + }
|
| +#endif
|
| for (cp = argv[i]; *cp; ++cp)
|
| {
|
| if (*cp == '\n')
|
| @@ -310,17 +327,25 @@ construct_inferior_arguments (int argc, char **argv)
|
| /* A newline cannot be quoted with a backslash (it
|
| just disappears), only by putting it inside
|
| quotes. */
|
| - *out++ = '\'';
|
| + *out++ = quote;
|
| *out++ = '\n';
|
| - *out++ = '\'';
|
| + *out++ = quote;
|
| }
|
| else
|
| {
|
| +#ifdef __MINGW32__
|
| + if (*cp == quote)
|
| +#else
|
| if (strchr (special, *cp) != NULL)
|
| +#endif
|
| *out++ = '\\';
|
| *out++ = *cp;
|
| }
|
| }
|
| +#ifdef __MINGW32__
|
| + if (quoted)
|
| + *out++ = quote;
|
| +#endif
|
| }
|
| }
|
| *out = '\0';
|
| @@ -607,7 +632,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
|
|
|
| /* 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 ()), TARGET_SIGNAL_0, 0);
|
| + proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0, 0);
|
|
|
| /* Since there was no error, there's no need to finish the thread
|
| states here. */
|
| @@ -660,11 +685,11 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
|
|
|
| switch_to_thread (thread->ptid);
|
| clear_proceed_status ();
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
|
| return 0;
|
| }
|
|
|
| -void
|
| +static void
|
| ensure_valid_thread (void)
|
| {
|
| if (ptid_equal (inferior_ptid, null_ptid)
|
| @@ -676,7 +701,7 @@ ensure_valid_thread (void)
|
| is likely to mix up recorded and live target data. So simply
|
| disallow those commands. */
|
|
|
| -void
|
| +static void
|
| ensure_not_tfind_mode (void)
|
| {
|
| if (get_traceframe_number () >= 0)
|
| @@ -708,7 +733,7 @@ continue_1 (int all_threads)
|
| ensure_valid_thread ();
|
| ensure_not_running ();
|
| clear_proceed_status ();
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
|
| }
|
| }
|
|
|
| @@ -1036,7 +1061,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
|
| tp->control.step_range_start = tp->control.step_range_end = 1;
|
| else if (tp->control.step_range_end == 0)
|
| {
|
| - char *name;
|
| + const char *name;
|
|
|
| if (find_pc_partial_function (pc, &name,
|
| &tp->control.step_range_start,
|
| @@ -1064,7 +1089,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
|
| tp->control.step_over_calls = STEP_OVER_ALL;
|
|
|
| tp->step_multi = (count > 1);
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
|
|
|
| /* For async targets, register a continuation to do any
|
| additional steps. For sync targets, the caller will handle
|
| @@ -1115,7 +1140,7 @@ jump_command (char *arg, int from_tty)
|
| if (!arg)
|
| error_no_arg (_("starting address"));
|
|
|
| - sals = decode_line_spec_1 (arg, DECODE_LINE_FUNFIRSTLINE);
|
| + sals = decode_line_with_last_displayed (arg, DECODE_LINE_FUNFIRSTLINE);
|
| if (sals.nelts != 1)
|
| {
|
| error (_("Unreasonable jump request"));
|
| @@ -1175,7 +1200,7 @@ jump_command (char *arg, int from_tty)
|
| }
|
|
|
| clear_proceed_status ();
|
| - proceed (addr, TARGET_SIGNAL_0, 0);
|
| + proceed (addr, GDB_SIGNAL_0, 0);
|
| }
|
|
|
|
|
| @@ -1198,7 +1223,7 @@ go_command (char *line_no, int from_tty)
|
| static void
|
| signal_command (char *signum_exp, int from_tty)
|
| {
|
| - enum target_signal oursig;
|
| + enum gdb_signal oursig;
|
| int async_exec = 0;
|
|
|
| dont_repeat (); /* Too dangerous. */
|
| @@ -1230,26 +1255,26 @@ signal_command (char *signum_exp, int from_tty)
|
| /* It would be even slicker to make signal names be valid expressions,
|
| (the type could be "enum $signal" or some such), then the user could
|
| assign them to convenience variables. */
|
| - oursig = target_signal_from_name (signum_exp);
|
| + oursig = gdb_signal_from_name (signum_exp);
|
|
|
| - if (oursig == TARGET_SIGNAL_UNKNOWN)
|
| + if (oursig == GDB_SIGNAL_UNKNOWN)
|
| {
|
| /* No, try numeric. */
|
| int num = parse_and_eval_long (signum_exp);
|
|
|
| if (num == 0)
|
| - oursig = TARGET_SIGNAL_0;
|
| + oursig = GDB_SIGNAL_0;
|
| else
|
| - oursig = target_signal_from_command (num);
|
| + oursig = gdb_signal_from_command (num);
|
| }
|
|
|
| if (from_tty)
|
| {
|
| - if (oursig == TARGET_SIGNAL_0)
|
| + if (oursig == GDB_SIGNAL_0)
|
| printf_filtered (_("Continuing with no signal.\n"));
|
| else
|
| printf_filtered (_("Continuing with signal %s.\n"),
|
| - target_signal_to_name (oursig));
|
| + gdb_signal_to_name (oursig));
|
| }
|
|
|
| clear_proceed_status ();
|
| @@ -1330,7 +1355,7 @@ until_next_command (int from_tty)
|
| set_longjmp_breakpoint (tp, get_frame_id (frame));
|
| old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
|
|
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
|
|
|
| if (target_can_async_p () && is_running (inferior_ptid))
|
| {
|
| @@ -1416,7 +1441,7 @@ advance_command (char *arg, int from_tty)
|
| command/BP. */
|
|
|
| struct value *
|
| -get_return_value (struct type *func_type, struct type *value_type)
|
| +get_return_value (struct value *function, struct type *value_type)
|
| {
|
| struct regcache *stop_regs = stop_registers;
|
| struct gdbarch *gdbarch;
|
| @@ -1443,14 +1468,14 @@ get_return_value (struct type *func_type, struct type *value_type)
|
| inferior function call code. In fact, when inferior function
|
| calls are made async, this will likely be made the norm. */
|
|
|
| - switch (gdbarch_return_value (gdbarch, func_type, value_type,
|
| + switch (gdbarch_return_value (gdbarch, function, value_type,
|
| NULL, NULL, NULL))
|
| {
|
| case RETURN_VALUE_REGISTER_CONVENTION:
|
| case RETURN_VALUE_ABI_RETURNS_ADDRESS:
|
| case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
|
| value = allocate_value (value_type);
|
| - gdbarch_return_value (gdbarch, func_type, value_type, stop_regs,
|
| + gdbarch_return_value (gdbarch, function, value_type, stop_regs,
|
| value_contents_raw (value), NULL);
|
| break;
|
| case RETURN_VALUE_STRUCT_CONVENTION:
|
| @@ -1468,26 +1493,26 @@ get_return_value (struct type *func_type, struct type *value_type)
|
| /* Print the result of a function at the end of a 'finish' command. */
|
|
|
| static void
|
| -print_return_value (struct type *func_type, struct type *value_type)
|
| +print_return_value (struct value *function, struct type *value_type)
|
| {
|
| - struct value *value = get_return_value (func_type, value_type);
|
| - struct cleanup *old_chain;
|
| - struct ui_stream *stb;
|
| + struct value *value = get_return_value (function, value_type);
|
| struct ui_out *uiout = current_uiout;
|
|
|
| if (value)
|
| {
|
| struct value_print_options opts;
|
| + struct ui_file *stb;
|
| + struct cleanup *old_chain;
|
|
|
| /* Print it. */
|
| - stb = ui_out_stream_new (uiout);
|
| - old_chain = make_cleanup_ui_out_stream_delete (stb);
|
| + 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",
|
| record_latest_value (value));
|
| ui_out_text (uiout, " = ");
|
| get_raw_print_options (&opts);
|
| - value_print (value, stb->stream, &opts);
|
| + value_print (value, stb, &opts);
|
| ui_out_field_stream (uiout, "return-value", stb);
|
| ui_out_text (uiout, "\n");
|
| do_cleanups (old_chain);
|
| @@ -1548,13 +1573,15 @@ finish_command_continuation (void *arg, int err)
|
| if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
|
| {
|
| volatile struct gdb_exception ex;
|
| + struct value *func;
|
|
|
| + func = read_var_value (a->function, get_current_frame ());
|
| TRY_CATCH (ex, RETURN_MASK_ALL)
|
| {
|
| /* print_return_value can throw an exception in some
|
| circumstances. We need to catch this so that we still
|
| delete the breakpoint. */
|
| - print_return_value (SYMBOL_TYPE (a->function), value_type);
|
| + print_return_value (func, value_type);
|
| }
|
| if (ex.reason < 0)
|
| exception_print (gdb_stdout, ex);
|
| @@ -1620,14 +1647,14 @@ finish_backward (struct symbol *function)
|
| insert_step_resume_breakpoint_at_sal (gdbarch,
|
| sr_sal, null_frame_id);
|
|
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
|
| }
|
| else
|
| {
|
| /* We're almost there -- we just need to back up by one more
|
| single-step. */
|
| tp->control.step_range_start = tp->control.step_range_end = 1;
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
|
| }
|
| }
|
|
|
| @@ -1652,6 +1679,9 @@ finish_forward (struct symbol *function, struct frame_info *frame)
|
| get_stack_frame_id (frame),
|
| bp_finish);
|
|
|
| + /* set_momentary_breakpoint invalidates FRAME. */
|
| + frame = NULL;
|
| +
|
| old_chain = make_cleanup_delete_breakpoint (breakpoint);
|
|
|
| set_longjmp_breakpoint (tp, frame_id);
|
| @@ -1666,7 +1696,7 @@ finish_forward (struct symbol *function, struct frame_info *frame)
|
| cargs->function = function;
|
| add_continuation (tp, finish_command_continuation, cargs,
|
| finish_command_continuation_free_arg);
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
|
|
|
| discard_cleanups (old_chain);
|
| if (!target_can_async_p ())
|
| @@ -1743,10 +1773,15 @@ finish_command (char *arg, int from_tty)
|
| print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
|
| }
|
|
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
|
| return;
|
| }
|
|
|
| + /* Ignore TAILCALL_FRAME type frames, they were executed already before
|
| + entering THISFRAME. */
|
| + while (get_frame_type (frame) == TAILCALL_FRAME)
|
| + frame = get_prev_frame (frame);
|
| +
|
| /* Find the function we will return from. */
|
|
|
| function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
|
| @@ -1823,11 +1858,11 @@ program_info (char *args, int from_tty)
|
| stat = bpstat_num (&bs, &num);
|
| }
|
| }
|
| - else if (tp->suspend.stop_signal != TARGET_SIGNAL_0)
|
| + else if (tp->suspend.stop_signal != GDB_SIGNAL_0)
|
| {
|
| printf_filtered (_("It stopped with signal %s, %s.\n"),
|
| - target_signal_to_name (tp->suspend.stop_signal),
|
| - target_signal_to_string (tp->suspend.stop_signal));
|
| + gdb_signal_to_name (tp->suspend.stop_signal),
|
| + gdb_signal_to_string (tp->suspend.stop_signal));
|
| }
|
|
|
| if (!from_tty)
|
| @@ -2171,7 +2206,7 @@ registers_info (char *addr_exp, int fpregs)
|
| struct value_print_options opts;
|
| struct value *val = value_of_user_reg (regnum, frame);
|
|
|
| - printf_filtered ("%s: ", start);
|
| + printf_filtered ("%.*s: ", (int) (end - start), start);
|
| get_formatted_print_options (&opts, 'x');
|
| val_print_scalar_formatted (check_typedef (value_type (val)),
|
| value_contents_for_printing (val),
|
| @@ -2309,7 +2344,7 @@ kill_command (char *arg, int from_tty)
|
| /* Used in `attach&' command. ARG is a point to an integer
|
| representing a process id. Proceed threads of this process iff
|
| they stopped due to debugger request, and when they did, they
|
| - reported a clean stop (TARGET_SIGNAL_0). Do not proceed threads
|
| + reported a clean stop (GDB_SIGNAL_0). Do not proceed threads
|
| that have been explicitly been told to stop. */
|
|
|
| static int
|
| @@ -2322,11 +2357,11 @@ proceed_after_attach_callback (struct thread_info *thread,
|
| && !is_exited (thread->ptid)
|
| && !is_executing (thread->ptid)
|
| && !thread->stop_requested
|
| - && thread->suspend.stop_signal == TARGET_SIGNAL_0)
|
| + && thread->suspend.stop_signal == GDB_SIGNAL_0)
|
| {
|
| switch_to_thread (thread->ptid);
|
| clear_proceed_status ();
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
|
| }
|
|
|
| return 0;
|
| @@ -2423,10 +2458,10 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
|
| proceed_after_attach (inferior->pid);
|
| else
|
| {
|
| - if (inferior_thread ()->suspend.stop_signal == TARGET_SIGNAL_0)
|
| + if (inferior_thread ()->suspend.stop_signal == GDB_SIGNAL_0)
|
| {
|
| clear_proceed_status ();
|
| - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
| + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
|
| }
|
| }
|
| }
|
| @@ -2607,7 +2642,7 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
|
|
|
| /* 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 != TARGET_SIGNAL_0. We don't try to
|
| + target reports a signal != GDB_SIGNAL_0. We don't try to
|
| resume threads with such a stop signal. */
|
| async_exec = non_stop;
|
|
|
| @@ -2806,9 +2841,87 @@ unset_command (char *args, int from_tty)
|
| help_list (unsetlist, "unset ", -1, gdb_stdout);
|
| }
|
|
|
| +/* Implement `info proc' family of commands. */
|
| +
|
| +static void
|
| +info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty)
|
| +{
|
| + struct gdbarch *gdbarch = get_current_arch ();
|
| +
|
| + if (gdbarch_info_proc_p (gdbarch))
|
| + gdbarch_info_proc (gdbarch, args, what);
|
| + else
|
| + target_info_proc (args, what);
|
| +}
|
| +
|
| +/* Implement `info proc' when given without any futher parameters. */
|
| +
|
| +static void
|
| +info_proc_cmd (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_MINIMAL, from_tty);
|
| +}
|
| +
|
| +/* Implement `info proc mappings'. */
|
| +
|
| +static void
|
| +info_proc_cmd_mappings (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_MAPPINGS, from_tty);
|
| +}
|
| +
|
| +/* Implement `info proc stat'. */
|
| +
|
| +static void
|
| +info_proc_cmd_stat (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_STAT, from_tty);
|
| +}
|
| +
|
| +/* Implement `info proc status'. */
|
| +
|
| +static void
|
| +info_proc_cmd_status (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_STATUS, from_tty);
|
| +}
|
| +
|
| +/* Implement `info proc cwd'. */
|
| +
|
| +static void
|
| +info_proc_cmd_cwd (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_CWD, from_tty);
|
| +}
|
| +
|
| +/* Implement `info proc cmdline'. */
|
| +
|
| +static void
|
| +info_proc_cmd_cmdline (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_CMDLINE, from_tty);
|
| +}
|
| +
|
| +/* Implement `info proc exe'. */
|
| +
|
| +static void
|
| +info_proc_cmd_exe (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_EXE, from_tty);
|
| +}
|
| +
|
| +/* Implement `info proc all'. */
|
| +
|
| +static void
|
| +info_proc_cmd_all (char *args, int from_tty)
|
| +{
|
| + info_proc_cmd_1 (args, IP_ALL, from_tty);
|
| +}
|
| +
|
| void
|
| _initialize_infcmd (void)
|
| {
|
| + static struct cmd_list_element *info_proc_cmdlist;
|
| struct cmd_list_element *c = NULL;
|
|
|
| /* Add the filename of the terminal connected to inferior I/O. */
|
| @@ -3035,4 +3148,39 @@ Register name as argument means describe only that register."));
|
|
|
| add_info ("vector", vector_info,
|
| _("Print the status of the vector unit\n"));
|
| +
|
| + add_prefix_cmd ("proc", class_info, info_proc_cmd,
|
| + _("\
|
| +Show /proc process information about any running process.\n\
|
| +Specify any process id, or use the program being debugged by default."),
|
| + &info_proc_cmdlist, "info proc ",
|
| + 1/*allow-unknown*/, &infolist);
|
| +
|
| + add_cmd ("mappings", class_info, info_proc_cmd_mappings, _("\
|
| +List of mapped memory regions."),
|
| + &info_proc_cmdlist);
|
| +
|
| + add_cmd ("stat", class_info, info_proc_cmd_stat, _("\
|
| +List process info from /proc/PID/stat."),
|
| + &info_proc_cmdlist);
|
| +
|
| + add_cmd ("status", class_info, info_proc_cmd_status, _("\
|
| +List process info from /proc/PID/status."),
|
| + &info_proc_cmdlist);
|
| +
|
| + add_cmd ("cwd", class_info, info_proc_cmd_cwd, _("\
|
| +List current working directory of the process."),
|
| + &info_proc_cmdlist);
|
| +
|
| + add_cmd ("cmdline", class_info, info_proc_cmd_cmdline, _("\
|
| +List command line arguments of the process."),
|
| + &info_proc_cmdlist);
|
| +
|
| + add_cmd ("exe", class_info, info_proc_cmd_exe, _("\
|
| +List absolute filename for executable of the process."),
|
| + &info_proc_cmdlist);
|
| +
|
| + add_cmd ("all", class_info, info_proc_cmd_all, _("\
|
| +List all available /proc info."),
|
| + &info_proc_cmdlist);
|
| }
|
|
|