Allow making GDB not automatically connect to the native target.
authorPedro Alves <palves@redhat.com>
Wed, 21 May 2014 17:30:47 +0000 (18:30 +0100)
committerPedro Alves <palves@redhat.com>
Wed, 21 May 2014 17:30:47 +0000 (18:30 +0100)
Sometimes it's useful to be able to disable the automatic connection
to the native target.  E.g., sometimes GDB disconnects from the
extended-remote target I was debugging, without me noticing it, and
then I do "run".  That starts the program locally, and only after a
little head scratch session do I figure out the program is running
locally instead of remotely as intended.  Same thing with "attach",
"info os", etc.

With the patch, we now can have this instead:

 (gdb) set auto-connect-native-target off
 (gdb) target extended-remote :9999
 ...
 *gdb disconnects*
 (gdb) run
 Don't know how to run.  Try "help target".

To still be able to connect to the native target with
auto-connect-native-target set to off, I've made "target native" work
instead of erroring out as today.

Before:

 (gdb) target native
 Use the "run" command to start a native process.

After:

 (gdb) target native
 Done.  Use the "run" command to start a process.
 (gdb) maint print target-stack
 The current target stack is:
   - native (Native process)
   - exec (Local exec file)
   - None (None)
 (gdb) run
 Starting program: ./a.out
 ...

I've also wanted this for the testsuite, when running against the
native-extended-gdbserver.exp board (runs against gdbserver in
extended-remote mode).  With a non-native-target board, it's always a
bug to launch a program with the native target.  Turns out we still
have one such case this patch catches:

 (gdb) break main
 Breakpoint 1 at 0x4009e5: file ../../../src/gdb/testsuite/gdb.base/coremaker.c, line 138.
 (gdb) run
 Don't know how to run.  Try "help target".
 (gdb) FAIL: gdb.base/corefile.exp: run: with core

On the patch itself, probably the least obvious bit is the need to go
through all targets, and move the unpush_target call to after the
generic_mourn_inferior call instead of before.  This is what
inf-ptrace.c does too, ever since multi-process support was added.
The reason inf-ptrace.c does things in that order is that in the
current multi-process/single-target model, we shouldn't unpush the
target if there are still other live inferiors being debugged.  The
check for that is "have_inferiors ()" (a misnomer nowadays...), which
does:

 have_inferiors (void)
 {
   for (inf = inferior_list; inf; inf = inf->next)
     if (inf->pid != 0)
       return 1;

It's generic_mourn_inferior that ends up clearing inf->pid, so we need
to call it before the have_inferiors check.  To make all native
targets behave the same WRT to explicit "target native", I've added an
inf_child_maybe_unpush_target function that targets call instead of
calling unpush_target directly, and as that includes the
have_inferiors check, I needed to adjust the targets.

Tested on x86_64 Fedora 20, native, and also with the
extended-gdbserver board.

Confirmed a cross build of djgpp gdb still builds.

Smoke tested a cross build of Windows gdb under Wine.

Untested otherwise.

gdb/
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.
(windows_detach): Use inf_child_maybe_unpush_target.
(windows_mourn_inferior): Only unpush the target after mourning
the inferior.  Use inf_child_maybe_unpush_target.

gdb/doc/
2014-05-21  Pedro Alves  <palves@redhat.com>

* gdb.texinfo (Starting): Document "set/show
auto-connect-native-target".
(Target Commands): Document "target native".

gdb/testsuite/
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.

20 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/darwin-nat.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/gnu-nat.c
gdb/go32-nat.c
gdb/inf-child.c
gdb/inf-child.h
gdb/inf-ptrace.c
gdb/inf-ttrace.c
gdb/linux-nat.c
gdb/nto-procfs.c
gdb/procfs.c
gdb/target.c
gdb/testsuite/ChangeLog
gdb/testsuite/boards/gdbserver-base.exp
gdb/testsuite/gdb.base/auto-connect-native-target.c [new file with mode: 0644]
gdb/testsuite/gdb.base/auto-connect-native-target.exp [new file with mode: 0644]
gdb/windows-nat.c

index 1c7484311cc168ee21c572ffe5720f389acda79b..ba052db0c90fbf0aeb398cfd0aeea70f79e0fa53 100644 (file)
@@ -1,3 +1,71 @@
+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"
index e5d413002b0608777c95203817048bfd99db8e7c..4663650253e6731756d557e42350c0a333029565 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -61,6 +61,12 @@ maint ada show ignore-descriptive-types
   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
@@ -108,6 +114,10 @@ maint ada show ignore-descriptive-types
   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
index 478429cedcaff4cf868ada57ec6cfdc4ad3d4a74..f3d510dec09c50077da073a7bf1459d99e51e9b1 100644 (file)
@@ -1214,8 +1214,6 @@ darwin_mourn_inferior (struct target_ops *ops)
   mach_port_t prev;
   int i;
 
-  unpush_target (darwin_ops);
-
   /* Deallocate threads.  */
   if (inf->private->threads)
     {
@@ -1271,6 +1269,7 @@ darwin_mourn_inferior (struct target_ops *ops)
   inf->private = NULL;
 
   generic_mourn_inferior ();
+  inf_child_maybe_unpush_target (ops);
 }
 
 static void
@@ -1506,7 +1505,8 @@ impact on the debugging session."));
             "returned: %d"),
           kret);
 
