X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfcmd.c;h=a8ab1f0faf5511deed07c5e675287bc1d923adb1;hb=affddf13813eefe252c923001e09e7582adb8cfd;hp=1fc778ce2f83f5d61b0e60cffd21829cb3cc099c;hpb=714835d5a63b86bb0e82c13d2a4840d8b5e633d3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 1fc778ce2f..a8ab1f0faf 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008 Free Software Foundation, Inc. + 2008, 2009 Free Software Foundation, Inc. This file is part of GDB. @@ -51,6 +51,7 @@ #include "exceptions.h" #include "cli/cli-decode.h" #include "gdbthread.h" +#include "valprint.h" /* Functions exported for general use, in inferior.h: */ @@ -85,8 +86,6 @@ static void unset_command (char *, int); static void float_info (char *, int); -static void detach_command (char *, int); - static void disconnect_command (char *, int); static void unset_environment_command (char *, int); @@ -120,8 +119,6 @@ static int strip_bg_char (char **); void _initialize_infcmd (void); -#define GO_USAGE "Usage: go \n" - #define ERROR_NO_INFERIOR \ if (!target_has_execution) error (_("The program is not being run.")); @@ -147,27 +144,15 @@ static char *inferior_io_terminal; ptid_t inferior_ptid; -/* Last signal that the inferior received (why it stopped). */ - -enum target_signal stop_signal; - /* Address at which inferior stopped. */ CORE_ADDR stop_pc; -/* Chain containing status of breakpoint(s) that we have stopped at. */ - -bpstat stop_bpstat; - /* Flag indicating that a command has proceeded the inferior past the current breakpoint. */ int breakpoint_proceeded; -/* Nonzero if stopped due to a step command. */ - -int stop_step; - /* Nonzero if stopped due to completion of a stack dummy routine. */ int stop_stack_dummy; @@ -177,36 +162,10 @@ int stop_stack_dummy; int stopped_by_random_signal; -/* Range to single step within. - If this is nonzero, respond to a single-step signal - by continuing to step if the pc is in this range. */ - -CORE_ADDR step_range_start; /* Inclusive */ -CORE_ADDR step_range_end; /* Exclusive */ - -/* Stack frame address as of when stepping command was issued. - This is how we know when we step into a subroutine call, - and how to set the frame for the breakpoint used to step out. */ - -struct frame_id step_frame_id; - -enum step_over_calls_kind step_over_calls; - -/* If stepping, nonzero means step count is > 1 - so don't print frame next time inferior stops - if it stops due to stepping. */ - -int step_multi; - /* Environment to use for running inferior, in format described in environ.h. */ struct gdb_environ *inferior_environ; - -/* When set, no calls to target_resumed observer will be made. */ -int suppress_resume_observer = 0; -/* When set, normal_stop will not call the normal_stop observer. */ -int suppress_stop_observer = 0; /* Accessor routines. */ @@ -219,7 +178,7 @@ set_inferior_io_terminal (const char *terminal_name) if (!terminal_name) inferior_io_terminal = NULL; else - inferior_io_terminal = savestring (terminal_name, strlen (terminal_name)); + inferior_io_terminal = xstrdup (terminal_name); } const char * @@ -235,8 +194,7 @@ get_inferior_args (void) { char *n, *old; - n = gdbarch_construct_inferior_arguments (current_gdbarch, - inferior_argc, inferior_argv); + n = construct_inferior_arguments (inferior_argc, inferior_argv); old = set_inferior_args (n); xfree (old); } @@ -288,7 +246,7 @@ notice_args_read (struct ui_file *file, int from_tty, /* Compute command-line string given argument vector. This does the same shell processing as fork_inferior. */ char * -construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv) +construct_inferior_arguments (int argc, char **argv) { char *result; @@ -304,7 +262,7 @@ construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv) /* We over-compute the size. It shouldn't matter. */ for (i = 0; i < argc; ++i) - length += 2 * strlen (argv[i]) + 1 + 2 * (argv[i][0] == '\0'); + length += 3 * strlen (argv[i]) + 1 + 2 * (argv[i][0] == '\0'); result = (char *) xmalloc (length); out = result; @@ -324,9 +282,21 @@ construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv) { for (cp = argv[i]; *cp; ++cp) { - if (strchr (special, *cp) != NULL) - *out++ = '\\'; - *out++ = *cp; + if (*cp == '\n') + { + /* A newline cannot be quoted with a backslash (it + just disappears), only by putting it inside + quotes. */ + *out++ = '\''; + *out++ = '\n'; + *out++ = '\''; + } + else + { + if (strchr (special, *cp) != NULL) + *out++ = '\\'; + *out++ = *cp; + } } } } @@ -420,7 +390,12 @@ post_create_inferior (struct target_ops *target, int from_tty) don't need to. */ target_find_description (); - if (exec_bfd) + /* Now that we know the register layout, retrieve current PC. */ + stop_pc = regcache_read_pc (get_current_regcache ()); + + /* If the solist is global across processes, there's no need to + refetch it here. */ + if (exec_bfd && !gdbarch_has_global_solist (target_gdbarch)) { /* Sometimes the platform-specific hook loads initial shared libraries, and sometimes it doesn't. Try to do so first, so @@ -432,7 +407,10 @@ post_create_inferior (struct target_ops *target, int from_tty) #else solib_add (NULL, from_tty, target, auto_solib_add); #endif + } + if (exec_bfd) + { /* Create the hooks to handle shared library load and unload events. */ #ifdef SOLIB_CREATE_INFERIOR_HOOK @@ -442,6 +420,18 @@ post_create_inferior (struct target_ops *target, int from_tty) #endif } + /* If the user sets watchpoints before execution having started, + then she gets software watchpoints, because GDB can't know which + target will end up being pushed, or if it supports hardware + watchpoints or not. breakpoint_re_set takes care of promoting + watchpoints to hardware watchpoints if possible, however, if this + new inferior doesn't load shared libraries or we don't pull in + symbols from any other source on this target/arch, + breakpoint_re_set is never called. Call it now so that software + watchpoints get a chance to be promoted to hardware watchpoints + if the now pushed target supports hardware watchpoints. */ + breakpoint_re_set (); + observer_notify_inferior_created (target, from_tty); } @@ -460,12 +450,10 @@ kill_if_already_running (int from_tty) target_require_runnable (); if (from_tty - && !query ("The program being debugged has been started already.\n\ -Start it from the beginning? ")) + && !query (_("The program being debugged has been started already.\n\ +Start it from the beginning? "))) error (_("Program not restarted.")); target_kill (); - no_shared_libraries (NULL, from_tty); - init_wait_for_inferior (); } } @@ -477,10 +465,14 @@ static void run_command_1 (char *args, int from_tty, int tbreak_at_main) { char *exec_file; + struct cleanup *old_chain; + ptid_t ptid; dont_repeat (); kill_if_already_running (from_tty); + + init_wait_for_inferior (); clear_breakpoint_hit_counts (); /* Clean up any leftovers from other runs. Some other things from @@ -563,14 +555,29 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) target_create_inferior (exec_file, get_inferior_args (), environ_vector (inferior_environ), from_tty); + /* We're starting off a new process. When we get out of here, in + non-stop mode, finish the state of all threads of that process, + but leave other threads alone, as they may be stopped in internal + events --- the frontend shouldn't see them as stopped. In + all-stop, always finish the state of all threads, as we may be + resuming more than just the new process. */ + if (non_stop) + ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); + else + ptid = minus_one_ptid; + old_chain = make_cleanup (finish_thread_state_cleanup, &ptid); + /* Pass zero for FROM_TTY, because at this point the "run" command has done its thing; now we are setting up the running program. */ post_create_inferior (¤t_target, 0); /* Start the target running. */ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); -} + /* Since there was no error, there's no need to finish the thread + states here. */ + discard_cleanups (old_chain); +} static void run_command (char *args, int from_tty) @@ -605,15 +612,33 @@ start_command (char *args, int from_tty) static int proceed_thread_callback (struct thread_info *thread, void *arg) { + /* We go through all threads individually instead of compressing + into a single target `resume_all' request, because some threads + may be stopped in internal breakpoints/events, or stopped waiting + for its turn in the displaced stepping queue (that is, they are + running && !executing). The target side has no idea about why + the thread is stopped, so a `resume_all' command would resume too + much. If/when GDB gains a way to tell the target `hold this + thread stopped until I say otherwise', then we can optimize + this. */ if (!is_stopped (thread->ptid)) return 0; - context_switch_to (thread->ptid); + switch_to_thread (thread->ptid); clear_proceed_status (); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); return 0; } +void +ensure_valid_thread (void) +{ + if (ptid_equal (inferior_ptid, null_ptid) + || is_exited (inferior_ptid)) + error (_("\ +Cannot execute this command without a live selected thread.")); +} + void continue_1 (int all_threads) { @@ -635,6 +660,7 @@ continue_1 (int all_threads) } else { + ensure_valid_thread (); ensure_not_running (); clear_proceed_status (); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); @@ -688,9 +714,23 @@ Can't resume all threads and specify proceed count simultaneously.")); stopped at. */ if (args != NULL) { - bpstat bs = stop_bpstat; + bpstat bs = NULL; int num, stat; int stopped = 0; + struct thread_info *tp; + + if (non_stop) + tp = find_thread_ptid (inferior_ptid); + else + { + ptid_t last_ptid; + struct target_waitstatus ws; + + get_last_target_status (&last_ptid, &ws); + tp = find_thread_ptid (last_ptid); + } + if (tp != NULL) + bs = tp->stop_bpstat; while ((stat = bpstat_num (&bs, &num)) != 0) if (stat > 0) @@ -765,6 +805,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) int thread = -1; ERROR_NO_INFERIOR; + ensure_valid_thread (); ensure_not_running (); if (count_string) @@ -795,65 +836,41 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) make_cleanup (delete_longjmp_breakpoint_cleanup, &thread); } - /* In synchronous case, all is well, just use the regular for loop. */ + /* In synchronous case, all is well; each step_once call will step once. */ if (!target_can_async_p ()) { for (; count > 0; count--) { - clear_proceed_status (); - - frame = get_current_frame (); - if (!frame) /* Avoid coredump here. Why tho? */ - error (_("No current frame")); - step_frame_id = get_frame_id (frame); - - if (!single_inst) - { - find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end); - if (step_range_end == 0) - { - char *name; - if (find_pc_partial_function (stop_pc, &name, &step_range_start, - &step_range_end) == 0) - error (_("Cannot find bounds of current function")); + struct thread_info *tp; + step_once (skip_subroutines, single_inst, count, thread); - target_terminal_ours (); - printf_filtered (_("\ -Single stepping until exit from function %s, \n\ -which has no line number information.\n"), name); - } - } + if (target_has_execution + && !ptid_equal (inferior_ptid, null_ptid)) + tp = inferior_thread (); else + tp = NULL; + + if (!tp || !tp->stop_step || !tp->step_multi) { - /* Say we are stepping, but stop after one insn whatever it does. */ - step_range_start = step_range_end = 1; - if (!skip_subroutines) - /* It is stepi. - Don't step over function calls, not even to functions lacking - line numbers. */ - step_over_calls = STEP_OVER_NONE; + /* If we stopped for some reason that is not stepping + there are no further steps to make. */ + if (tp) + tp->step_multi = 0; + break; } - - if (skip_subroutines) - step_over_calls = STEP_OVER_ALL; - - step_multi = (count > 1); - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); - - if (!stop_step) - break; } do_cleanups (cleanups); - return; } - /* In case of asynchronous target things get complicated, do only - one step for now, before returning control to the event loop. Let - the continuation figure out how many other steps we need to do, - and handle them one at the time, through step_once(). */ else { + /* In the case of an asynchronous target things get complicated; + do only one step for now, before returning control to the + event loop. Let the continuation figure out how many other + steps we need to do, and handle them one at the time, through + step_once. */ step_once (skip_subroutines, single_inst, count, thread); + /* We are running, and the continuation is installed. It will disable the longjmp breakpoint as appropriate. */ discard_cleanups (cleanups); @@ -878,54 +895,70 @@ step_1_continuation (void *args) { struct step_1_continuation_args *a = args; - if (!step_multi || !stop_step) + if (target_has_execution) { - /* If we stopped for some reason that is not stepping there are - no further steps to make. Cleanup. */ - if (!a->single_inst || a->skip_subroutines) - delete_longjmp_breakpoint (a->thread); - step_multi = 0; + struct thread_info *tp; + + tp = inferior_thread (); + if (tp->step_multi && tp->stop_step) + { + /* There are more steps to make, and we did stop due to + ending a stepping range. Do another step. */ + step_once (a->skip_subroutines, a->single_inst, + a->count - 1, a->thread); + return; + } + tp->step_multi = 0; } - else - step_once (a->skip_subroutines, a->single_inst, a->count - 1, a->thread); + + /* We either stopped for some reason that is not stepping, or there + are no further steps to make. Cleanup. */ + if (!a->single_inst || a->skip_subroutines) + delete_longjmp_breakpoint (a->thread); } -/* Do just one step operation. If count >1 we will have to set up a - continuation to be done after the target stops (after this one - step). This is useful to implement the 'step n' kind of commands, in - case of asynchronous targets. We had to split step_1 into two parts, - one to be done before proceed() and one afterwards. This function is - called in case of step n with n>1, after the first step operation has - been completed.*/ -static void +/* Do just one step operation. This is useful to implement the 'step + n' kind of commands. In case of asynchronous targets, we will have + to set up a continuation to be done after the target stops (after + this one step). For synch targets, the caller handles further + stepping. */ + +static void step_once (int skip_subroutines, int single_inst, int count, int thread) { struct frame_info *frame; - struct step_1_continuation_args *args; if (count > 0) { + /* Don't assume THREAD is a valid thread id. It is set to -1 if + the longjmp breakpoint was not required. Use the + INFERIOR_PTID thread instead, which is the same thread when + THREAD is set. */ + struct thread_info *tp = inferior_thread (); clear_proceed_status (); frame = get_current_frame (); - if (!frame) /* Avoid coredump here. Why tho? */ - error (_("No current frame")); - step_frame_id = get_frame_id (frame); + tp->step_frame_id = get_frame_id (frame); if (!single_inst) { - find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end); + CORE_ADDR pc; + + pc = get_frame_pc (frame); + find_pc_line_pc_range (pc, + &tp->step_range_start, &tp->step_range_end); /* If we have no line info, switch to stepi mode. */ - if (step_range_end == 0 && step_stop_if_no_debug) + if (tp->step_range_end == 0 && step_stop_if_no_debug) { - step_range_start = step_range_end = 1; + tp->step_range_start = tp->step_range_end = 1; } - else if (step_range_end == 0) + else if (tp->step_range_end == 0) { char *name; - if (find_pc_partial_function (stop_pc, &name, &step_range_start, - &step_range_end) == 0) + if (find_pc_partial_function (pc, &name, + &tp->step_range_start, + &tp->step_range_end) == 0) error (_("Cannot find bounds of current function")); target_terminal_ours (); @@ -937,26 +970,35 @@ which has no line number information.\n"), name); else { /* Say we are stepping, but stop after one insn whatever it does. */ - step_range_start = step_range_end = 1; + tp->step_range_start = tp->step_range_end = 1; if (!skip_subroutines) /* It is stepi. Don't step over function calls, not even to functions lacking line numbers. */ - step_over_calls = STEP_OVER_NONE; + tp->step_over_calls = STEP_OVER_NONE; } if (skip_subroutines) - step_over_calls = STEP_OVER_ALL; + tp->step_over_calls = STEP_OVER_ALL; - step_multi = (count > 1); + tp->step_multi = (count > 1); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); - args = xmalloc (sizeof (*args)); - args->skip_subroutines = skip_subroutines; - args->single_inst = single_inst; - args->count = count; - args->thread = thread; - add_intermediate_continuation (step_1_continuation, args, xfree); + /* For async targets, register a continuation to do any + additional steps. For sync targets, the caller will handle + further stepping. */ + if (target_can_async_p ()) + { + struct step_1_continuation_args *args; + + args = xmalloc (sizeof (*args)); + args->skip_subroutines = skip_subroutines; + args->single_inst = single_inst; + args->count = count; + args->thread = thread; + + add_intermediate_continuation (tp, step_1_continuation, args, xfree); + } } } @@ -974,6 +1016,7 @@ jump_command (char *arg, int from_tty) int async_exec = 0; ERROR_NO_INFERIOR; + ensure_valid_thread (); ensure_not_running (); /* Find out whether we must run in the background. */ @@ -1007,7 +1050,7 @@ jump_command (char *arg, int from_tty) sfn = find_pc_function (sal.pc); if (fn != NULL && sfn != fn) { - if (!query ("Line %d is not in `%s'. Jump anyway? ", sal.line, + if (!query (_("Line %d is not in `%s'. Jump anyway? "), sal.line, SYMBOL_PRINT_NAME (fn))) { error (_("Not confirmed.")); @@ -1021,7 +1064,7 @@ jump_command (char *arg, int from_tty) if (section_is_overlay (SYMBOL_OBJ_SECTION (sfn)) && !section_is_mapped (SYMBOL_OBJ_SECTION (sfn))) { - if (!query ("WARNING!!! Destination is in unmapped overlay! Jump anyway? ")) + if (!query (_("WARNING!!! Destination is in unmapped overlay! Jump anyway? "))) { error (_("Not confirmed.")); /* NOTREACHED */ @@ -1056,7 +1099,7 @@ static void go_command (char *line_no, int from_tty) { if (line_no == (char *) NULL || !*line_no) - printf_filtered (GO_USAGE); + printf_filtered (_("Usage: go \n")); else { tbreak_command (line_no, from_tty); @@ -1075,6 +1118,7 @@ signal_command (char *signum_exp, int from_tty) dont_repeat (); /* Too dangerous. */ ERROR_NO_INFERIOR; + ensure_valid_thread (); ensure_not_running (); /* Find out whether we must run in the background. */ @@ -1123,11 +1167,7 @@ signal_command (char *signum_exp, int from_tty) } clear_proceed_status (); - /* "signal 0" should not get stuck if we are stopped at a breakpoint. - FIXME: Neither should "signal foo" but when I tried passing - (CORE_ADDR)-1 unconditionally I got a testsuite failure which I haven't - tried to track down yet. */ - proceed (oursig == TARGET_SIGNAL_0 ? (CORE_ADDR) -1 : stop_pc, oursig, 0); + proceed ((CORE_ADDR) -1, oursig, 0); } /* Proceed until we reach a different source line with pc greater than @@ -1145,6 +1185,7 @@ until_next_command (int from_tty) CORE_ADDR pc; struct symbol *func; struct symtab_and_line sal; + struct thread_info *tp = inferior_thread (); clear_proceed_status (); @@ -1154,7 +1195,7 @@ until_next_command (int from_tty) than the current line (if in symbolic section) or pc (if not). */ - pc = read_pc (); + pc = get_frame_pc (frame); func = find_pc_function (pc); if (!func) @@ -1164,21 +1205,21 @@ until_next_command (int from_tty) if (msymbol == NULL) error (_("Execution is not within a known function.")); - step_range_start = SYMBOL_VALUE_ADDRESS (msymbol); - step_range_end = pc; + tp->step_range_start = SYMBOL_VALUE_ADDRESS (msymbol); + tp->step_range_end = pc; } else { sal = find_pc_line (pc, 0); - step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func)); - step_range_end = sal.end; + tp->step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func)); + tp->step_range_end = sal.end; } - step_over_calls = STEP_OVER_ALL; - step_frame_id = get_frame_id (frame); + tp->step_over_calls = STEP_OVER_ALL; + tp->step_frame_id = get_frame_id (frame); - step_multi = 0; /* Only one call to proceed */ + tp->step_multi = 0; /* Only one call to proceed */ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); } @@ -1250,7 +1291,7 @@ advance_command (char *arg, int from_tty) static void print_return_value (struct type *func_type, struct type *value_type) { - struct gdbarch *gdbarch = current_gdbarch; + struct gdbarch *gdbarch = get_regcache_arch (stop_registers); struct cleanup *old_chain; struct ui_stream *stb; struct value *value; @@ -1284,6 +1325,8 @@ print_return_value (struct type *func_type, struct type *value_type) if (value) { + struct value_print_options opts; + /* Print it. */ stb = ui_out_stream_new (uiout); old_chain = make_cleanup_ui_out_stream_delete (stb); @@ -1291,7 +1334,8 @@ print_return_value (struct type *func_type, struct type *value_type) ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value)); ui_out_text (uiout, " = "); - value_print (value, stb->stream, 0, Val_no_prettyprint); + get_raw_print_options (&opts); + value_print (value, stb->stream, &opts); ui_out_field_stream (uiout, "return-value", stb); ui_out_text (uiout, "\n"); do_cleanups (old_chain); @@ -1324,8 +1368,18 @@ static void finish_command_continuation (void *arg) { struct finish_command_continuation_args *a = arg; + struct thread_info *tp = NULL; + bpstat bs = NULL; + + if (!ptid_equal (inferior_ptid, null_ptid) + && target_has_execution + && is_stopped (inferior_ptid)) + { + tp = inferior_thread (); + bs = tp->stop_bpstat; + } - if (bpstat_find_breakpoint (stop_bpstat, a->breakpoint) != NULL + if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL && a->function != NULL) { struct type *value_type; @@ -1340,37 +1394,121 @@ finish_command_continuation (void *arg) } /* We suppress normal call of normal_stop observer and do it here so - that that *stopped notification includes the return value. */ - /* NOTE: This is broken in non-stop mode. There is no guarantee the - next stop will be in the same thread that we started doing a - finish on. This suppressing (or some other replacement means) - should be a thread property. */ - observer_notify_normal_stop (stop_bpstat); - suppress_stop_observer = 0; + that the *stopped notification includes the return value. */ + if (bs != NULL && tp->proceed_to_finish) + observer_notify_normal_stop (bs, 1 /* print frame */); delete_breakpoint (a->breakpoint); } static void finish_command_continuation_free_arg (void *arg) { - /* NOTE: See finish_command_continuation. This would go away, if - this suppressing is made a thread property. */ - suppress_stop_observer = 0; xfree (arg); } +/* finish_backward -- helper function for finish_command. */ + +static void +finish_backward (struct symbol *function) +{ + struct symtab_and_line sal; + struct thread_info *tp = inferior_thread (); + struct breakpoint *breakpoint; + struct cleanup *old_chain; + CORE_ADDR pc; + CORE_ADDR func_addr; + int back_up; + + pc = get_frame_pc (get_current_frame ()); + + if (find_pc_partial_function (pc, NULL, &func_addr, NULL) == 0) + internal_error (__FILE__, __LINE__, + _("Finish: couldn't find function.")); + + sal = find_pc_line (func_addr, 0); + + /* We don't need a return value. */ + tp->proceed_to_finish = 0; + /* Special case: if we're sitting at the function entry point, + then all we need to do is take a reverse singlestep. We + don't need to set a breakpoint, and indeed it would do us + no good to do so. + + Note that this can only happen at frame #0, since there's + no way that a function up the stack can have a return address + that's equal to its entry point. */ + + if (sal.pc != pc) + { + /* Set breakpoint and continue. */ + breakpoint = + set_momentary_breakpoint (sal, + get_frame_id (get_selected_frame (NULL)), + bp_breakpoint); + /* Tell the breakpoint to keep quiet. We won't be done + until we've done another reverse single-step. */ + make_breakpoint_silent (breakpoint); + old_chain = make_cleanup_delete_breakpoint (breakpoint); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); + /* We will be stopped when proceed returns. */ + back_up = bpstat_find_breakpoint (tp->stop_bpstat, breakpoint) != NULL; + do_cleanups (old_chain); + } + else + back_up = 1; + if (back_up) + { + /* If in fact we hit the step-resume breakpoint (and not + some other breakpoint), then we're almost there -- + we just need to back up by one more single-step. */ + tp->step_range_start = tp->step_range_end = 1; + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); + } + return; +} + +/* finish_forward -- helper function for finish_command. */ + +static void +finish_forward (struct symbol *function, struct frame_info *frame) +{ + struct symtab_and_line sal; + struct thread_info *tp = inferior_thread (); + struct breakpoint *breakpoint; + struct cleanup *old_chain; + struct finish_command_continuation_args *cargs; + + sal = find_pc_line (get_frame_pc (frame), 0); + sal.pc = get_frame_pc (frame); + + breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), + bp_finish); + + old_chain = make_cleanup_delete_breakpoint (breakpoint); + + tp->proceed_to_finish = 1; /* We want stop_registers, please... */ + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); + + cargs = xmalloc (sizeof (*cargs)); + + cargs->breakpoint = breakpoint; + cargs->function = function; + add_continuation (tp, finish_command_continuation, cargs, + finish_command_continuation_free_arg); + + discard_cleanups (old_chain); + if (!target_can_async_p ()) + do_all_continuations (); +} + /* "finish": Set a temporary breakpoint at the place the selected frame will return to, then continue. */ static void finish_command (char *arg, int from_tty) { - struct symtab_and_line sal; struct frame_info *frame; struct symbol *function; - struct breakpoint *breakpoint; - struct cleanup *old_chain; - struct finish_command_continuation_args *cargs; int async_exec = 0; @@ -1383,6 +1521,10 @@ finish_command (char *arg, int from_tty) if (async_exec && !target_can_async_p ()) error (_("Asynchronous execution not supported on this target.")); + /* Don't try to async in reverse. */ + if (async_exec && execution_direction == EXEC_REVERSE) + error (_("Asynchronous 'finish' not supported in reverse.")); + /* If we are not asked to run in the bg, then prepare to run in the foreground, synchronously. */ if (!async_exec && target_can_async_p ()) @@ -1402,13 +1544,6 @@ finish_command (char *arg, int from_tty) clear_proceed_status (); - sal = find_pc_line (get_frame_pc (frame), 0); - sal.pc = get_frame_pc (frame); - - breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish); - - old_chain = make_cleanup_delete_breakpoint (breakpoint); - /* Find the function we will return from. */ function = find_pc_function (get_frame_pc (get_selected_frame (NULL))); @@ -1417,34 +1552,28 @@ finish_command (char *arg, int from_tty) source. */ if (from_tty) { - printf_filtered (_("Run till exit from ")); + if (execution_direction == EXEC_REVERSE) + printf_filtered (_("Run back to call of ")); + else + printf_filtered (_("Run till exit from ")); + print_stack_frame (get_selected_frame (NULL), 1, LOCATION); } - proceed_to_finish = 1; /* We want stop_registers, please... */ - make_cleanup_restore_integer (&suppress_stop_observer); - suppress_stop_observer = 1; - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); - - cargs = xmalloc (sizeof (*cargs)); - - cargs->breakpoint = breakpoint; - cargs->function = function; - add_continuation (finish_command_continuation, cargs, - finish_command_continuation_free_arg); - - discard_cleanups (old_chain); - if (!target_can_async_p ()) - do_all_continuations (); + if (execution_direction == EXEC_REVERSE) + finish_backward (function); + else + finish_forward (function, frame); } static void program_info (char *args, int from_tty) { - bpstat bs = stop_bpstat; - int num; - int stat = bpstat_num (&bs, &num); + bpstat bs; + int num, stat; + struct thread_info *tp; + ptid_t ptid; if (!target_has_execution) { @@ -1452,10 +1581,26 @@ program_info (char *args, int from_tty) return; } + if (non_stop) + ptid = inferior_ptid; + else + { + struct target_waitstatus ws; + get_last_target_status (&ptid, &ws); + } + + if (ptid_equal (ptid, null_ptid) || is_exited (ptid)) + error (_("Invalid selected thread.")); + else if (is_running (ptid)) + error (_("Selected thread is running.")); + + tp = find_thread_ptid (ptid); + bs = tp->stop_bpstat; + stat = bpstat_num (&bs, &num); + target_files_info (); - printf_filtered (_("Program stopped at %s.\n"), - hex_string ((unsigned long) stop_pc)); - if (stop_step) + printf_filtered (_("Program stopped at %s.\n"), paddress (stop_pc)); + if (tp->stop_step) printf_filtered (_("It stopped after being stepped.\n")); else if (stat != 0) { @@ -1473,11 +1618,11 @@ It stopped at a breakpoint that has since been deleted.\n")); stat = bpstat_num (&bs, &num); } } - else if (stop_signal != TARGET_SIGNAL_0) + else if (tp->stop_signal != TARGET_SIGNAL_0) { printf_filtered (_("It stopped with signal %s, %s.\n"), - target_signal_to_name (stop_signal), - target_signal_to_string (stop_signal)); + target_signal_to_name (tp->stop_signal), + target_signal_to_string (tp->stop_signal)); } if (!from_tty) @@ -1699,9 +1844,12 @@ default_print_registers_info (struct gdbarch *gdbarch, || TYPE_CODE (register_type (gdbarch, i)) == TYPE_CODE_DECFLOAT) { int j; + struct value_print_options opts; + get_user_print_options (&opts); + opts.deref_ref = 1; val_print (register_type (gdbarch, i), buffer, 0, 0, - file, 0, 1, 0, Val_pretty_default, current_language); + file, 0, &opts, current_language); fprintf_filtered (file, "\t(raw 0x"); for (j = 0; j < register_size (gdbarch, i); j++) @@ -1717,16 +1865,23 @@ default_print_registers_info (struct gdbarch *gdbarch, } else { + struct value_print_options opts; + /* Print the register in hex. */ + get_formatted_print_options (&opts, 'x'); + opts.deref_ref = 1; val_print (register_type (gdbarch, i), buffer, 0, 0, - file, 'x', 1, 0, Val_pretty_default, current_language); + file, 0, &opts, + current_language); /* If not a vector register, print it also according to its natural format. */ if (TYPE_VECTOR (register_type (gdbarch, i)) == 0) { + get_user_print_options (&opts); + opts.deref_ref = 1; fprintf_filtered (file, "\t"); val_print (register_type (gdbarch, i), buffer, 0, 0, - file, 0, 1, 0, Val_pretty_default, current_language); + file, 0, &opts, current_language); } } @@ -1792,12 +1947,14 @@ registers_info (char *addr_exp, int fpregs) if (regnum >= gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch)) { + struct value_print_options opts; struct value *val = value_of_user_reg (regnum, frame); printf_filtered ("%s: ", start); + get_formatted_print_options (&opts, 'x'); print_scalar_formatted (value_contents (val), check_typedef (value_type (val)), - 'x', 0, gdb_stdout); + &opts, 0, gdb_stdout); printf_filtered ("\n"); } else @@ -1807,21 +1964,6 @@ registers_info (char *addr_exp, int fpregs) } } - /* A register number? (how portable is this one?). */ - { - char *endptr; - int regnum = strtol (start, &endptr, 0); - if (endptr == end - && regnum >= 0 - && regnum < gdbarch_num_regs (gdbarch) - + gdbarch_num_pseudo_regs (gdbarch)) - { - gdbarch_print_registers_info (gdbarch, gdb_stdout, - frame, regnum, fpregs); - continue; - } - } - /* A register group? */ { struct reggroup *group; @@ -1870,9 +2012,11 @@ nofp_registers_info (char *addr_exp, int from_tty) } static void -print_vector_info (struct gdbarch *gdbarch, struct ui_file *file, +print_vector_info (struct ui_file *file, struct frame_info *frame, const char *args) { + struct gdbarch *gdbarch = get_frame_arch (frame); + if (gdbarch_print_vector_info_p (gdbarch)) gdbarch_print_vector_info (gdbarch, file, frame, args); else @@ -1902,10 +2046,82 @@ vector_info (char *args, int from_tty) if (!target_has_registers) error (_("The program has no registers now.")); - print_vector_info (current_gdbarch, gdb_stdout, - get_selected_frame (NULL), args); + print_vector_info (gdb_stdout, get_selected_frame (NULL), args); } +/* Kill the inferior process. Make us have no inferior. */ + +static void +kill_command (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 + some targets don't have processes! */ + + if (ptid_equal (inferior_ptid, null_ptid)) + error (_("The program is not being run.")); + if (!query (_("Kill the program being debugged? "))) + error (_("Not confirmed.")); + target_kill (); + + /* If we still have other inferiors to debug, then don't mess with + with their threads. */ + if (!have_inferiors ()) + { + init_thread_list (); /* Destroy thread info */ + + /* Killing off the inferior can leave us with a core file. If + so, print the state we are left in. */ + if (target_has_stack) + { + printf_filtered (_("In %s,\n"), target_longname); + print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); + } + } + bfd_cache_close_all (); +} + +/* 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 + that have been explicitly been told to stop. */ + +static int +proceed_after_attach_callback (struct thread_info *thread, + void *arg) +{ + int pid = * (int *) arg; + + if (ptid_get_pid (thread->ptid) == pid + && !is_exited (thread->ptid) + && !is_executing (thread->ptid) + && !thread->stop_requested + && thread->stop_signal == TARGET_SIGNAL_0) + { + switch_to_thread (thread->ptid); + clear_proceed_status (); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); + } + + return 0; +} + +static void +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 (); + + iterate_over_threads (proceed_after_attach_callback, &pid); + + /* Restore selected ptid. */ + do_cleanups (old_chain); +} /* * TODO: @@ -1928,8 +2144,10 @@ attach_command_post_wait (char *args, int from_tty, int async_exec) { char *exec_file; char *full_exec_path = NULL; + struct inferior *inferior; - stop_soon = NO_STOP_QUIETLY; + inferior = current_inferior (); + inferior->stop_soon = NO_STOP_QUIETLY; /* If no exec file is yet known, try to determine it from the process itself. */ @@ -1948,7 +2166,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec) filename. Not much more we can do...) */ if (!source_full_path_of (exec_file, &full_exec_path)) - full_exec_path = savestring (exec_file, strlen (exec_file)); + full_exec_path = xstrdup (exec_file); exec_file_attach (full_exec_path, from_tty); symbol_file_add_main (full_exec_path, from_tty); @@ -1969,11 +2187,44 @@ attach_command_post_wait (char *args, int from_tty, int async_exec) target_terminal_inferior (); if (async_exec) - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); + { + /* The user requested an `attach&', so be sure to leave threads + that didn't get a signal running. */ + + /* Immediatelly resume all suspended threads of this inferior, + and this inferior only. This should have no effect on + already running threads. If a thread has been stopped with a + signal, leave it be. */ + if (non_stop) + proceed_after_attach (inferior->pid); + else + { + if (inferior_thread ()->stop_signal == TARGET_SIGNAL_0) + { + clear_proceed_status (); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); + } + } + } else { + /* The user requested a plain `attach', so be sure to leave + the inferior stopped. */ + if (target_can_async_p ()) async_enable_stdin (); + + /* At least the current thread is already stopped. */ + + /* In all-stop, by definition, all threads have to be already + stopped at this point. In non-stop, however, although the + selected thread is stopped, others may still be executing. + Be sure to explicitly stop all threads of the process. This + should have no effect on already stopped threads. */ + if (non_stop) + target_stop (pid_to_ptid (inferior->pid)); + + /* Tell the user/frontend where we're stopped. */ normal_stop (); if (deprecated_attach_hook) deprecated_attach_hook (); @@ -2008,12 +2259,17 @@ attach_command (char *args, int from_tty) char *exec_file; char *full_exec_path = NULL; int async_exec = 0; + struct cleanup *back_to = make_cleanup (null_cleanup, NULL); dont_repeat (); /* Not for the faint of heart */ - if (target_has_execution) + if (gdbarch_has_global_solist (target_gdbarch)) + /* Don't complain if all processes share the same symbol + space. */ + ; + else if (target_has_execution) { - if (query ("A program is being debugged already. Kill it? ")) + if (query (_("A program is being debugged already. Kill it? "))) target_kill (); else error (_("Not killed.")); @@ -2042,6 +2298,7 @@ attach_command (char *args, int from_tty) { /* Simulate synchronous execution */ async_disable_stdin (); + make_cleanup ((make_cleanup_ftype *)async_enable_stdin, NULL); } target_attach (args, from_tty); @@ -2055,16 +2312,33 @@ attach_command (char *args, int from_tty) init_wait_for_inferior (); clear_proceed_status (); + if (non_stop) + { + /* If we find that the current thread isn't stopped, explicitly + do so now, because we're going to install breakpoints and + poke at memory. */ + + if (async_exec) + /* The user requested an `attach&'; stop just one thread. */ + target_stop (inferior_ptid); + else + /* The user requested an `attach', so stop all threads of this + inferior. */ + target_stop (pid_to_ptid (ptid_get_pid (inferior_ptid))); + } + /* Some system don't generate traps when attaching to inferior. E.g. Mach 3 or GNU hurd. */ if (!target_attach_no_wait) { + struct inferior *inferior = current_inferior (); + /* Careful here. See comments in inferior.h. Basically some OSes don't ignore SIGSTOPs on continue requests anymore. We need a way for handle_inferior_event to reset the stop_signal variable after an attach, and this is what STOP_QUIETLY_NO_SIGSTOP is for. */ - stop_soon = STOP_QUIETLY_NO_SIGSTOP; + inferior->stop_soon = STOP_QUIETLY_NO_SIGSTOP; if (target_can_async_p ()) { @@ -2075,8 +2349,9 @@ attach_command (char *args, int from_tty) a->args = xstrdup (args); a->from_tty = from_tty; a->async_exec = async_exec; - add_continuation (attach_command_continuation, a, - attach_command_continuation_free_args); + add_inferior_continuation (attach_command_continuation, a, + attach_command_continuation_free_args); + discard_cleanups (back_to); return; } @@ -2084,6 +2359,73 @@ attach_command (char *args, int from_tty) } attach_command_post_wait (args, from_tty, async_exec); + discard_cleanups (back_to); +} + +/* We had just found out that the target was already attached to an + inferior. PTID points at a thread of this new inferior, that is + the most likely to be stopped right now, but not necessarily so. + The new inferior is assumed to be already added to the inferior + list at this point. If LEAVE_RUNNING, then leave the threads of + this inferior running, except those we've explicitly seen reported + as stopped. */ + +void +notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) +{ + struct cleanup* old_chain; + int async_exec; + + old_chain = make_cleanup (null_cleanup, NULL); + + /* 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 + resume threads with such a stop signal. */ + async_exec = non_stop; + + if (!ptid_equal (inferior_ptid, null_ptid)) + make_cleanup_restore_current_thread (); + + switch_to_thread (ptid); + + /* When we "notice" a new inferior we need to do all the things we + would normally do if we had just attached to it. */ + + if (is_executing (inferior_ptid)) + { + struct inferior *inferior = current_inferior (); + + /* We're going to install breakpoints, and poke at memory, + ensure that the inferior is stopped for a moment while we do + that. */ + target_stop (inferior_ptid); + + inferior->stop_soon = STOP_QUIETLY_REMOTE; + + /* Wait for stop before proceeding. */ + if (target_can_async_p ()) + { + struct attach_command_continuation_args *a; + + a = xmalloc (sizeof (*a)); + a->args = xstrdup (""); + a->from_tty = from_tty; + a->async_exec = async_exec; + add_inferior_continuation (attach_command_continuation, a, + attach_command_continuation_free_args); + + do_cleanups (old_chain); + return; + } + else + wait_for_inferior (0); + } + + async_exec = leave_running; + attach_command_post_wait ("" /* args */, from_tty, async_exec); + + do_cleanups (old_chain); } /* @@ -2097,13 +2439,26 @@ attach_command (char *args, int from_tty) * started via the normal ptrace (PTRACE_TRACEME). */ -static void +void detach_command (char *args, int from_tty) { dont_repeat (); /* Not for the faint of heart. */ + + if (ptid_equal (inferior_ptid, null_ptid)) + error (_("The program is not being run.")); + target_detach (args, from_tty); - no_shared_libraries (NULL, from_tty); - init_thread_list (); + + /* 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)) + no_shared_libraries (NULL, from_tty); + + /* If we still have inferiors to debug, then don't mess with their + threads. */ + if (!have_inferiors ()) + init_thread_list (); + if (deprecated_detach_hook) deprecated_detach_hook (); } @@ -2136,6 +2491,15 @@ interrupt_target_1 (int all_threads) else ptid = inferior_ptid; target_stop (ptid); + + /* Tag the thread as having been explicitly requested to stop, so + other parts of gdb know not to resume this thread automatically, + if it was stopped due to an internal event. Limit this to + non-stop mode, as when debugging a multi-threaded application in + all-stop mode, we will only get one stop event --- it's undefined + which thread will report the event. */ + if (non_stop) + set_stop_requested (ptid, 1); } /* Stop the execution of the target while running in async mode, in @@ -2165,9 +2529,11 @@ interrupt_target_command (char *args, int from_tty) } static void -print_float_info (struct gdbarch *gdbarch, struct ui_file *file, +print_float_info (struct ui_file *file, struct frame_info *frame, const char *args) { + struct gdbarch *gdbarch = get_frame_arch (frame); + if (gdbarch_print_float_info_p (gdbarch)) gdbarch_print_float_info (gdbarch, file, frame, args); else @@ -2198,8 +2564,7 @@ float_info (char *args, int from_tty) if (!target_has_registers) error (_("The program has no registers now.")); - print_float_info (current_gdbarch, gdb_stdout, - get_selected_frame (NULL), args); + print_float_info (gdb_stdout, get_selected_frame (NULL), args); } static void @@ -2274,6 +2639,9 @@ fully linked executable files and separately compiled object files as needed."), &showlist); set_cmd_completer (c, noop_completer); + add_com ("kill", class_run, kill_command, + _("Kill execution of program being debugged.")); + add_com ("attach", class_run, attach_command, _("\ Attach to a process or file outside of GDB.\n\ This command attaches to another target, of the same type as your last\n\