X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfcmd.c;h=9cad3cb18652673fe47f047db94636ae954b21eb;hb=d729566a19c83c452f3a962182d1c6d349562159;hp=06e3bc5fc311cf0742a25ef4b9247c476632845f;hpb=252fbfc86a997c0750804d5cdd3ae395d24bebc4;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 06e3bc5fc3..9cad3cb186 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); @@ -167,11 +166,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. */ @@ -269,7 +263,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 +283,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 +391,9 @@ post_create_inferior (struct target_ops *target, int from_tty) don't need to. */ target_find_description (); - if (exec_bfd) + /* 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 +405,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 @@ -425,8 +436,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 +451,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 +541,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) @@ -570,6 +598,15 @@ 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; @@ -579,6 +616,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) { @@ -600,6 +646,7 @@ continue_1 (int all_threads) } else { + ensure_valid_thread (); ensure_not_running (); clear_proceed_status (); proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); @@ -744,6 +791,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) @@ -774,67 +822,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--) { - 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); @@ -868,7 +890,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; @@ -880,18 +903,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; if (count > 0) { @@ -903,13 +924,14 @@ step_once (int skip_subroutines, int single_inst, int count, int 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); if (!single_inst) { - find_pc_line_pc_range (stop_pc, + 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. */ @@ -920,7 +942,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread) 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")); @@ -948,12 +970,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); + } } } @@ -971,6 +1002,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. */ @@ -1004,7 +1036,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.")); @@ -1018,7 +1050,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 */ @@ -1072,6 +1104,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. */ @@ -1120,11 +1153,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 @@ -1152,7 +1181,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) @@ -1282,6 +1311,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); @@ -1289,7 +1320,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); @@ -1322,13 +1354,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) @@ -1345,22 +1380,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); } @@ -1373,11 +1401,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.")); @@ -1394,7 +1424,7 @@ 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) { /* Set breakpoint and continue. */ breakpoint = @@ -1443,8 +1473,6 @@ finish_forward (struct symbol *function, struct frame_info *frame) 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)); @@ -1557,8 +1585,7 @@ program_info (char *args, int from_tty) stat = bpstat_num (&bs, &num); target_files_info (); - printf_filtered (_("Program stopped at %s.\n"), - hex_string ((unsigned long) stop_pc)); + 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) @@ -1803,9 +1830,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++) @@ -1821,16 +1851,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); } } @@ -1896,12 +1933,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 @@ -1911,21 +1950,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; @@ -2011,6 +2035,48 @@ vector_info (char *args, 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 + 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: * Should save/restore the tty state since it might be that the @@ -2075,11 +2141,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 (); @@ -2114,12 +2213,16 @@ 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 (target_supports_multi_process ()) + /* Don't complain if we can be attached to multiple processes. */ + ; + 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.")); @@ -2148,6 +2251,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); @@ -2161,6 +2265,21 @@ 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) @@ -2183,9 +2302,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; } @@ -2193,6 +2312,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); } /* @@ -2206,13 +2392,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 the current target interface claims there's still execution, + then don't mess with threads of other processes. */ + if (!target_has_execution) + init_thread_list (); + if (deprecated_detach_hook) deprecated_detach_hook (); }