2014-05-21 Pedro Alves <palves@redhat.com>
+ * inf-child.c (inf_child_ops, inf_child_explicitly_opened): New
+ globals.
+ (inf_child_open_target): New function.
+ (inf_child_open): Use inf_child_open_target to push the target
+ instead of erroring out.
+ (inf_child_disconnect, inf_child_close)
+ (inf_child_maybe_unpush_target): New functions.
+ (inf_child_target): Install inf_child_disconnect and
+ inf_child_close. Store a pointer to the returned object.
+ * inf-child.h (inf_child_open_target, inf_child_maybe_unpush): New
+ declarations.
+ * target.c (auto_connect_native_target): New global.
+ (show_default_run_target): New function.
+ (find_default_run_target): Return NULL if automatically connecting
+ to the native target is disabled.
+ (_initialize_target): Install set/show auto-connect-native-target.
+ * NEWS: Mention "set auto-connect-native-target", and "target
+ native".
+ * linux-nat.c (super_close): New global.
+ (linux_nat_close): Call super_close.
+ (linux_nat_add_target): Store a pointer to the base class's
+ to_close method.
+ * inf-ptrace.c (inf_ptrace_mourn_inferior, inf_ptrace_detach): Use
+ inf_child_maybe_unpush.
+ * inf-ttrace.c (inf_ttrace_him): Don't push the target if it is
+ already pushed.
+ (inf_ttrace_mourn_inferior): Only unpush the target after mourning
+ the inferior. Use inf_child_maybe_unpush_target.
+ (inf_ttrace_attach): Don't push the target if it is already
+ pushed.
+ (inf_ttrace_detach): Use inf_child_maybe_unpush_target.
+ * darwin-nat.c (darwin_mourn_inferior): Only unpush the target
+ after mourning the inferior. Use inf_child_maybe_unpush_target.
+ (darwin_attach_pid): Don't push the target if it is already
+ pushed.
+ * gnu-nat.c (gnu_mourn_inferior): Only unpush the target after
+ mourning the inferior. Use inf_child_maybe_unpush_target.
+ (gnu_detach): Use inf_child_maybe_unpush_target.
+ * go32-nat.c (go32_create_inferior): Don't push the target if it
+ is already pushed.
+ (go32_mourn_inferior): Use inf_child_maybe_unpush_target.
+ * nto-procfs.c (procfs_is_nto_target): Adjust comment.
+ (procfs_open): Rename to ...
+ (procfs_open_1): ... this. Add target_ops parameter. Adjust
+ comments. Can target_preopen before changing node. Call
+ inf_child_open_target to push the target explicitly.
+ (procfs_attach): Don't push the target if it is already pushed.
+ (procfs_detach): Use inf_child_maybe_unpush_target.
+ (procfs_create_inferior): Don't push the target if it is already
+ pushed.
+ (nto_native_ops): New global.
+ (procfs_open): Reimplement.
+ (procfs_native_open): New function.
+ (init_procfs_targets): Install procfs_native_open as to_open of
+ "target native". Store a pointer to the "native" target in
+ nto_native_ops.
+ * procfs.c (procfs_attach): Don't push the target if it is already
+ pushed.
+ (procfs_detach): Use inf_child_maybe_unpush_target.
+ (procfs_mourn_inferior): Only unpush the target after mourning the
+ inferior. Use inf_child_maybe_unpush_target.
+ (procfs_init_inferior): Don't push the target if it is already
+ pushed.
+ * windows-nat.c (do_initial_windows_stuff): Don't push the target
+ if it is already pushed.
+
+2014-05-21 Pedro Alves <palves@redhat.com>
+
* NEWS: Mention that the "child", "GNU, "djgpp", "darwin-child"
and "procfs" targets are now called "native" instead.
the user manual for more details on descriptive types and the intended
usage of this option.
+set auto-connect-native-target
+
+ Control whether GDB is allowed to automatically connect to the
+ native target for the run, attach, etc. commands when not connected
+ to any target yet. See also "target native" below.
+
* New features in the GDB remote stub, GDBserver
** New option --debug-format=option1[,option2,...] allows one to add
commands: "help target", "info target", "info files", "maint print
target-stack".
+* The "target native" command now connects to the native target. This
+ can be used to launch native programs even when "set
+ auto-connect-native-target" is set to off.
+
* New remote packets
qXfer:btrace:read's annex
mach_port_t prev;
int i;
- unpush_target (darwin_ops);
-
/* Deallocate threads. */
if (inf->private->threads)
{
inf->private = NULL;
generic_mourn_inferior ();
+ inf_child_maybe_unpush_target (ops);
}
static void
"returned: %d"),
kret);
- push_target (darwin_ops);
+ if (!target_is_pushed (darwin_ops))
+ push_target (darwin_ops);
}
static void
+2014-05-21 Pedro Alves <palves@redhat.com>
+
+ * gdb.texinfo (Starting): Document "set/show
+ auto-connect-native-target".
+ (Target Commands): Document "target native".
+
2014-05-20 Pedro Alves <palves@redhat.com>
* gdb.texinfo (Memory) <compare-sections>: Generalize comments to
$@file{.zshenv} for the Z shell, or the file specified in the
@samp{BASH_ENV} environment variable for BASH.
+@anchor{set auto-connect-native-target}
+@kindex set auto-connect-native-target
+@item set auto-connect-native-target
+@itemx set auto-connect-native-target on
+@itemx set auto-connect-native-target off
+@itemx show auto-connect-native-target
+
+By default, if not connected to any target yet (e.g., with
+@code{target remote}), the @code{run} command starts your program as a
+native process under @value{GDBN}, on your local machine. If you're
+sure you don't want to debug programs on your local machine, you can
+tell @value{GDBN} to not connect to the native target automatically
+with the @code{set auto-connect-native-target off} command.
+
+If @code{on}, which is the default, and if @value{GDBN} is not
+connected to a target already, the @code{run} command automaticaly
+connects to the native target, if one is available.
+
+If @code{off}, and if @value{GDBN} is not connected to a target
+already, the @code{run} command fails with an error:
+
+@smallexample
+(@value{GDBP}) run
+Don't know how to run. Try "help target".
+@end smallexample
+
+If @value{GDBN} is already connected to a target, @value{GDBN} always
+uses it with the @code{run} command.
+
+In any case, you can explicitly connect to the native target with the
+@code{target native} command. For example,
+
+@smallexample
+(@value{GDBP}) set auto-connect-native-target off
+(@value{GDBP}) run
+Don't know how to run. Try "help target".
+(@value{GDBP}) target native
+(@value{GDBP}) run
+Starting program: ./a.out
+[Inferior 1 (process 10421) exited normally]
+@end smallexample
+
+In case you connected explicitly to the @code{native} target,
+@value{GDBN} remains connected even if all inferiors exit, ready for
+the next @code{run} command. Use the @code{disconnect} command to
+disconnect.
+
+Examples of other commands that likewise respect the
+@code{auto-connect-native-target} setting: @code{attach}, @code{info
+proc}, @code{info os}.
+
@kindex set disable-randomization
@item set disable-randomization
@itemx set disable-randomization on
see the appropriate section in @ref{Embedded Processors, ,Embedded
Processors}.
+@item target native
+@cindex native target
+Setup for local/native process debugging. Useful to make the
+@code{run} command spawn native processes (likewise @code{attach},
+etc.@:) even when @code{set auto-connect-native-target} is @code{off}
+(@pxref{set auto-connect-native-target}).
+
@end table
Different targets are available on different configurations of @value{GDBN};
{
inf_debug (gnu_current_inf, "rip");
inf_detach (gnu_current_inf);
- unpush_target (ops);
generic_mourn_inferior ();
+ inf_child_maybe_unpush_target (ops);
}
\f
inferior_ptid = null_ptid;
detach_inferior (pid);
- unpush_target (ops); /* Pop out of handling an inferior. */
+ inf_child_maybe_unpush_target (ops);
}
\f
static void
inf = current_inferior ();
inferior_appeared (inf, SOME_PID);
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
add_thread_silent (inferior_ptid);
delete_thread_silent (ptid);
prog_has_started = 0;
- unpush_target (ops);
generic_mourn_inferior ();
+ inf_child_maybe_unpush_target (ops);
}
/* Hardware watchpoint support. */
#include <fcntl.h>
#include <unistd.h>
+/* A pointer to what is returned by inf_child_target. Used by
+ inf_child_open to push the most-derived target in reaction to
+ "target native". */
+static struct target_ops *inf_child_ops = NULL;
+
/* Helper function for child_wait and the derivatives of child_wait.
HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
translation of that in OURSTATUS. */
{
}
+/* True if the user did "target native". In that case, we won't
+ unpush the child target automatically when the last inferior is
+ gone. */
+static int inf_child_explicitly_opened;
+
+/* See inf-child.h. */
+
+void
+inf_child_open_target (struct target_ops *target, char *arg, int from_tty)
+{
+ target_preopen (from_tty);
+ push_target (target);
+ inf_child_explicitly_opened = 1;
+ if (from_tty)
+ printf_filtered ("Done. Use the \"run\" command to start a process.\n");
+}
+
static void
inf_child_open (char *arg, int from_tty)
{
- error (_("Use the \"run\" command to start a process."));
+ inf_child_open_target (inf_child_ops, arg, from_tty);
+}
+
+/* Implement the to_disconnect target_ops method. */
+
+static void
+inf_child_disconnect (struct target_ops *target, char *args, int from_tty)
+{
+ if (args != NULL)
+ error (_("Argument given to \"disconnect\"."));
+
+ /* This offers to detach/kill current inferiors, and then pops all
+ targets. */
+ target_preopen (from_tty);
+}
+
+/* Implement the to_close target_ops method. */
+
+static void
+inf_child_close (struct target_ops *target)
+{
+ /* In case we were forcibly closed. */
+ inf_child_explicitly_opened = 0;
+}
+
+/* See inf-child.h. */
+
+void
+inf_child_maybe_unpush_target (struct target_ops *ops)
+{
+ if (!inf_child_explicitly_opened && !have_inferiors ())
+ unpush_target (ops);
}
static void
t->to_longname = "Native process";
t->to_doc = "Native process (started by the \"run\" command).";
t->to_open = inf_child_open;
+ t->to_close = inf_child_close;
+ t->to_disconnect = inf_child_disconnect;
t->to_post_attach = inf_child_post_attach;
t->to_fetch_registers = inf_child_fetch_inferior_registers;
t->to_store_registers = inf_child_store_inferior_registers;
t->to_magic = OPS_MAGIC;
t->to_use_agent = inf_child_use_agent;
t->to_can_use_agent = inf_child_can_use_agent;
+
+ /* Store a pointer so we can push the most-derived target from
+ inf_child_open. */
+ inf_child_ops = t;
+
return t;
}
/* This is for native targets which use a unix/POSIX-style waitstatus. */
extern void store_waitstatus (struct target_waitstatus *, int);
+/* This is to be called by the native target's open routine to push
+ the target, in case it need to override to_open. */
+
+extern void inf_child_open_target (struct target_ops *target,
+ char *arg, int from_tty);
+
+/* Unpush the target if it wasn't explicitly open with "target native"
+ and there are no live inferiors left. Note: if calling this as a
+ result of a mourn or detach, the current inferior shall already
+ have its PID cleared, so it isn't counted as live. That's usually
+ done by calling either generic_mourn_inferior or
+ detach_inferior. */
+
+extern void inf_child_maybe_unpush_target (struct target_ops *ops);
+
#endif
generic_mourn_inferior ();
- if (!have_inferiors ())
- unpush_target (ops);
+ inf_child_maybe_unpush_target (ops);
}
/* Attach to the process specified by ARGS. If FROM_TTY is non-zero,
inferior_ptid = null_ptid;
detach_inferior (pid);
- if (!have_inferiors ())
- unpush_target (ops);
+ inf_child_maybe_unpush_target (ops);
}
/* Kill the inferior. */
do_cleanups (old_chain);
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
}
inf_ttrace_page_dict.count = 0;
- unpush_target (ops);
generic_mourn_inferior ();
+ inf_child_maybe_unpush_target (ops);
}
/* Assuming we just attached the debugger to a new inferior, create
(uintptr_t)&tte, sizeof tte, 0) == -1)
perror_with_name (("ttrace"));
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
inf_ttrace_create_threads_after_attach (pid);
}
inferior_ptid = null_ptid;
detach_inferior (pid);
- unpush_target (ops);
+ inf_child_maybe_unpush_target (ops);
}
static void
Called by our to_xfer_partial. */
static target_xfer_partial_ftype *super_xfer_partial;
+/* The saved to_close method, inherited from inf-ptrace.c.
+ Called by our to_close. */
+static void (*super_close) (struct target_ops *);
+
static unsigned int debug_linux_nat;
static void
show_debug_linux_nat (struct ui_file *file, int from_tty,
if (linux_ops->to_close)
linux_ops->to_close (linux_ops);
+
+ super_close (self);
}
/* When requests are passed down from the linux-nat layer to the
t->to_async = linux_nat_async;
t->to_terminal_inferior = linux_nat_terminal_inferior;
t->to_terminal_ours = linux_nat_terminal_ours;
+
+ super_close = t->to_close;
t->to_close = linux_nat_close;
/* Methods for non-stop support. */
static procfs_run run;
-static void procfs_open (char *, int);
-
static ptid_t do_attach (ptid_t ptid);
static int procfs_can_use_hw_breakpoint (struct target_ops *self,
static int procfs_stopped_by_watchpoint (struct target_ops *ops);
-/* These two globals are only ever set in procfs_open(), but are
+/* These two globals are only ever set in procfs_open_1, but are
referenced elsewhere. 'nto_procfs_node' is a flag used to say
whether we are local, or we should get the current node descriptor
for the remote QNX node. */
return GDB_OSABI_QNXNTO;
}
-/* This is called when we call 'target procfs <arg>' from the (gdb) prompt.
- For QNX6 (nto), the only valid arg will be a QNX node string,
- eg: "/net/some_node". If arg is not a valid QNX node, we will
- default to local. */
+/* This is called when we call 'target native' or 'target procfs
+ <arg>' from the (gdb) prompt. For QNX6 (nto), the only valid arg
+ will be a QNX node string, eg: "/net/some_node". If arg is not a
+ valid QNX node, we will default to local. */
static void
-procfs_open (char *arg, int from_tty)
+procfs_open_1 (struct target_ops *ops, char *arg, int from_tty)
{
char *nodestr;
char *endstr;
procfs_sysinfo *sysinfo;
struct cleanup *cleanups;
+ /* Offer to kill previous inferiors before opening this target. */
+ target_preopen (from_tty);
+
nto_is_nto_target = procfs_is_nto_target;
/* Set the default node used for spawning to this one,
}
}
do_cleanups (cleanups);
+
+ inf_child_open_target (ops, arg, from_tty);
printf_filtered ("Debugging using %s\n", nto_procfs_path);
}
inferior_appeared (inf, pid);
inf->attach_flag = 1;
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
procfs_find_new_threads (ops);
}
inferior_ptid = null_ptid;
detach_inferior (pid);
init_thread_list ();
- unpush_target (ops); /* Pop out of handling an inferior. */
+ inf_child_maybe_unpush_target (ops);
}
static int
}
inferior_ptid = null_ptid;
init_thread_list ();
- unpush_target (ops);
generic_mourn_inferior ();
+ inf_child_maybe_unpush_target (ops);
}
/* This function breaks up an argument string into an argument
/* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
errn, strerror(errn) ); */
}
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
target_terminal_init ();
if (exec_bfd != NULL
/* "target procfs". */
static struct target_ops nto_procfs_ops;
+/* "target native". */
+static struct target_ops *nto_native_ops;
+
+/* to_open implementation for "target procfs". */
+
+static void
+procfs_open (char *arg, int from_tty)
+{
+ procfs_open_1 (&nto_procfs_ops, arg, from_tty);
+}
+
+/* to_open implementation for "target native". */
+
+static void
+procfs_native_open (char *arg, int from_tty)
+{
+ procfs_open_1 (nto_native_ops, arg, from_tty);
+}
+
/* Create the "native" and "procfs" targets. */
static void
/* Leave to_shortname as "native". */
t->to_longname = "QNX Neutrino local process";
t->to_doc = "QNX Neutrino local process (started by the \"run\" command).";
- t->to_open = procfs_open;
+ t->to_open = procfs_native_open;
t->to_attach = procfs_attach;
t->to_post_attach = procfs_post_attach;
t->to_detach = procfs_detach;
t->to_have_continuable_watchpoint = 1;
t->to_extra_thread_info = nto_extra_thread_info;
+ nto_native_ops = t;
+
/* Register "target native". This is the default run target. */
add_target (t);
nto_procfs_ops.to_can_run = procfs_can_run;
t->to_longname = "QNX Neutrino local or remote process";
t->to_doc = "QNX Neutrino process. target procfs <node>";
+ t->to_open = procfs_open;
+
add_target (&nto_procfs_ops);
}
fflush (stdout);
}
inferior_ptid = do_attach (pid_to_ptid (pid));
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
}
static void
inferior_ptid = null_ptid;
detach_inferior (pid);
- unpush_target (ops);
+ inf_child_maybe_unpush_target (ops);
}
static ptid_t
if (pi)
destroy_procinfo (pi);
}
- unpush_target (ops);
+
+ generic_mourn_inferior ();
if (dbx_link_bpt != NULL)
{
dbx_link_bpt = NULL;
}
- generic_mourn_inferior ();
+ inf_child_maybe_unpush_target (ops);
}
/* When GDB forks to create a runnable inferior process, this function
/* This routine called on the parent side (GDB side)
after GDB forks the inferior. */
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
if ((pi = create_procinfo (pid, 0)) == NULL)
perror (_("procfs: out of memory in 'init_inferior'"));
internal_error (__FILE__, __LINE__, _("No targets found"));
}
+/* Whether GDB is allowed to fall back to the default run target for
+ "run", "attach", etc. when no target is connected yet. */
+static int auto_connect_native_target = 1;
+
+static void
+show_auto_connect_native_target (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file,
+ _("Whether GDB may automatically connect to the "
+ "native target is %s.\n"),
+ value);
+}
+
/* Look through the list of possible targets for a target that can
execute a run or attach command without any other data. This is
used to locate the default process stratum.
static struct target_ops *
find_default_run_target (char *do_mesg)
{
- struct target_ops **t;
struct target_ops *runable = NULL;
- int count;
- count = 0;
-
- for (t = target_structs; t < target_structs + target_struct_size;
- ++t)
+ if (auto_connect_native_target)
{
- if ((*t)->to_can_run != delegate_can_run && target_can_run (*t))
+ struct target_ops **t;
+ int count = 0;
+
+ for (t = target_structs; t < target_structs + target_struct_size;
+ ++t)
{
- runable = *t;
- ++count;
+ if ((*t)->to_can_run != delegate_can_run && target_can_run (*t))
+ {
+ runable = *t;
+ ++count;
+ }
}
+
+ if (count != 1)
+ runable = NULL;
}
- if (count != 1)
+ if (runable == NULL)
{
if (do_mesg)
error (_("Don't know how to %s. Try \"help target\"."), do_mesg);
Otherwise, any attempt to interrupt or stop will be ignored."),
set_target_permissions, NULL,
&setlist, &showlist);
+
+ add_setshow_boolean_cmd ("auto-connect-native-target", class_support,
+ &auto_connect_native_target, _("\
+Set whether GDB may automatically connect to the native target."), _("\
+Show whether GDB may automatically connect to the native target."), _("\
+When on, and GDB is not connected to a target yet, GDB\n\
+attempts \"run\" and other commands with the native target."),
+ NULL, show_auto_connect_native_target,
+ &setlist, &showlist);
}
2014-05-21 Pedro Alves <palves@redhat.com>
+ * boards/gdbserver-base.exp (GDBFLAGS): Set to "set
+ auto-connect-native-target off".
+ * gdb.base/auto-connect-native-target.c: New file.
+ * gdb.base/auto-connect-native-target.exp: New file.
+
+2014-05-21 Pedro Alves <palves@redhat.com>
+
* gdb.base/default.exp: Test "target native" instead of "target
child".
# The predefined TSVs in GDBserver.
set_board_info gdb,predefined_tsv "\\\$trace_timestamp"
+set GDBFLAGS "${GDBFLAGS} -ex \"set auto-connect-native-target off\""
+
proc ${board}_file { dest op args } {
if { $op == "delete" } {
return 0
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main ()
+{
+ return 0;
+}
+
--- /dev/null
+# Copyright 2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test "set auto-connect-native-target off" and "target native" on
+# native targets.
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+ return -1
+}
+
+# Whether this GDB is configured with a "native" target.
+set have_native 0
+
+set test "help target native"
+gdb_test_multiple $test $test {
+ -re "Undefined target command.* $gdb_prompt $" {
+ set have_native 0
+ }
+ -re "Native process.*$gdb_prompt $" {
+ set have_native 1
+ }
+}
+
+if { !$have_native } {
+ unsupported "No \"target native\" support."
+ return
+}
+
+# Returns the topmost target pushed on the target stack. TEST is used
+# as test message.
+
+proc get_topmost_target {test} {
+ global gdb_prompt
+
+ set topmost "unknown"
+
+ gdb_test_multiple "maint print target-stack" $test {
+ -re "The current target stack is:\r\n - (\[^ \]+) .*$gdb_prompt $" {
+ set topmost $expect_out(1,string)
+ pass $test
+ }
+ }
+
+ return $topmost
+}
+
+set topmost [get_topmost_target "check whether a target is already connected"]
+
+# Testing against the extended-remote board, for example?
+if { $topmost != "exec" } {
+ unsupported "Already connected to target $topmost."
+ return
+}
+
+# Check which target this board connects to. If testing with a native
+# target board, this should cause the native target to auto connect.
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+# Returns true if the native target is pushed on the target stack.
+# TEST is used as test message.
+
+proc check_native_target {test} {
+ global gdb_prompt
+
+ gdb_test_multiple "maint print target-stack" $test {
+ -re " native .*$gdb_prompt $" {
+ pass $test
+ return 1
+ }
+ -re "$gdb_prompt $" {
+ pass $test
+ }
+ }
+
+ return 0
+}
+
+# Testing against a remote board, for example?
+if { ![check_native_target "check whether board tests the native target"] } {
+ unsupported "Not testing the native target."
+ return
+}
+
+# Kill program. TEST is used as test message.
+
+proc kill_program {test} {
+ global gdb_prompt
+
+ gdb_test_multiple "kill" $test {
+ -re "Kill the program being debugged\\? .y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "$gdb_prompt $" {
+ pass $test
+ }
+ }
+}
+
+# Kill the program. This should pop the target. The "start" test
+# below will fail otherwise.
+kill_program "kill"
+
+# Now prevent the native target from auto connecting.
+gdb_test_no_output "set auto-connect-native-target off"
+
+# Commands that rely on the native target auto-connecting should no longer work.
+gdb_test "start" "Don't know how to run.*" "start no longer works"
+
+# Explicitly connect to the native target.
+gdb_test "target native" \
+ "Done. Use the \"run\" command to start a process.*" \
+ "explicitly connect to the native target"
+
+proc test_native_target_remains_pushed {} {
+ gdb_test "maint print target-stack" \
+ "The current target stack is:\r\n .* native .* exec .*" \
+ "native target remains pushed"
+}
+
+# Test a set of "inferior gone" scenarios, making sure the target
+# remains pushed.
+
+with_test_prefix "kill" {
+ gdb_test "start" "main.*" "start"
+
+ kill_program "kill"
+
+ test_native_target_remains_pushed
+}
+
+with_test_prefix "detach" {
+ gdb_test "start" "main.*"
+
+ set test "detach"
+ gdb_test_multiple $test $test {
+ -re "Detach the program being debugged\\? .y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "$gdb_prompt $" {
+ pass $test
+ }
+ }
+
+ test_native_target_remains_pushed
+}
+
+with_test_prefix "run to exit" {
+ gdb_test "start" "Temporary breakpoint .* main .*"
+
+ gdb_test "c" "$inferior_exited_re normally.*"
+
+ test_native_target_remains_pushed
+}
+
+# Now test disconnecting. Commands that rely on the native target
+# auto-connecting should no longer work (again) after this.
+
+with_test_prefix "disconnect" {
+ gdb_test "start" "Temporary breakpoint .* main .*"
+
+ set test "disconnect"
+ gdb_test_multiple $test $test {
+ -re "A program is being debugged already.* .y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "$gdb_prompt $" {
+ pass $test
+ }
+ }
+
+ set topmost \
+ [get_topmost_target "check whether the target is no longer connected"]
+
+ set test "no longer connected to a target"
+ if { $topmost == "exec" } {
+ pass $test
+ } else {
+ fail $test
+ }
+
+ gdb_test "start" "Don't know how to run.*" "start no longer works"
+}
+
+# Reenable auto-connecting to the native target. Plain "start" should
+# start working again.
+gdb_test_no_output "set auto-connect-native-target on"
+
+gdb_test "start" "Temporary breakpoint .* main .*" \
+ "start auto-connects to the native target after reenabling auto-connect"
#endif
current_event.dwProcessId = pid;
memset (¤t_event, 0, sizeof (current_event));
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
disable_breakpoints_in_shlibs ();
windows_clear_solib ();
clear_proceed_status ();
inferior_ptid = null_ptid;
detach_inferior (current_event.dwProcessId);
- unpush_target (ops);
+ inf_child_maybe_unpush_target (ops);
}
/* Try to determine the executable filename.
CHECK (CloseHandle (current_process_handle));
open_process_used = 0;
}
- unpush_target (ops);
generic_mourn_inferior ();
+ inf_child_maybe_unpush_target (ops);
}
/* Send a SIGINT to the process group. This acts just like the user typed a