-  push_target (darwin_ops);
+  if (!target_is_pushed (darwin_ops))
+    push_target (darwin_ops);
 }
 
 static void
index 7d0fdbd5711660611305a26b8b86d15b2250ec37..18588f6c7bee1def9ea2143919bbbcd286195594 100644 (file)
@@ -1,3 +1,9 @@
+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
index 6092ff4127be254279d2fa2802adf98824fdd678..47d4bb71f6b971e76d79cb0531e6cc6f293f3a8e 100644 (file)
@@ -2148,6 +2148,57 @@ initialization file---such as @file{.cshrc} for C-shell,
 $@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
@@ -18079,6 +18130,13 @@ provide these.  For info about any processor-specific simulator details,
 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};
index 82358112ee848459cac2490243ed5c662ed71cc8..3317215b17eda28990773d11ccde66f19630c6e8 100644 (file)
@@ -2080,8 +2080,8 @@ gnu_mourn_inferior (struct target_ops *ops)
 {
   inf_debug (gnu_current_inf, "rip");
   inf_detach (gnu_current_inf);
-  unpush_target (ops);
   generic_mourn_inferior ();
+  inf_child_maybe_unpush_target (ops);
 }
 
 \f
@@ -2253,7 +2253,7 @@ gnu_detach (struct target_ops *ops, const char *args, int from_tty)
   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
index e17707ac194d910fb3cd1e1dddd877ff6e07b364..77843ea05c6384ce1e6bd3d764ea0ff11d652ba7 100644 (file)
@@ -710,7 +710,8 @@ go32_create_inferior (struct target_ops *ops, char *exec_file,
   inf = current_inferior ();
   inferior_appeared (inf, SOME_PID);
 
-  push_target (ops);
+  if (!target_is_pushed (ops))
+    push_target (ops);
 
   add_thread_silent (inferior_ptid);
 
@@ -744,8 +745,8 @@ go32_mourn_inferior (struct target_ops *ops)
   delete_thread_silent (ptid);
   prog_has_started = 0;
 
-  unpush_target (ops);
   generic_mourn_inferior ();
+  inf_child_maybe_unpush_target (ops);
 }
 
 /* Hardware watchpoint support.  */
index 8a99adc01c46ac9c88f7e37ed055acc51e346b42..a3c4fe4c445f98c678415a10586bb4d3d8b6c7af 100644 (file)
 #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.  */
