From patchwork Mon Sep 3 12:17:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Darrington X-Patchwork-Id: 29164 Received: (qmail 50609 invoked by alias); 3 Sep 2018 12:17:54 -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 50593 invoked by uid 89); 3 Sep 2018 12:17:54 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.2 spammy=communicate, protocol, relating, IAC X-HELO: jocasta.intra Received: from de.cellform.com (HELO jocasta.intra) (88.217.224.109) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 03 Sep 2018 12:17:45 +0000 Received: from jocasta.intra (localhost [127.0.0.1]) by jocasta.intra (8.15.2/8.15.2/Debian-8) with ESMTPS id w83CHgO6005509 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 3 Sep 2018 14:17:42 +0200 Received: (from john@localhost) by jocasta.intra (8.15.2/8.15.2/Submit) id w83CHflG005508; Mon, 3 Sep 2018 14:17:41 +0200 From: John Darrington To: gdb-patches@sourceware.org Cc: John Darrington Subject: [PATCH] Allow remote debugging over a Unix local domain socket. Date: Mon, 3 Sep 2018 14:17:36 +0200 Message-Id: <20180903121736.5246-2-john@darrington.wattle.id.au> In-Reply-To: <20180903121736.5246-1-john@darrington.wattle.id.au> References: <20180903121736.5246-1-john@darrington.wattle.id.au> Extend the "target remote" and "target extended-remote" commands such that if the filename provided is a Unix local domain (AF_UNIX) socket, then it'll be treated as such, instead of trying to open it as if it were a character device. gdb/ChangeLog: * NEWS: Mention changed commands. * configure.ac (SER_HARDWIRE): Add ser-socket.o. * ser-socket.c: New file. * Makefile.in: Add new file. * serial.c (serial_open): Check if filename is a socket and lookup the appropriate interface accordingly. gdb/doc/ChangeLog: * gdb.texinfo (Remote Connection Commands): Describe the changes to target remote and target extended-remote relating to Unix domain sockets. --- gdb/Makefile.in | 1 + gdb/NEWS | 5 +++ gdb/configure | 1 + gdb/configure.ac | 1 + gdb/doc/gdb.texinfo | 22 +++++++++- gdb/ser-socket.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/serial.c | 12 +++++- 7 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 gdb/ser-socket.c diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 118c3c8062..4646ade6c1 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2323,6 +2323,7 @@ ALLDEPFILES = \ ser-go32.c \ ser-mingw.c \ ser-pipe.c \ + ser-socket.c \ ser-tcp.c \ sh-nbsd-nat.c \ sh-nbsd-tdep.c \ diff --git a/gdb/NEWS b/gdb/NEWS index a7a3674375..e5926897a0 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -36,6 +36,11 @@ maint show dwarf unwinders * Changed commands +target remote FILENAME +target extended-remote FILENAME + If FILENAME is a Unix domain socket, GDB will attempt to connect + to this socket instead of opening FILENAME as a character device. + thread apply [all | COUNT | -COUNT] [FLAG]... COMMAND The 'thread apply' command accepts new FLAG arguments. FLAG arguments allow to control what output to produce and how to handle diff --git a/gdb/configure b/gdb/configure index 9cd0036848..21c4f8b6af 100755 --- a/gdb/configure +++ b/gdb/configure @@ -15586,6 +15586,7 @@ case ${host} in *go32* ) SER_HARDWIRE=ser-go32.o ;; *djgpp* ) SER_HARDWIRE=ser-go32.o ;; *mingw32*) SER_HARDWIRE="ser-base.o ser-tcp.o ser-mingw.o" ;; + *) SER_HARDWIRE="$SER_HARDWIRE ser-socket.o" ;; esac diff --git a/gdb/configure.ac b/gdb/configure.ac index 13bc5f9a8f..07c874df96 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -1875,6 +1875,7 @@ case ${host} in *go32* ) SER_HARDWIRE=ser-go32.o ;; *djgpp* ) SER_HARDWIRE=ser-go32.o ;; *mingw32*) SER_HARDWIRE="ser-base.o ser-tcp.o ser-mingw.o" ;; + *) SER_HARDWIRE="$SER_HARDWIRE ser-socket.o" ;; esac AC_SUBST(SER_HARDWIRE) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 5068c0ac81..dae62c1787 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20703,7 +20703,8 @@ programs. @subsection Remote Connection Commands @cindex remote connection commands -@value{GDBN} can communicate with the target over a serial line, or +@value{GDBN} can communicate with the target over a serial line, a +local Unix domain socket, or over an @acronym{IP} network using @acronym{TCP} or @acronym{UDP}. In each case, @value{GDBN} uses the same protocol for debugging your program; only the medium carrying the debugging packets varies. The @@ -20728,6 +20729,25 @@ If you're using a serial line, you may want to give @value{GDBN} the (@pxref{Remote Configuration, set serial baud}) before the @code{target} command. + +@item target remote @var{local-socket} +@itemx target extended-remote @var{local-socket} +@cindex local socket, @code{target remote} +@cindex Unix domain socket +Use @var{local-socket} to communicate with the target. For example, +to use a local Unix domain socket bound to the file system entry @file{/tmp/gdb-socket0}: + +@smallexample +target remote /tmp/gdb-socket0 +@end smallexample + +Note that this command has the same form as the command to connect +to a serial line. @value{GDBN} will automatically determine which +kind of file you have specified and will make the appropriate kind +of connection. +This feature is not available if the host system does not support +Unix domain sockets. + @item target remote @code{@var{host}:@var{port}} @itemx target remote @code{@var{[host]}:@var{port}} @itemx target remote @code{tcp:@var{host}:@var{port}} diff --git a/gdb/ser-socket.c b/gdb/ser-socket.c new file mode 100644 index 0000000000..6275447e2b --- /dev/null +++ b/gdb/ser-socket.c @@ -0,0 +1,115 @@ +/* Serial interface for local domain connections on Un*x like systems. + + Copyright (C) 1992-2018 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "defs.h" +#include "serial.h" +#include "ser-base.h" + +#include +#include + +/* Open a AF_UNIX socket. */ +int +socket_open (struct serial *scb, const char *name) +{ + struct sockaddr_un addr; + + memset (&addr, 0, sizeof addr); + addr.sun_family = AF_UNIX; +#ifndef UNIX_MAX_PATH +# define UNIX_MAX_PATH 108 +#endif + strncpy (addr.sun_path, name, UNIX_MAX_PATH - 1); + + int sock = socket (AF_UNIX, SOCK_STREAM, 0); + + if (connect (sock, (struct sockaddr *) &addr, + sizeof (struct sockaddr_un)) < 0) + { + close (sock); + scb->fd = -1; + return -1; + } + + scb->fd = sock; + + return 0; +} + +void +socket_close (struct serial *scb) +{ + if (scb->fd == -1) + return; + + close (scb->fd); + scb->fd = -1; +} + +static int +socket_read_prim (struct serial *scb, size_t count) +{ + return recv (scb->fd, scb->buf, count, 0); +} + +static int +socket_write_prim (struct serial *scb, const void *buf, size_t count) +{ + return send (scb->fd, buf, count, 0); +} + +static int +ser_socket_send_break (struct serial *scb) +{ + /* Send telnet IAC and BREAK characters. */ + return (serial_write (scb, "\377\363", 2)); +} + +/* The SOCKET ops. */ + +static const struct serial_ops socket_ops = +{ + "socket", + socket_open, + socket_close, + NULL, + ser_base_readchar, + ser_base_write, + ser_base_flush_output, + ser_base_flush_input, + ser_socket_send_break, + ser_base_raw, + ser_base_get_tty_state, + ser_base_copy_tty_state, + ser_base_set_tty_state, + ser_base_print_tty_state, + ser_base_setbaudrate, + ser_base_setstopbits, + ser_base_setparity, + ser_base_drain_output, + ser_base_async, + socket_read_prim, + socket_write_prim +}; + +void +_initialize_ser_socket (void) +{ + serial_add_interface (&socket_ops); +} diff --git a/gdb/serial.c b/gdb/serial.c index fb2b212918..f1fcd95e3c 100644 --- a/gdb/serial.c +++ b/gdb/serial.c @@ -213,7 +213,17 @@ serial_open (const char *name) else if (strchr (name, ':')) ops = serial_interface_lookup ("tcp"); else - ops = serial_interface_lookup ("hardwire"); + { +#ifndef USE_WIN32API + /* Check to see if name is a socket. If it is, then treat it + as such. Otherwise assume that it's a character device. */ + struct stat sb; + if (0 == stat (name, &sb) && ((sb.st_mode & S_IFMT) == S_IFSOCK)) + ops = serial_interface_lookup ("socket"); + else +#endif + ops = serial_interface_lookup ("hardwire"); + } if (!ops) return NULL;