From 6ad8ae5c579e2e6198870b21d10459edba9457ca Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Tue, 17 Jun 2003 20:28:14 +0000 Subject: [PATCH] gdb/ * NEWS: Mention gdbserver detach change and "disconnect" command. * infcmd.c (disconnect_command): New function. (_initialize_infcmd): Add ``disconnect'' command. * remote.c (remote_async_detach): Delete. (remote_detach): Merge remote_async_detach. (remote_disconnect): New. (init_remote_ops): Set to_disconnect. (init_remote_cisco_ops): Likewise. (init_remote_async_ops): Likewise. Use remote_detach. * target.c (cleanup_target): Default to_disconnect. (update_current_target): Inherit to_disconnect. (target_disconnect, debug_to_disconnect): New functions. (setup_target_debug): Set to_disconnect. * target.h (struct target_ops): Add to_disconnect. (target_disconnect): Add prototype. gdbserver/ * linux-low.c: Move comment to linux_thread_alive where it belonged. (linux_detach_one_process, linux_detach): New functions. (linux_target_ops): Add linux_detach. * server.c (main): Handle 'D' packet. * target.h (struct target_ops): Add "detach" member. (detach_inferior): Define. mi/ * mi-cmds.c (mi_cmds): Add "-target-disconnect". --- gdb/ChangeLog | 18 ++++++++++++++++++ gdb/NEWS | 6 ++++++ gdb/gdbserver/ChangeLog | 9 +++++++++ gdb/gdbserver/linux-low.c | 18 +++++++++++++++++- gdb/gdbserver/server.c | 22 ++++++++++++++++++++++ gdb/gdbserver/target.h | 7 +++++++ gdb/infcmd.c | 27 +++++++++++++++++++++++++++ gdb/mi/ChangeLog | 4 ++++ gdb/mi/mi-cmds.c | 1 + gdb/remote.c | 20 +++++++++++--------- gdb/target.c | 26 ++++++++++++++++++++++++++ gdb/target.h | 6 ++++++ 12 files changed, 154 insertions(+), 10 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e972edc..dfae4df 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,23 @@ 2003-06-17 Daniel Jacobowitz + * NEWS: Mention gdbserver detach change and "disconnect" command. + * infcmd.c (disconnect_command): New function. + (_initialize_infcmd): Add ``disconnect'' command. + * remote.c (remote_async_detach): Delete. + (remote_detach): Merge remote_async_detach. + (remote_disconnect): New. + (init_remote_ops): Set to_disconnect. + (init_remote_cisco_ops): Likewise. + (init_remote_async_ops): Likewise. Use remote_detach. + * target.c (cleanup_target): Default to_disconnect. + (update_current_target): Inherit to_disconnect. + (target_disconnect, debug_to_disconnect): New functions. + (setup_target_debug): Set to_disconnect. + * target.h (struct target_ops): Add to_disconnect. + (target_disconnect): Add prototype. + +2003-06-17 Daniel Jacobowitz + * breakpoint.c (insert_catchpoint): New function. (insert_breakpoints): Use catch_exceptions to call insert_catchpoint. Disable catchpoints if they fail to insert. diff --git a/gdb/NEWS b/gdb/NEWS index 98aab4f..10cd468 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,12 @@ *** Changes since GDB 5.3: +* The meaning of "detach" has changed for gdbserver + +The "detach" command will now resume the application, as documented. To +disconnect from gdbserver and leave it stopped, use the new "disconnect" +command. + * d10v `regs' command deprecated The `info registers' command has been updated so that it displays the diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 8e95517..c865334 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,12 @@ +2003-06-17 Daniel Jacobowitz + + * linux-low.c: Move comment to linux_thread_alive where it belonged. + (linux_detach_one_process, linux_detach): New functions. + (linux_target_ops): Add linux_detach. + * server.c (main): Handle 'D' packet. + * target.h (struct target_ops): Add "detach" member. + (detach_inferior): Define. + 2003-06-13 Mark Kettenis From Kelley Cook : diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 4ad204e..c700d40 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -234,13 +234,28 @@ linux_kill_one_process (struct inferior_list_entry *entry) } while (WIFSTOPPED (wstat)); } -/* Return nonzero if the given thread is still alive. */ static void linux_kill (void) { for_each_inferior (&all_threads, linux_kill_one_process); } +static void +linux_detach_one_process (struct inferior_list_entry *entry) +{ + struct thread_info *thread = (struct thread_info *) entry; + struct process_info *process = get_thread_process (thread); + + ptrace (PTRACE_DETACH, pid_of (process), 0, 0); +} + +static void +linux_detach (void) +{ + for_each_inferior (&all_threads, linux_detach_one_process); +} + +/* Return nonzero if the given thread is still alive. */ static int linux_thread_alive (int tid) { @@ -1249,6 +1264,7 @@ static struct target_ops linux_target_ops = { linux_create_inferior, linux_attach, linux_kill, + linux_detach, linux_thread_alive, linux_resume, linux_wait, diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index d0963ba..81fde5b 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -217,6 +217,28 @@ main (int argc, char *argv[]) case 'd': remote_debug = !remote_debug; break; + case 'D': + fprintf (stderr, "Detaching from inferior\n"); + detach_inferior (); + write_ok (own_buf); + putpkt (own_buf); + remote_close (); + + /* If we are attached, then we can exit. Otherwise, we need to + hang around doing nothing, until the child is gone. */ + if (!attached) + { + int status, ret; + + do { + ret = waitpid (signal_pid, &status, 0); + if (WIFEXITED (status) || WIFSIGNALED (status)) + break; + } while (ret != -1 || errno != ECHILD); + } + + exit (0); + case '!': if (attached == 0) { diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index c09ac8d..1c47a3a 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -48,6 +48,10 @@ struct target_ops void (*kill) (void); + /* Detach from all inferiors. */ + + void (*detach) (void); + /* Return 1 iff the thread with process ID PID is alive. */ int (*thread_alive) (int pid); @@ -122,6 +126,9 @@ void set_target_ops (struct target_ops *); #define kill_inferior() \ (*the_target->kill) () +#define detach_inferior() \ + (*the_target->detach) () + #define mythread_alive(pid) \ (*the_target->thread_alive) (pid) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 0ed0ce2..911e865 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -81,6 +81,8 @@ static void float_info (char *, int); static void detach_command (char *, int); +static void disconnect_command (char *, int); + static void unset_environment_command (char *, int); static void set_environment_command (char *, int); @@ -1876,6 +1878,26 @@ detach_command (char *args, int from_tty) detach_hook (); } +/* Disconnect from the current target without resuming it (leaving it + waiting for a debugger). + + We'd better not have left any breakpoints in the program or the + next debugger will get confused. Currently only supported for some + remote targets, since the normal attach mechanisms don't work on + stopped processes on some native platforms (e.g. GNU/Linux). */ + +static void +disconnect_command (char *args, int from_tty) +{ + dont_repeat (); /* Not for the faint of heart */ + target_disconnect (args, from_tty); +#if defined(SOLIB_RESTART) + SOLIB_RESTART (); +#endif + if (detach_hook) + detach_hook (); +} + /* Stop the execution of the target while running in async mode, in the backgound. */ void @@ -2014,6 +2036,11 @@ to specify the program, and to load its symbol table."); If a process, it is no longer traced, and it continues its execution. If\n\ you were debugging a file, the file is closed and gdb no longer accesses it."); + add_com ("disconnect", class_run, disconnect_command, + "Disconnect from a target.\n\ +The target will wait for another debugger to connect. Not available for\n\ +all targets."); + add_com ("signal", class_run, signal_command, "Continue program giving it signal specified by the argument.\n\ An argument of \"0\" means continue program without giving it a signal."); diff --git a/gdb/mi/ChangeLog b/gdb/mi/ChangeLog index 57651c2..ed861f0 100644 --- a/gdb/mi/ChangeLog +++ b/gdb/mi/ChangeLog @@ -1,3 +1,7 @@ +2003-06-17 Daniel Jacobowitz + + * mi-cmds.c (mi_cmds): Add "-target-disconnect". + 2003-06-11 David Carlton * mi-cmd-stack.c: Include dictionary.h. diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 9ec174f..9182402 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -127,6 +127,7 @@ struct mi_cmd mi_cmds[] = {"target-attach", 0, 0}, {"target-compare-sections", 0, 0}, {"target-detach", "detach", 0}, + {"target-disconnect", "disconnect", 0}, {"target-download", 0, mi_cmd_target_download}, {"target-exec-status", 0, 0}, {"target-list-available-targets", 0, 0}, diff --git a/gdb/remote.c b/gdb/remote.c index 3de323b..492661b 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -126,7 +126,6 @@ static void remote_async_kill (void); static int tohex (int nib); static void remote_detach (char *args, int from_tty); -static void remote_async_detach (char *args, int from_tty); static void remote_interrupt (int signo); @@ -2421,15 +2420,19 @@ remote_detach (char *args, int from_tty) strcpy (buf, "D"); remote_send (buf, (rs->remote_packet_size)); + /* Unregister the file descriptor from the event loop. */ + if (target_is_async_p ()) + serial_async (remote_desc, NULL, 0); + target_mourn_inferior (); if (from_tty) puts_filtered ("Ending remote debugging.\n"); - } -/* Same as remote_detach, but with async support. */ +/* Same as remote_detach, but don't send the "D" packet; just disconnect. */ + static void -remote_async_detach (char *args, int from_tty) +remote_disconnect (char *args, int from_tty) { struct remote_state *rs = get_remote_state (); char *buf = alloca (rs->remote_packet_size); @@ -2437,10 +2440,6 @@ remote_async_detach (char *args, int from_tty) if (args) error ("Argument given to \"detach\" when remotely debugging."); - /* Tell the remote target to detach. */ - strcpy (buf, "D"); - remote_send (buf, (rs->remote_packet_size)); - /* Unregister the file descriptor from the event loop. */ if (target_is_async_p ()) serial_async (remote_desc, NULL, 0); @@ -5438,6 +5437,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_open = remote_open; remote_ops.to_close = remote_close; remote_ops.to_detach = remote_detach; + remote_ops.to_disconnect = remote_disconnect; remote_ops.to_resume = remote_resume; remote_ops.to_wait = remote_wait; remote_ops.to_fetch_registers = remote_fetch_registers; @@ -5858,6 +5858,7 @@ Specify the serial device it is connected to (e.g. host:2020)."; remote_cisco_ops.to_open = remote_cisco_open; remote_cisco_ops.to_close = remote_cisco_close; remote_cisco_ops.to_detach = remote_detach; + remote_cisco_ops.to_disconnect = remote_disconnect; remote_cisco_ops.to_resume = remote_resume; remote_cisco_ops.to_wait = remote_cisco_wait; remote_cisco_ops.to_fetch_registers = remote_fetch_registers; @@ -5953,7 +5954,8 @@ init_remote_async_ops (void) Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_async_ops.to_open = remote_async_open; remote_async_ops.to_close = remote_close; - remote_async_ops.to_detach = remote_async_detach; + remote_async_ops.to_detach = remote_detach; + remote_async_ops.to_disconnect = remote_disconnect; remote_async_ops.to_resume = remote_async_resume; remote_async_ops.to_wait = remote_async_wait; remote_async_ops.to_fetch_registers = remote_fetch_registers; diff --git a/gdb/target.c b/gdb/target.c index fd0165a..e738208 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -95,6 +95,8 @@ static void debug_to_attach (char *, int); static void debug_to_detach (char *, int); +static void debug_to_disconnect (char *, int); + static void debug_to_resume (ptid_t, int, enum target_signal); static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *); @@ -371,6 +373,9 @@ cleanup_target (struct target_ops *t) de_fault (to_detach, (void (*) (char *, int)) target_ignore); + de_fault (to_disconnect, + (void (*) (char *, int)) + tcomplain); de_fault (to_resume, (void (*) (ptid_t, int, enum target_signal)) noprocess); @@ -556,6 +561,7 @@ update_current_target (void) INHERIT (to_attach, t); INHERIT (to_post_attach, t); INHERIT (to_detach, t); + INHERIT (to_disconnect, t); INHERIT (to_resume, t); INHERIT (to_wait, t); INHERIT (to_post_wait, t); @@ -1141,6 +1147,16 @@ target_detach (char *args, int from_tty) } void +target_disconnect (char *args, int from_tty) +{ + /* Handle any optimized stores to the inferior. */ +#ifdef DO_DEFERRED_STORES + DO_DEFERRED_STORES; +#endif + (current_target.to_disconnect) (args, from_tty); +} + +void target_link (char *modname, CORE_ADDR *t_reloc) { if (STREQ (current_target.to_shortname, "rombug")) @@ -1562,6 +1578,15 @@ debug_to_detach (char *args, int from_tty) } static void +debug_to_disconnect (char *args, int from_tty) +{ + debug_target.to_disconnect (args, from_tty); + + fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n", + args, from_tty); +} + +static void debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal) { debug_target.to_resume (ptid, step, siggnal); @@ -2202,6 +2227,7 @@ setup_target_debug (void) current_target.to_attach = debug_to_attach; current_target.to_post_attach = debug_to_post_attach; current_target.to_detach = debug_to_detach; + current_target.to_disconnect = debug_to_disconnect; current_target.to_resume = debug_to_resume; current_target.to_wait = debug_to_wait; current_target.to_post_wait = debug_to_post_wait; diff --git a/gdb/target.h b/gdb/target.h index c2d8793..a3e10e8 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -198,6 +198,7 @@ struct target_ops void (*to_attach) (char *, int); void (*to_post_attach) (int); void (*to_detach) (char *, int); + void (*to_disconnect) (char *, int); void (*to_resume) (ptid_t, int, enum target_signal); ptid_t (*to_wait) (ptid_t, struct target_waitstatus *); void (*to_post_wait) (ptid_t, int); @@ -414,6 +415,11 @@ extern struct target_stack_item *target_stack; extern void target_detach (char *, int); +/* Disconnect from the current target without resuming it (leaving it + waiting for a debugger). */ + +extern void target_disconnect (char *, int); + /* Resume execution of the target process PTID. STEP says whether to single-step or to run free; SIGGNAL is the signal to be given to the target, or TARGET_SIGNAL_0 for no signal. The caller may not -- 2.7.4