@@ -109,10 +114,58 @@ inf_child_prepare_to_store (struct target_ops *self,
 {
 }
 
+/* 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
@@ -410,6 +463,8 @@ inf_child_target (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;
@@ -445,5 +500,10 @@ inf_child_target (void)
   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;
 }
index 4473cff5a8df55a4c2191c700186c7393d8a69bc..3f00ab638916ea96c5842cc95390bbe46c1f97d6 100644 (file)
@@ -30,4 +30,19 @@ extern struct target_ops *inf_child_target (void);
 /* 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
index bffb4bac0311bcf5585bd49bfa6341309ce12a62..cc4921bda4ec37716b049556cf874a0b9fa26038 100644 (file)
@@ -176,8 +176,7 @@ inf_ptrace_mourn_inferior (struct target_ops *ops)
 
   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,
@@ -297,8 +296,7 @@ inf_ptrace_detach (struct target_ops *ops, const char *args, int from_tty)
   inferior_ptid = null_ptid;
   detach_inferior (pid);
 
-  if (!have_inferiors ())
-    unpush_target (ops);
+  inf_child_maybe_unpush_target (ops);
 }
 
 /* Kill the inferior.  */
index 802dc85dd125dae3837a85230dc7094117948e77..96105dcbd0af5b7bc72ac86a48ab4568aa33bf2d 100644 (file)
@@ -644,7 +644,8 @@ inf_ttrace_him (struct target_ops *ops, int pid)
 
   do_cleanups (old_chain);
 
-  push_target (ops);
+  if (!target_is_pushed (ops))
+    push_target (ops);
 
   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
 
@@ -695,8 +696,8 @@ inf_ttrace_mourn_inferior (struct target_ops *ops)
     }
   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
@@ -796,7 +797,8 @@ inf_ttrace_attach (struct target_ops *ops, char *args, int from_tty)
              (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);
 }
@@ -837,7 +839,7 @@ inf_ttrace_detach (struct target_ops *ops, const char *args, int from_tty)
   inferior_ptid = null_ptid;
   detach_inferior (pid);
 
-  unpush_target (ops);
+  inf_child_maybe_unpush_target (ops);
 }
 
 static void
index e84ee952783fc101368e14ea939933f0e38925a3..f60d54c8191c2365f6e60e202f27f9b7cf1f730a 100644 (file)
@@ -201,6 +201,10 @@ static int (*linux_nat_siginfo_fixup) (siginfo_t *,
    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,
@@ -4775,6 +4779,8 @@ linux_nat_close (struct target_ops *self)
 
   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
@@ -4856,6 +4862,8 @@ linux_nat_add_target (struct target_ops *t)
   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.  */
index b328dfa99bfb19ab851917242d16520c6c0a3434..8a241a8a5d2faa3ece9ff8a4e7cf7c878622953a 100644 (file)
@@ -54,8 +54,6 @@ static void (*ofunc) ();
 
 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,
@@ -71,7 +69,7 @@ static int procfs_remove_hw_watchpoint (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.  */
@@ -103,12 +101,12 @@ procfs_is_nto_target (bfd *abfd)
   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;
@@ -117,6 +115,9 @@ procfs_open (char *arg, int from_tty)
   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,
@@ -197,6 +198,8 @@ procfs_open (char *arg, int from_tty)
        }
     }
   do_cleanups (cleanups);
+
+  inf_child_open_target (ops, arg, from_tty);
   printf_filtered ("Debugging using %s\n", nto_procfs_path);
 }
 
@@ -628,7 +631,8 @@ procfs_attach (struct target_ops *ops, char *args, int from_tty)
   inferior_appeared (inf, pid);
   inf->attach_flag = 1;
 
-  push_target (ops);
+  if (!target_is_pushed (ops))
+    push_target (ops);
 
   procfs_find_new_threads (ops);
 }
@@ -904,7 +908,7 @@ procfs_detach (struct target_ops *ops, const char *args, int from_tty)
   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
@@ -1023,8 +1027,8 @@ procfs_mourn_inferior (struct target_ops *ops)
     }
   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
