From: John Darrington <john@darrington.wattle.id.au>
To: gdb-patches@sourceware.org
Cc: John Darrington <john@darrington.wattle.id.au>
Subject: [PATCH 1/4] GDBSERVER: Listen on a unix domain (instead of TCP) socket if requested.
Date: Sat, 13 Oct 2018 17:58:00 -0000 [thread overview]
Message-ID: <20181013175801.2670-1-john@darrington.wattle.id.au> (raw)
In-Reply-To: <cc6ec9f9-20c0-ee07-7047-acd1801a2b1a@redhat.com>
When invoking gdbserver, if the COMM parameter takes the form "unix::/path/name"
then a local (unix) domain socket will be created with that name and gdbserver
will listen for connections on that.
gdb/
* NEWS: Mention new feature.
gdb/gdbserver/
* configure.ac (AC_CHECK_HEADERS): Add sys/un.h.
* configure: Regenerate.
* remote-utils.c (remote_prepare): Create a local socket if requested.
(remote_open): Don't attempt to open a file if it's a socket.
(handle_accept_event): Display the name of the socket on connection.
gdb/common/
* netstuff.c (parse_connection_spec)[prefixes]: New member for local domain sockets.
---
gdb/NEWS | 4 ++
gdb/common/netstuff.c | 9 +++
gdb/gdbserver/configure.ac | 2 +-
gdb/gdbserver/remote-utils.c | 148 ++++++++++++++++++++++++++++++-------------
4 files changed, 117 insertions(+), 46 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 126e61e282..23de349324 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -15,6 +15,10 @@
can be passed using the '[ADDRESS]:PORT' notation, or the regular
'ADDRESS:PORT' method.
+* GDB and GDBserver now support local domain socket connections. The
+ name of a local domain socket may be provided instead of the
+ [ADDRESS]:PORT notation.
+
* DWARF index cache: GDB can now automatically save indices of DWARF
symbols on disk to speed up further loading of the same binaries.
diff --git a/gdb/common/netstuff.c b/gdb/common/netstuff.c
index c1c401ccb2..8da6aba24e 100644
--- a/gdb/common/netstuff.c
+++ b/gdb/common/netstuff.c
@@ -57,6 +57,8 @@ parse_connection_spec_without_prefix (std::string spec, struct addrinfo *hint)
|| std::count (spec.begin (),
spec.end (), ':') > 1)));
+ bool is_unix = hint->ai_family == AF_UNIX;
+
if (is_ipv6)
{
if (spec[0] == '[')
@@ -109,6 +111,12 @@ parse_connection_spec_without_prefix (std::string spec, struct addrinfo *hint)
if (ret.host_str.empty ())
ret.host_str = "localhost";
+ if (is_unix && ret.host_str != "localhost")
+ error (_("The host name must be empty or 'localhost' for a unix domain socket."));
+
+ if (is_unix && ret.port_str.empty ())
+ error (_("A path name must be specified for a unix domain socket."));
+
return ret;
}
@@ -138,6 +146,7 @@ parse_connection_spec (const char *spec, struct addrinfo *hint)
{ "tcp4:", AF_INET, SOCK_STREAM },
{ "udp6:", AF_INET6, SOCK_DGRAM },
{ "tcp6:", AF_INET6, SOCK_STREAM },
+ { "unix:", AF_LOCAL, SOCK_STREAM },
};
for (const host_prefix prefix : prefixes)
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index fa3ca53efd..de7e7d4103 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -98,7 +98,7 @@ ACX_CONFIGURE_DIR(["../../libiberty"], ["build-libiberty-gdbserver"])
AC_CHECK_HEADERS(termios.h sys/reg.h string.h dnl
proc_service.h sys/procfs.h linux/elf.h dnl
fcntl.h signal.h sys/file.h dnl
- sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
+ sys/ioctl.h netinet/in.h sys/socket.h sys/un.h netdb.h dnl
netinet/tcp.h arpa/inet.h)
AC_FUNC_FORK
AC_CHECK_FUNCS(getauxval pread pwrite pread64 setns)
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 9199a9c7ad..0eb53c2116 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -38,6 +38,9 @@
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
+#if HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -193,20 +196,33 @@ handle_accept_event (int err, gdb_client_data client_data)
descriptor open for add_file_handler to wait for a new connection. */
delete_file_handler (listen_desc);
- /* Convert IP address to string. */
- char orig_host[GDB_NI_MAX_ADDR], orig_port[GDB_NI_MAX_PORT];
-
- int r = getnameinfo ((struct sockaddr *) &sockaddr, len,
- orig_host, sizeof (orig_host),
- orig_port, sizeof (orig_port),
- NI_NUMERICHOST | NI_NUMERICSERV);
+ if (sockaddr.ss_family == AF_UNIX)
+ {
+ struct sockaddr_un su;
+ socklen_t len;
+ if (getsockname (listen_desc, (struct sockaddr *) &su, &len) != 0)
+ perror (_("Could not obtain remote address"));
- if (r != 0)
- fprintf (stderr, _("Could not obtain remote address: %s\n"),
- gai_strerror (r));
+ fprintf (stderr, _("Remote debugging on local socket bound to %s\n"),
+ su.sun_path);
+ }
else
- fprintf (stderr, _("Remote debugging from host %s, port %s\n"),
- orig_host, orig_port);
+ {
+ /* Convert IP address to string. */
+ char orig_host[GDB_NI_MAX_ADDR], orig_port[GDB_NI_MAX_PORT];
+
+ int r = getnameinfo ((struct sockaddr *) &sockaddr, len,
+ orig_host, sizeof (orig_host),
+ orig_port, sizeof (orig_port),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+
+ if (r != 0)
+ fprintf (stderr, _("Could not obtain remote address: %s\n"),
+ gai_strerror (r));
+ else
+ fprintf (stderr, _("Remote debugging from host %s, port %s\n"),
+ orig_host, orig_port);
+ }
enable_async_notification (remote_desc);
@@ -250,6 +266,9 @@ remote_prepare (const char *name)
struct addrinfo hint;
struct addrinfo *ainfo;
+ struct sockaddr *addr;
+ socklen_t addrlen;
+
memset (&hint, 0, sizeof (hint));
/* Assume no prefix will be passed, therefore we should use
AF_UNSPEC. */
@@ -258,7 +277,7 @@ remote_prepare (const char *name)
hint.ai_protocol = IPPROTO_TCP;
parsed_connection_spec parsed
- = parse_connection_spec_without_prefix (name, &hint);
+ = parse_connection_spec (name, &hint);
if (parsed.port_str.empty ())
{
@@ -276,47 +295,86 @@ remote_prepare (const char *name)
}
#endif
- int r = getaddrinfo (parsed.host_str.c_str (), parsed.port_str.c_str (),
- &hint, &ainfo);
+ struct sockaddr_un unix_addr;
- if (r != 0)
- error (_("%s: cannot resolve name: %s"), name, gai_strerror (r));
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
+#endif
- scoped_free_addrinfo freeaddrinfo (ainfo);
+ if (hint.ai_family == AF_LOCAL)
+ {
+ const char *sock_name = parsed.port_str.c_str ();
+ if (parsed.port_str.length() > UNIX_PATH_MAX - 1)
+ {
+ error
+ (_("%s is too long. Socket names may be no longer than %s bytes."),
+ sock_name, pulongest (UNIX_PATH_MAX - 1));
+ return;
+ }
+ listen_desc = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (listen_desc < 0)
+ perror_with_name ("Can't open socket");
- struct addrinfo *iter;
+ memset (&unix_addr, 0, sizeof (unix_addr));
+ unix_addr.sun_family = AF_UNIX;
+ strncpy (unix_addr.sun_path, sock_name, UNIX_PATH_MAX - 1);
- for (iter = ainfo; iter != NULL; iter = iter->ai_next)
- {
- listen_desc = gdb_socket_cloexec (iter->ai_family, iter->ai_socktype,
- iter->ai_protocol);
+ struct stat statbuf;
+ int stat_result = stat (sock_name, &statbuf);
+ if (stat_result == 0
+ && (S_IFSOCK & statbuf.st_mode))
+ unlink (sock_name);
- if (listen_desc >= 0)
- break;
+ addr = (struct sockaddr *) &unix_addr;
+ addrlen = sizeof (unix_addr);
}
+ else
+ {
+ struct addrinfo *iter;
- if (iter == NULL)
- perror_with_name ("Can't open socket");
+ int r = getaddrinfo (parsed.host_str.c_str (),
+ parsed.port_str.c_str (),
+ &hint, &ainfo);
- /* Allow rapid reuse of this port. */
- tmp = 1;
- setsockopt (listen_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
- sizeof (tmp));
+ if (r != 0)
+ error (_("%s: cannot resolve name: %s"), name, gai_strerror (r));
- switch (iter->ai_family)
- {
- case AF_INET:
- ((struct sockaddr_in *) iter->ai_addr)->sin_addr.s_addr = INADDR_ANY;
- break;
- case AF_INET6:
- ((struct sockaddr_in6 *) iter->ai_addr)->sin6_addr = in6addr_any;
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Invalid 'ai_family' %d\n"), iter->ai_family);
+ scoped_free_addrinfo freeaddrinfo (ainfo);
+
+ for (iter = ainfo; iter != NULL; iter = iter->ai_next)
+ {
+ listen_desc = gdb_socket_cloexec (iter->ai_family, iter->ai_socktype,
+ iter->ai_protocol);
+
+ if (listen_desc >= 0)
+ break;
+ }
+
+ if (iter == NULL)
+ perror_with_name ("Can't open socket");
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (listen_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
+ sizeof (tmp));
+
+ switch (iter->ai_family)
+ {
+ case AF_INET:
+ ((struct sockaddr_in *) iter->ai_addr)->sin_addr.s_addr = INADDR_ANY;
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *) iter->ai_addr)->sin6_addr = in6addr_any;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("Invalid 'ai_family' %d\n"), iter->ai_family);
+ }
+ addr = iter->ai_addr;
+ addrlen = iter->ai_addrlen;
}
- if (bind (listen_desc, iter->ai_addr, iter->ai_addrlen) != 0)
+ if (bind (listen_desc, addr, addrlen) != 0)
perror_with_name ("Can't bind address");
if (listen (listen_desc, 1) != 0)
@@ -354,11 +412,11 @@ remote_open (const char *name)
}
#ifndef USE_WIN32API
else if (port_str == NULL)
- {
+ {
struct stat statbuf;
if (stat (name, &statbuf) == 0
- && (S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode)))
+ && (S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode)))
remote_desc = open (name, O_RDWR);
else
{
--
2.11.0
next prev parent reply other threads:[~2018-10-13 17:58 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-10-09 17:33 Gdbserver can listen on local domain sockets John Darrington
2018-10-09 17:33 ` [PATCH] GDBSERVER: Listen on a unix domain (instead of TCP) socket if requested John Darrington
2018-10-09 17:56 ` Eli Zaretskii
2018-10-09 18:02 ` Pedro Alves
2018-10-09 18:41 ` John Darrington
2018-10-09 18:53 ` Pedro Alves
2018-10-09 19:00 ` John Darrington
2018-10-09 19:06 ` Pedro Alves
2018-10-13 17:58 ` John Darrington [this message]
2018-10-13 17:58 ` [PATCH 4/4] GDB: Remote target can now accept the form unix::/path/to/socket John Darrington
2018-10-13 17:58 ` [PATCH 2/4] GDB: Document the unix::/path/to/socket of remote connection John Darrington
2018-10-13 18:11 ` Eli Zaretskii
2018-10-15 9:31 ` Simon Tatham
2018-10-15 11:28 ` John Darrington
2018-10-18 20:21 ` Sergio Durigan Junior
2018-10-13 17:58 ` [PATCH 3/4] GDB: Fix documentation for invoking GDBSERVER John Darrington
2018-10-13 18:10 ` Eli Zaretskii
2018-10-18 20:27 ` Sergio Durigan Junior
2018-10-19 7:05 ` John Darrington
2018-10-19 20:45 ` Sergio Durigan Junior
2018-10-21 7:33 ` John Darrington
2018-10-21 16:47 ` Sergio Durigan Junior
2018-10-23 18:25 ` John Darrington
2018-10-23 18:58 ` Sergio Durigan Junior
2018-10-13 18:12 ` [PATCH 1/4] GDBSERVER: Listen on a unix domain (instead of TCP) socket if requested Eli Zaretskii
2018-10-18 20:18 ` Sergio Durigan Junior
2018-10-19 18:55 ` John Darrington
2018-10-19 19:43 ` Sergio Durigan Junior
2018-10-28 16:20 ` Simon Marchi
2018-10-28 18:10 ` John Darrington
2018-10-28 18:51 ` Simon Marchi
2018-10-29 8:24 ` John Darrington
2018-10-29 9:13 ` Rainer Orth
2018-10-29 9:38 ` Rainer Orth
2018-10-29 15:52 ` Simon Marchi
2018-10-29 16:26 ` John Darrington
2018-10-29 16:42 ` Sergio Durigan Junior
2018-10-29 17:34 ` John Darrington
2018-10-31 13:54 ` Simon Marchi
2018-10-29 18:32 ` Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181013175801.2670-1-john@darrington.wattle.id.au \
--to=john@darrington.wattle.id.au \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).