From patchwork Mon Mar 17 15:23:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 121 Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx22.g.dreamhost.com (caibbdcaabij.dreamhost.com [208.113.200.189]) by wilcox.dreamhost.com (Postfix) with ESMTP id 6859E3600C9 for ; Mon, 17 Mar 2014 08:24:12 -0700 (PDT) Received: by homiemail-mx22.g.dreamhost.com (Postfix, from userid 14314964) id 140F25000952; Mon, 17 Mar 2014 08:24:12 -0700 (PDT) X-Original-To: gdb@patchwork.siddhesh.in Delivered-To: x14314964@homiemail-mx22.g.dreamhost.com Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by homiemail-mx22.g.dreamhost.com (Postfix) with ESMTPS id E0EDA5000947 for ; Mon, 17 Mar 2014 08:24:11 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=P+UlpjRHm1123UJNXRy/22w/ALE1mLW y8hbw/nOmX6yHTlvYYIpqUshfHb11+Ihvk/57O4kcIgoSTfafIwUAYuMgoEmp+iQ AdBIsjb1A1LPTsD9+CX0Rgtbx1Uv7kPVaIULBh7oZqI/iTZMMZqXmUeO0CKVgsgo pn/jZurXiaoc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:in-reply-to :references; s=default; bh=VtNYfKNnP/axp6kQIVXmUGRoFjY=; b=wuMty RTgaBDp9aWcb10LO5KYIWrELV2hm0VwcnPfyhUuN4U9Y/vMh/zoGatMRz44AuUqo pzJE+qT3bKCu8eOnxZuwj97pDEWH4TBWRyxWZtOPD9TzbRHwqcFnNjKJik+3UwS4 18FhbTlBY2/lhCkh9ZsnP7LbaHOCOzjw3dLkTU= Received: (qmail 7212 invoked by alias); 17 Mar 2014 15:23:32 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 6991 invoked by uid 89); 17 Mar 2014 15:23:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.1 required=5.0 tests=AWL, BAYES_05, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 17 Mar 2014 15:23:24 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s2HFNLtM013406 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 17 Mar 2014 11:23:22 -0400 Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s2HFN5A5009032 for ; Mon, 17 Mar 2014 11:23:17 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 8/8] Allow making GDB not automatically connect to the native target. Date: Mon, 17 Mar 2014 15:23:04 +0000 Message-Id: <1395069784-7406-9-git-send-email-palves@redhat.com> In-Reply-To: <1395069784-7406-1-git-send-email-palves@redhat.com> References: <1395069784-7406-1-git-send-email-palves@redhat.com> X-DH-Original-To: gdb@patchwork.siddhesh.in 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 that 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, I 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 17, 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-03-17 Pedro Alves * 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-03-17 Pedro Alves * gdb.texinfo (Starting): Document "set/show auto-connect-native-target". (Target Commands): Document "target native". gdb/testsuite/ 2014-03-17 Pedro Alves * boards/native-extended-gdbserver.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. --- gdb/NEWS | 10 + gdb/darwin-nat.c | 6 +- gdb/doc/gdb.texinfo | 58 ++++++ gdb/gnu-nat.c | 4 +- gdb/go32-nat.c | 5 +- gdb/inf-child.c | 62 +++++- gdb/inf-child.h | 11 ++ gdb/inf-ptrace.c | 6 +- gdb/inf-ttrace.c | 10 +- gdb/linux-nat.c | 8 + gdb/nto-procfs.c | 53 ++++-- gdb/procfs.c | 13 +- gdb/target.c | 48 ++++- gdb/testsuite/boards/native-extended-gdbserver.exp | 2 + .../gdb.base/auto-connect-native-target.c | 23 +++ .../gdb.base/auto-connect-native-target.exp | 209 +++++++++++++++++++++ gdb/windows-nat.c | 7 +- 17 files changed, 488 insertions(+), 47 deletions(-) create mode 100644 gdb/testsuite/gdb.base/auto-connect-native-target.c create mode 100644 gdb/testsuite/gdb.base/auto-connect-native-target.exp diff --git a/gdb/NEWS b/gdb/NEWS index 5bdda0a..b917eb0 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -43,6 +43,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 @@ -87,6 +93,10 @@ maint ada show ignore-descriptive-types "help target", "info target", "info files", "maint print target-stack". +* The "target native" command now really 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 diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c index 8650f03..c0e6340 100644 --- a/gdb/darwin-nat.c +++ b/gdb/darwin-nat.c @@ -1161,8 +1161,6 @@ darwin_mourn_inferior (struct target_ops *ops) mach_port_t prev; int i; - unpush_target (darwin_ops); - /* Deallocate threads. */ if (inf->private->threads) { @@ -1218,6 +1216,7 @@ darwin_mourn_inferior (struct target_ops *ops) inf->private = NULL; generic_mourn_inferior (); + inf_child_maybe_unpush_target (ops); } static void @@ -1453,7 +1452,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 diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index de5ac63..2fbacb9 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -2146,6 +2146,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{run}, @code{attach}, +@code{info proc}, @code{info os}. + @kindex set disable-randomization @item set disable-randomization @itemx set disable-randomization on @@ -18050,6 +18101,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}; diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c index 8235811..3317215 100644 --- a/gdb/gnu-nat.c +++ b/gdb/gnu-nat.c @@ -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); } @@ -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); } static void diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c index e17707a..69edb9d 100644 --- a/gdb/go32-nat.c +++ b/gdb/go32-nat.c @@ -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,7 +745,7 @@ go32_mourn_inferior (struct target_ops *ops) delete_thread_silent (ptid); prog_has_started = 0; - unpush_target (ops); + inf_child_maybe_unpush_target (ops); generic_mourn_inferior (); } diff --git a/gdb/inf-child.c b/gdb/inf-child.c index 8a99adc..a3c4fe4 100644 --- a/gdb/inf-child.c +++ b/gdb/inf-child.c @@ -40,6 +40,11 @@ #include #include +/* 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; } diff --git a/gdb/inf-child.h b/gdb/inf-child.h index 4473cff..3161ac3 100644 --- a/gdb/inf-child.h +++ b/gdb/inf-child.h @@ -30,4 +30,15 @@ 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. */ + +extern void inf_child_maybe_unpush_target (struct target_ops *ops); + #endif diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c index bffb4ba..cc4921b 100644 --- a/gdb/inf-ptrace.c +++ b/gdb/inf-ptrace.c @@ -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. */ diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c index 802dc85..96105dc 100644 --- a/gdb/inf-ttrace.c +++ b/gdb/inf-ttrace.c @@ -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 diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index b615423..7faf0dc 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -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, @@ -4776,6 +4780,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 @@ -4857,6 +4863,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. */ diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c index b328dfa..acef9ca 100644 --- a/gdb/nto-procfs.c +++ b/gdb/nto-procfs.c @@ -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 ' 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 + ' 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,7 @@ 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); + inf_child_maybe_push_target (ops); target_terminal_init (); if (exec_bfd != NULL @@ -1385,6 +1389,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 +1418,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 +1447,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 +1458,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 "; + t->to_open = procfs_open; + add_target (&nto_procfs_ops); } diff --git a/gdb/procfs.c b/gdb/procfs.c index f0d65d2..80b0a6a 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -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'")); diff --git a/gdb/target.c b/gdb/target.c index 0d22297..bbb8e5e 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2574,6 +2574,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. @@ -2584,23 +2598,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); @@ -4369,4 +4388,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); } diff --git a/gdb/testsuite/boards/native-extended-gdbserver.exp b/gdb/testsuite/boards/native-extended-gdbserver.exp index 8bb95db..080a22e 100644 --- a/gdb/testsuite/boards/native-extended-gdbserver.exp +++ b/gdb/testsuite/boards/native-extended-gdbserver.exp @@ -36,6 +36,8 @@ set_board_info gdb_protocol "extended-remote" send_user "configuring for gdbserver local testing (extended-remote)\n" +set GDBFLAGS "${GDBFLAGS} -ex \"set auto-connect-native-target off\"" + # We must load this explicitly here, and rename the procedures we want # to override. If we didn't do this, given that mi-support.exp is # loaded later in the test files, the procedures loaded then would 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 index 0000000..9677e0e --- /dev/null +++ b/gdb/testsuite/gdb.base/auto-connect-native-target.c @@ -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 . */ + +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 index 0000000..ac8c79f --- /dev/null +++ b/gdb/testsuite/gdb.base/auto-connect-native-target.exp @@ -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 . + +# 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" diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 3054d12..6387c5e 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -1709,7 +1709,8 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching) #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 (); @@ -1897,7 +1898,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. @@ -2350,8 +2351,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