From patchwork Mon May 4 21:54:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabriel Corona X-Patchwork-Id: 6564 Received: (qmail 52272 invoked by alias); 4 May 2015 21:54:34 -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 52263 invoked by uid 89); 4 May 2015 21:54:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, SPF_NEUTRAL autolearn=ham version=3.3.2 X-HELO: smtp1-g21.free.fr Received: from smtp1-g21.free.fr (HELO smtp1-g21.free.fr) (212.27.42.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Mon, 04 May 2015 21:54:31 +0000 Received: from localhost.localdomain (unknown [81.56.99.41]) by smtp1-g21.free.fr (Postfix) with ESMTP id 4AEF6940091; Mon, 4 May 2015 23:51:39 +0200 (CEST) From: Gabriel Corona To: gdb-patches@sourceware.org Cc: Gabriel Corona Subject: [PATCH v2 1/2] Use a shell command as a socket for gdbserver Date: Mon, 4 May 2015 23:54:22 +0200 Message-Id: <1430776463-23214-1-git-send-email-gabriel.corona@enst-bretagne.fr> X-IsSubscribed: yes This brings feature parity with gdb in this regard. This can be used to do gdbserver over unix socket (without redirecting the inferior stdio to /dev/null): $ gdbserver '|socat STDIO UNIX-LISTEN:foo.sock' ./foo and in gdb: (gdb) target remote |socat STDIO UNIX:foo.sock Altneratively, we can initiate a connection to a remote server: $ gdbserver '|socat STDIO TCP:gdb.example.com:9000' ./foo gdb/gdbserver/ChangeLog: * remote-utils.c: add support for using a shell command stdio as COMM * remote.c: add documentation about this feature --- gdb/gdbserver/remote-utils.c | 71 ++++++++++++++++++++++++++++++++++++++++++++ gdb/gdbserver/server.c | 3 +- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index 1de86be..f15f1ce 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -58,6 +58,8 @@ #endif #include +#include "gdb_wait.h" + #if USE_WIN32API #include #endif @@ -239,6 +241,14 @@ remote_prepare (char *name) return; } +#ifndef USE_WIN32API + if (name[0] == '|') + { + transport_is_reliable = 1; + return; + } +#endif + port_str = strchr (name, ':'); if (port_str == NULL) { @@ -280,6 +290,56 @@ remote_prepare (char *name) transport_is_reliable = 1; } +#ifndef USE_WIN32API +static int +open_shell_command (char *command) +{ + int sockets[2]; + pid_t child, grandchild, res; + int status; + + if (socketpair (AF_LOCAL, SOCK_STREAM, 0, sockets) < 0) + perror_with_name ("Can't get socketpair"); + child = fork (); + if (child < 0) + { + perror_with_name ("Can't fork"); + } + else if (child == 0) + { + if (close (sockets[0]) < 0) + perror_with_name ("Can't close socket"); + if (dup2 (sockets[1], 0) < 0 || dup2 (sockets[1], 1) < 0) + perror_with_name ("Can't dup socket to stdio"); + if (close (sockets[1]) < 0) + perror_with_name ("Can't close original socket"); + /* Double fork in order to inherit the grandchild. The process + is expected to exit when the other end of the socketpair is + closed. + */ + grandchild = fork (); + if (grandchild < 0) + perror_with_name ("Can't double fork command process"); + if (grandchild != 0) + exit (0); + execl ("/bin/sh", "sh", "-c", command, NULL); + perror_with_name ("Can't exec command"); + } + else + { + close (sockets[1]); + signal (SIGPIPE, SIG_IGN); + while ((res = waitpid (child, &status, 0)) < 0 && errno == EINTR); + if (res < 0) + perror_with_name ("Can't wait child process"); + if (!WIFEXITED (status) || WEXITSTATUS (status)) + perror_with_name ("Child process did not terminate correctly"); + return sockets[0]; + } + return -1; +} +#endif + /* Open a connection to a remote debugger. NAME is the filename used for communication. */ @@ -288,6 +348,17 @@ remote_open (char *name) { char *port_str; +#ifndef USE_WIN32API + if (name[0] == '|') + { + fprintf (stderr, "Remote debugging using shell command\n"); + remote_desc = open_shell_command (name + 1); + enable_async_notification (remote_desc); + add_file_handler (remote_desc, handle_serial_event, NULL); + return; + } +#endif + port_str = strchr (name, ':'); #ifdef USE_WIN32API if (port_str == NULL) diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index d2e20d9..9ed4049 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -3036,7 +3036,8 @@ gdbserver_usage (FILE *stream) "\tgdbserver [OPTIONS] --attach COMM PID\n" "\tgdbserver [OPTIONS] --multi COMM\n" "\n" - "COMM may either be a tty device (for serial debugging),\n" + "COMM may be a tty device (for serial debugging),\n" + "'|some shell command' to use stdin/stdout of a given shell command,\n" "HOST:PORT to listen for a TCP connection, or '-' or 'stdio' to use \n" "stdin/stdout of gdbserver.\n" "PROG is the executable program. ARGS are arguments passed to inferior.\n"