From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20980 invoked by alias); 14 Jun 2003 04:26:47 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 20949 invoked from network); 14 Jun 2003 04:26:45 -0000 Received: from unknown (HELO crack.them.org) (146.82.138.56) by sources.redhat.com with SMTP; 14 Jun 2003 04:26:45 -0000 Received: from dsl093-172-017.pit1.dsl.speakeasy.net ([66.93.172.17] helo=nevyn.them.org ident=mail) by crack.them.org with asmtp (Exim 3.12 #1 (Debian)) id 19R2dY-0003Rh-00 for ; Fri, 13 Jun 2003 23:27:32 -0500 Received: from drow by nevyn.them.org with local (Exim 3.36 #1 (Debian)) id 19R2ck-0000S4-00 for ; Sat, 14 Jun 2003 00:26:42 -0400 Date: Sat, 14 Jun 2003 04:26:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: RFA: "disconnect" command Message-ID: <20030614042642.GA28231@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.1i X-SW-Source: 2003-06/txt/msg00491.txt.bz2 This patch got tabled shortly before 5.3, due to bad timing on my part. Now here we are coming up on 6.0 and my timing's no better... this is the first of several old patches that I would like to see included in 6.0, assuming I get the time to revisit them all. Refresher on this one: the patch adds a "disconnect" commad, and implements it for remote targets. "disconnect" leaves the target stopped, while "detach" usually resumes it. Useful with kgdb, gdbserver, et cetera. I've included the gdbserver portion of the patch this time, too. There was a consensus on this patch the last time I posted it, but it's been so long that I'd like a thumbs-up from another maintainer first. I've corrected the doc problems; Andrew, there's still no MI testcase, because I could not figure out a reasonable way to write one without leaving a dangling process around. Re-attaching to it to kill it properly, from within the testsuite, ranges from hard to really hard. Thoughts? OK? -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer 2003-06-14 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-14 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-14 Daniel Jacobowitz * gdb.texinfo (Debug Session): Document "disconnect" command. (GDB/MI Target Manipulation): Document "-target-disconnect". 2003-06-14 Daniel Jacobowitz * mi-cmds.c (mi_cmds): Add "-target-disconnect". Index: gdb/NEWS =================================================================== RCS file: /cvs/src/src/gdb/NEWS,v retrieving revision 1.109 diff -u -p -r1.109 NEWS --- gdb/NEWS 13 May 2003 05:40:34 -0000 1.109 +++ gdb/NEWS 14 Jun 2003 04:05:25 -0000 @@ -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 Index: gdb/infcmd.c =================================================================== RCS file: /cvs/src/src/gdb/infcmd.c,v retrieving revision 1.81 diff -u -p -r1.81 infcmd.c --- gdb/infcmd.c 11 Jun 2003 19:38:26 -0000 1.81 +++ gdb/infcmd.c 14 Jun 2003 04:05:25 -0000 @@ -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 @@ -2013,6 +2035,11 @@ to specify the program, and to load its "Detach a process or file previously attached.\n\ 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\ Index: gdb/remote.c =================================================================== RCS file: /cvs/src/src/gdb/remote.c,v retrieving revision 1.105 diff -u -p -r1.105 remote.c --- gdb/remote.c 10 Jun 2003 14:37:04 -0000 1.105 +++ gdb/remote.c 14 Jun 2003 04:05:26 -0000 @@ -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 fro 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); @@ -5435,6 +5434,7 @@ Specify the serial device it is connecte 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; @@ -5855,6 +5855,7 @@ Specify the serial device it is connecte 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; @@ -5950,7 +5951,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; Index: gdb/target.c =================================================================== RCS file: /cvs/src/src/gdb/target.c,v retrieving revision 1.52 diff -u -p -r1.52 target.c --- gdb/target.c 8 May 2003 20:52:48 -0000 1.52 +++ gdb/target.c 14 Jun 2003 04:05:26 -0000 @@ -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_tt } 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; Index: gdb/target.h =================================================================== RCS file: /cvs/src/src/gdb/target.h,v retrieving revision 1.40 diff -u -p -r1.40 target.h --- gdb/target.h 2 Jun 2003 23:20:47 -0000 1.40 +++ gdb/target.h 14 Jun 2003 04:05:26 -0000 @@ -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); @@ -413,6 +414,11 @@ extern struct target_stack_item *target_ says whether to be verbose or not. */ 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 Index: gdb/doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.164 diff -u -p -r1.164 gdb.texinfo --- gdb/doc/gdb.texinfo 9 Jun 2003 21:12:19 -0000 1.164 +++ gdb/doc/gdb.texinfo 14 Jun 2003 04:05:29 -0000 @@ -11069,6 +11069,10 @@ step and continue the remote program. To resume the remote program and stop debugging it, use the @code{detach} command. +@kindex disconnect +To disconnect from the remote program and let it wait for another debugger +to connect, use the @code{disconnect} command. + @cindex interrupting remote programs @cindex remote programs, interrupting Whenever @value{GDBN} is waiting for the remote program, if you type the @@ -17392,6 +17396,31 @@ The corresponding @value{GDBN} command i @end smallexample +@subheading The @code{-target-disconnect} Command +@findex -target-disconnect + +@subsubheading Synopsis + +@example + -target-disconnect +@end example + +Disconnect from the remote target. There's no output. + +@subsubheading @value{GDBN} command + +The corresponding @value{GDBN} command is @samp{disconnect}. + +@subsubheading Example + +@smallexample +(@value{GDBP}) +-target-disconnect +^done +(@value{GDBP}) +@end smallexample + + @subheading The @code{-target-download} Command @findex -target-download @@ -19775,7 +19804,7 @@ Toggle debug flag. @cindex @code{D} packet Detach @value{GDBN} from the remote system. Sent to the remote target -before @value{GDBN} disconnects. +before @value{GDBN} disconnects via the @code{detach} command. Reply: @table @samp Index: gdb/gdbserver/linux-low.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v retrieving revision 1.23 diff -u -p -r1.23 linux-low.c --- gdb/gdbserver/linux-low.c 5 Jun 2003 14:26:58 -0000 1.23 +++ gdb/gdbserver/linux-low.c 14 Jun 2003 04:05:29 -0000 @@ -234,13 +234,28 @@ linux_kill_one_process (struct inferior_ } 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_op linux_create_inferior, linux_attach, linux_kill, + linux_detach, linux_thread_alive, linux_resume, linux_wait, Index: gdb/gdbserver/server.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/server.c,v retrieving revision 1.14 diff -u -p -r1.14 server.c --- gdb/gdbserver/server.c 29 Aug 2002 18:50:25 -0000 1.14 +++ gdb/gdbserver/server.c 14 Jun 2003 04:05:29 -0000 @@ -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) { Index: gdb/gdbserver/target.h =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/target.h,v retrieving revision 1.6 diff -u -p -r1.6 target.h --- gdb/gdbserver/target.h 5 Jun 2003 14:26:58 -0000 1.6 +++ gdb/gdbserver/target.h 14 Jun 2003 04:05:29 -0000 @@ -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); @@ -121,6 +125,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) Index: gdb/mi/mi-cmds.c =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-cmds.c,v retrieving revision 1.12 diff -u -p -r1.12 mi-cmds.c --- gdb/mi/mi-cmds.c 4 May 2003 03:50:13 -0000 1.12 +++ gdb/mi/mi-cmds.c 14 Jun 2003 04:05:29 -0000 @@ -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},