X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Finfcmd.c;h=53fb3b406971d691ccd2e993e42eeb36d59c72e2;hb=6c95b8df7fef5273da71c34775918c554aae0ea8;hp=1854985d47f4353fd758088a62a4a745acde2258;hpb=74531fed1f2d662debc2c209b8b3faddceb55960;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 1854985d47..53fb3b4069 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. @@ -20,6 +20,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "arch-utils.h" #include #include "gdb_string.h" #include "symtab.h" @@ -51,6 +52,8 @@ #include "exceptions.h" #include "cli/cli-decode.h" #include "gdbthread.h" +#include "valprint.h" +#include "inline-frame.h" /* Functions exported for general use, in inferior.h: */ @@ -85,8 +88,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); @@ -167,11 +168,6 @@ int stopped_by_random_signal; 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. */ @@ -184,7 +180,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 * @@ -200,8 +196,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); } @@ -253,7 +248,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; @@ -269,7 +264,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; @@ -289,9 +284,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; + } } } } @@ -385,7 +392,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 @@ -397,7 +409,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 @@ -407,6 +422,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); } @@ -425,8 +452,8 @@ 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 (); } @@ -440,6 +467,8 @@ 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 (); @@ -528,14 +557,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) @@ -588,6 +632,15 @@ proceed_thread_callback (struct thread_info *thread, void *arg) 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) { @@ -609,6 +662,7 @@ continue_1 (int all_threads) } else { + ensure_valid_thread (); ensure_not_running (); clear_proceed_status (); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); @@ -668,14 +722,14 @@ Can't resume all threads and specify proceed count simultaneously.")); struct thread_info *tp; if (non_stop) - tp = find_thread_pid (inferior_ptid); + 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_pid (last_ptid); + tp = find_thread_ptid (last_ptid); } if (tp != NULL) bs = tp->stop_bpstat; @@ -706,6 +760,17 @@ Can't resume all threads and specify proceed count simultaneously.")); continue_1 (all_threads); } +/* Record the starting point of a "step" or "next" command. */ + +static void +set_step_frame (void) +{ + struct symtab_and_line sal; + + find_frame_sal (get_current_frame (), &sal); + set_step_info (get_current_frame (), sal); +} + /* Step until outside of current statement. */ static void @@ -753,6 +818,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) @@ -778,72 +844,46 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) if (in_thread_list (inferior_ptid)) thread = pid_to_thread_id (inferior_ptid); - set_longjmp_breakpoint (); + set_longjmp_breakpoint (thread); 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--) { - struct thread_info *tp = inferior_thread (); - clear_proceed_status (); - - frame = get_current_frame (); - tp->step_frame_id = get_frame_id (frame); + struct thread_info *tp; + step_once (skip_subroutines, single_inst, count, thread); - if (!single_inst) - { - find_pc_line_pc_range (stop_pc, - &tp->step_range_start, &tp->step_range_end); - if (tp->step_range_end == 0) - { - char *name; - if (find_pc_partial_function (stop_pc, &name, - &tp->step_range_start, - &tp->step_range_end) == 0) - error (_("Cannot find bounds of current function")); - - 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. */ - 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. */ - tp->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) - tp->step_over_calls = STEP_OVER_ALL; - - tp->step_multi = (count > 1); - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); - - if (!target_has_execution - || !inferior_thread ()->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); @@ -877,7 +917,8 @@ step_1_continuation (void *args) { /* 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); + step_once (a->skip_subroutines, a->single_inst, + a->count - 1, a->thread); return; } tp->step_multi = 0; @@ -889,18 +930,16 @@ step_1_continuation (void *args) 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; + struct frame_info *frame = get_current_frame (); if (count > 0) { @@ -910,26 +949,36 @@ step_once (int skip_subroutines, int single_inst, int count, int thread) 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")); - tp->step_frame_id = get_frame_id (frame); + set_step_frame (); if (!single_inst) { - find_pc_line_pc_range (stop_pc, + CORE_ADDR pc; + + /* Step at an inlined function behaves like "down". */ + if (!skip_subroutines && !single_inst + && inline_skipped_frames (inferior_ptid)) + { + step_into_inline_frame (inferior_ptid); + if (count > 1) + step_once (skip_subroutines, single_inst, count - 1, thread); + else + /* Pretend that we've stopped. */ + normal_stop (); + return; + } + + 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 (tp->step_range_end == 0 && step_stop_if_no_debug) - { - tp->step_range_start = tp->step_range_end = 1; - } + tp->step_range_start = tp->step_range_end = 1; else if (tp->step_range_end == 0) { char *name; - if (find_pc_partial_function (stop_pc, &name, + if (find_pc_partial_function (pc, &name, &tp->step_range_start, &tp->step_range_end) == 0) error (_("Cannot find bounds of current function")); @@ -957,12 +1006,21 @@ which has no line number information.\n"), name); 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 (tp, 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); + } } } @@ -972,6 +1030,7 @@ which has no line number information.\n"), name); static void 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; @@ -980,6 +1039,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. */ @@ -1013,7 +1073,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.")); @@ -1027,7 +1087,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 */ @@ -1040,7 +1100,7 @@ jump_command (char *arg, int from_tty) if (from_tty) { printf_filtered (_("Continuing at ")); - fputs_filtered (paddress (addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, addr), gdb_stdout); printf_filtered (".\n"); } @@ -1081,6 +1141,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. */ @@ -1129,11 +1190,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 @@ -1154,6 +1211,7 @@ until_next_command (int from_tty) struct thread_info *tp = inferior_thread (); clear_proceed_status (); + set_step_frame (); frame = get_current_frame (); @@ -1161,7 +1219,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) @@ -1183,7 +1241,6 @@ until_next_command (int from_tty) } tp->step_over_calls = STEP_OVER_ALL; - tp->step_frame_id = get_frame_id (frame); tp->step_multi = 0; /* Only one call to proceed */ @@ -1257,7 +1314,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; @@ -1291,6 +1348,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); @@ -1298,7 +1357,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); @@ -1331,13 +1391,16 @@ 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)) - bs = inferior_thread ()->stop_bpstat; + { + tp = inferior_thread (); + bs = tp->stop_bpstat; + } if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL && a->function != NULL) @@ -1354,22 +1417,15 @@ 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 (bs); - 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); } @@ -1382,11 +1438,13 @@ finish_backward (struct symbol *function) struct thread_info *tp = inferior_thread (); struct breakpoint *breakpoint; struct cleanup *old_chain; + CORE_ADDR pc; CORE_ADDR func_addr; int back_up; - if (find_pc_partial_function (get_frame_pc (get_current_frame ()), - NULL, &func_addr, NULL) == 0) + 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.")); @@ -1403,12 +1461,15 @@ finish_backward (struct symbol *function) no way that a function up the stack can have a return address that's equal to its entry point. */ - if (sal.pc != read_pc ()) + if (sal.pc != pc) { + struct frame_info *frame = get_selected_frame (NULL); + struct gdbarch *gdbarch = get_frame_arch (frame); + /* Set breakpoint and continue. */ breakpoint = - set_momentary_breakpoint (sal, - get_frame_id (get_selected_frame (NULL)), + set_momentary_breakpoint (gdbarch, sal, + get_stack_frame_id (frame), bp_breakpoint); /* Tell the breakpoint to keep quiet. We won't be done until we've done another reverse single-step. */ @@ -1437,6 +1498,7 @@ finish_backward (struct symbol *function) static void finish_forward (struct symbol *function, struct frame_info *frame) { + struct gdbarch *gdbarch = get_frame_arch (frame); struct symtab_and_line sal; struct thread_info *tp = inferior_thread (); struct breakpoint *breakpoint; @@ -1446,22 +1508,20 @@ finish_forward (struct symbol *function, struct frame_info *frame) sal = find_pc_line (get_frame_pc (frame), 0); sal.pc = get_frame_pc (frame); - breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), + breakpoint = set_momentary_breakpoint (gdbarch, sal, + get_stack_frame_id (frame), bp_finish); old_chain = make_cleanup_delete_breakpoint (breakpoint); tp->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 (tp, finish_command_continuation, cargs, finish_command_continuation_free_arg); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); discard_cleanups (old_chain); if (!target_can_async_p ()) @@ -1511,6 +1571,36 @@ finish_command (char *arg, int from_tty) clear_proceed_status (); + /* Finishing from an inline frame is completely different. We don't + try to show the "return value" - no way to locate it. So we do + not need a completion. */ + if (get_frame_type (get_selected_frame (_("No selected frame."))) + == INLINE_FRAME) + { + /* Claim we are stepping in the calling frame. An empty step + range means that we will stop once we aren't in a function + 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 thread_info *tp = inferior_thread (); + struct symtab_and_line empty_sal; + init_sal (&empty_sal); + set_step_info (frame, empty_sal); + tp->step_range_start = tp->step_range_end = get_frame_pc (frame); + tp->step_over_calls = STEP_OVER_ALL; + + /* Print info on the selected frame, including level number but not + source. */ + if (from_tty) + { + printf_filtered (_("Run till exit from ")); + print_stack_frame (get_selected_frame (NULL), 1, LOCATION); + } + + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); + return; + } + /* Find the function we will return from. */ function = find_pc_function (get_frame_pc (get_selected_frame (NULL))); @@ -1561,13 +1651,13 @@ program_info (char *args, int from_tty) else if (is_running (ptid)) error (_("Selected thread is running.")); - tp = find_thread_pid (ptid); + 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)); + paddress (target_gdbarch, stop_pc)); if (tp->stop_step) printf_filtered (_("It stopped after being stepped.\n")); else if (stat != 0) @@ -1812,9 +1902,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++) @@ -1830,16 +1923,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); } } @@ -1905,12 +2005,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 @@ -1920,21 +2022,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; @@ -1983,9 +2070,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 @@ -2015,10 +2104,40 @@ 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 @@ -2105,7 +2224,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); @@ -2198,12 +2317,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.")); @@ -2232,6 +2356,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); @@ -2282,9 +2407,9 @@ attach_command (char *args, int from_tty) a->args = xstrdup (args); a->from_tty = from_tty; a->async_exec = async_exec; - add_continuation (inferior_thread (), - 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; } @@ -2292,6 +2417,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); } /* @@ -2305,13 +2497,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 (); } @@ -2382,9 +2587,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 @@ -2415,8 +2622,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 @@ -2491,6 +2697,10 @@ fully linked executable files and separately compiled object files as needed."), &showlist); set_cmd_completer (c, noop_completer); + add_prefix_cmd ("kill", class_run, kill_command, + _("Kill execution of program being debugged."), + &killlist, "kill ", 0, &cmdlist); + 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\