diff options
-rw-r--r-- | gdb/ChangeLog | 68 | ||||
-rw-r--r-- | gdb/NEWS | 10 | ||||
-rw-r--r-- | gdb/darwin-nat.c | 6 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 58 | ||||
-rw-r--r-- | gdb/gnu-nat.c | 4 | ||||
-rw-r--r-- | gdb/go32-nat.c | 5 | ||||
-rw-r--r-- | gdb/inf-child.c | 62 | ||||
-rw-r--r-- | gdb/inf-child.h | 15 | ||||
-rw-r--r-- | gdb/inf-ptrace.c | 6 | ||||
-rw-r--r-- | gdb/inf-ttrace.c | 10 | ||||
-rw-r--r-- | gdb/linux-nat.c | 8 | ||||
-rw-r--r-- | gdb/nto-procfs.c | 54 | ||||
-rw-r--r-- | gdb/procfs.c | 13 | ||||
-rw-r--r-- | gdb/target.c | 48 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/boards/gdbserver-base.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/auto-connect-native-target.c | 23 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/auto-connect-native-target.exp | 209 | ||||
-rw-r--r-- | gdb/windows-nat.c | 7 |
20 files changed, 574 insertions, 47 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1c74843..ba052db0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,73 @@ 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. @@ -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 diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c index 478429c..f3d510d 100644 --- a/gdb/darwin-nat.c +++ b/gdb/darwin-nat.c @@ -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 diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 7d0fdbd..18588f6 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -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 diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6092ff4..47d4bb7 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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}; 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..77843ea 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,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. */ 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 <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; } diff --git a/gdb/inf-child.h b/gdb/inf-child.h index 4473cff..3f00ab6 100644 --- a/gdb/inf-child.h +++ b/gdb/inf-child.h @@ -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 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 e84ee95..f60d54c 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, @@ -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. */ diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c index b328dfa..8a241a8 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 <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); } 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 71292d3..07e3c2b 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -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); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 790a82a..4639f3b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,12 @@ 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". diff --git a/gdb/testsuite/boards/gdbserver-base.exp b/gdb/testsuite/boards/gdbserver-base.exp index eff6327..f6bdf8c 100644 --- a/gdb/testsuite/boards/gdbserver-base.exp +++ b/gdb/testsuite/boards/gdbserver-base.exp @@ -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 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 <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 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 <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" diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index d026a36..fe43c24 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -1726,7 +1726,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 (); @@ -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 |