@@ -1207,7 +1211,8 @@ procfs_create_inferior (struct target_ops *ops, char *exec_file,
       /* 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
@@ -1385,6 +1390,25 @@ procfs_can_run (struct target_ops *self)
 /* "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
@@ -1395,7 +1419,7 @@ init_procfs_targets (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;
@@ -1424,6 +1448,8 @@ init_procfs_targets (void)
   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);
 
@@ -1433,6 +1459,8 @@ init_procfs_targets (void)
   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);
 }
 
index f0d65d2d74de92dc12bdb67d3846ff410665647b..80b0a6af649b2183e55741664bb879d95d0c5943 100644 (file)
@@ -3062,7 +3062,8 @@ procfs_attach (struct target_ops *ops, char *args, int from_tty)
       fflush (stdout);
     }
   inferior_ptid = do_attach (pid_to_ptid (pid));
-  push_target (ops);
+  if (!target_is_pushed (ops))
+    push_target (ops);
 }
 
 static void
@@ -3091,7 +3092,7 @@ procfs_detach (struct target_ops *ops, const char *args, int from_tty)
 
   inferior_ptid = null_ptid;
   detach_inferior (pid);
-  unpush_target (ops);
+  inf_child_maybe_unpush_target (ops);
 }
 
 static ptid_t
@@ -4340,7 +4341,8 @@ procfs_mourn_inferior (struct target_ops *ops)
       if (pi)
        destroy_procinfo (pi);
     }
-  unpush_target (ops);
+
+  generic_mourn_inferior ();
 
   if (dbx_link_bpt != NULL)
     {
@@ -4349,7 +4351,7 @@ procfs_mourn_inferior (struct target_ops *ops)
       dbx_link_bpt = NULL;
     }
 
-  generic_mourn_inferior ();
+  inf_child_maybe_unpush_target (ops);
 }
 
 /* When GDB forks to create a runnable inferior process, this function
@@ -4367,7 +4369,8 @@ procfs_init_inferior (struct target_ops *ops, int pid)
 
   /* 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'"));
index 71292d333a34bd21dc2d932523c673236f69129c..07e3c2b1af03535a124e0b7f00b532472b6e2b70 100644 (file)
@@ -2436,6 +2436,20 @@ target_require_runnable (void)
   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.
@@ -2446,23 +2460,28 @@ target_require_runnable (void)
 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);
@@ -4270,4 +4289,13 @@ When this permission is on, GDB may interrupt/stop the target's execution.\n\
 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);
 }
index 790a82a6a0365dcb9d675c62b98c7c33ab36b80d..4639f3bc7368d947b951cafaebb08f3a473fd9b2 100644 (file)
@@ -1,3 +1,10 @@
+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
index eff6327c1d367d39a95b11cd89fc5585cd3ae301..f6bdf8cd8375f3f32c88df359dc8466b991c41fb 100644 (file)
@@ -34,6 +34,8 @@ set_board_info gdb,nofileio 1
 # 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
diff --git a/gdb/testsuite/gdb.base/auto-connect-native-target.c b/gdb/testsuite/gdb.base/auto-connect-native-target.c
new file mode 100644 (file)
index 0000000..9677e0e
--- /dev/null
@@ -0,0 +1,23 @@
+/* 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;
+}
+
diff --git a/gdb/testsuite/gdb.base/auto-connect-native-target.exp b/gdb/testsuite/gdb.base/auto-connect-native-target.exp
new file mode 100644 (file)
index 0000000..ac8c79f
--- /dev/null
@@ -0,0 +1,209 @@
+# 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"
index d026a367e779d01d6246c20f7a14d2079014734b..fe43c2469c709407f5dcd2f7ba98a9d4079876fe 100644 (file)
@@ -1726,7 +1726,8 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
 #endif
   current_event.dwProcessId = pid;
   memset (&current_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 ();
@@ -1914,7 +1915,7 @@ windows_detach (struct target_ops *ops, const char *args, int from_tty)
   inferior_ptid = null_ptid;
   detach_inferior (current_event.dwProcessId);
 
-  unpush_target (ops);
+  inf_child_maybe_unpush_target (ops);
 }
 
 /* Try to determine the executable filename.
@@ -2367,8 +2368,8 @@ windows_mourn_inferior (struct target_ops *ops)
       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