* [patch] IPv6 support for gdbserver
@ 2006-09-27 16:33 Jan Kratochvil
2006-09-27 18:20 ` Daniel Jacobowitz
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kratochvil @ 2006-09-27 16:33 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 178 bytes --]
Hi,
while it may not make too much sense here is IPv6 support ("tcp6:"/"udp6:"
address prefixes, autodetected if possible) for
target-remote/gdbserver/gdbreplay.
Regards,
Jan
[-- Attachment #2: gdb-6.5-IPv6.patch --]
[-- Type: text/plain, Size: 27559 bytes --]
2006-09-27 Jan Kratochvil <jan.kratochvil@redhat.com>
* ser-tcp.c (net_open): Support IPv6, "tcp6:"&co. notation.
2006-09-27 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdbreplay.c (remote_open): Support IPv6, "tcp6:"&co. notation.
* remote-utils.c (remote_open): Likewise.
2006-09-27 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.texinfo (Connecting to a remote target): Support IPv6,
"tcp6:"&co. notation.
(Using the gdbserver program): Likewise.
Index: gdb/ser-tcp.c
===================================================================
RCS file: /cvs/src/src/gdb/ser-tcp.c,v
retrieving revision 1.26
diff -u -p -r1.26 ser-tcp.c
--- gdb/ser-tcp.c 10 Feb 2006 22:01:43 -0000 1.26
+++ gdb/ser-tcp.c 27 Sep 2006 13:11:01 -0000
@@ -68,67 +68,129 @@ void _initialize_ser_tcp (void);
int
net_open (struct serial *scb, const char *name)
{
- char *port_str, hostname[100];
- int n, port, tmp;
- int use_udp;
- struct hostent *hostent;
- struct sockaddr_in sockaddr;
+ char *name_base;
+ char *port_str;
+ int n, tmp;
#ifdef USE_WIN32API
u_long ioarg;
#else
int ioarg;
#endif
-
- use_udp = 0;
- if (strncmp (name, "udp:", 4) == 0)
+ struct prefix
+ {
+ const char *string;
+ int family;
+ int socktype;
+ };
+ const struct prefix prefixes[] =
+ {
+ { "udp:", AF_UNSPEC, SOCK_DGRAM },
+ { "tcp:", AF_UNSPEC, SOCK_STREAM },
+ { "udp4:", AF_INET, SOCK_DGRAM },
+ { "tcp4:", AF_INET, SOCK_STREAM },
+ { "udp6:", AF_INET6, SOCK_DGRAM },
+ { "tcp6:", AF_INET6, SOCK_STREAM },
+ };
+ const struct prefix *prefix;
+ struct addrinfo hints, *hints_p = NULL;
+ struct addrinfo *addrinfo_base, *addrinfo = NULL;
+ struct address
+ {
+ const char *string;
+ int family;
+ };
+ const struct address addresses[] =
+ {
+ { "::1", AF_INET6 },
+ { "127.0.0.1", AF_INET },
+ { "localhost", AF_UNSPEC },
+ };
+ const struct address *address;
+ int fake_localhost = 0;
+
+ name_base = xstrdup (name);
+ name = name_base;
+ for (prefix = prefixes; prefix < prefixes + ARRAY_SIZE (prefixes); prefix++)
+ if (strncmp (name, prefix->string, strlen (prefix->string)) == 0)
+ {
+ name += strlen (prefix->string);
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = prefix->family;
+ hints.ai_socktype = prefix->socktype;
+ hints_p = &hints;
+ break;
+ }
+ if (!(hints_p != NULL && hints_p->ai_family == AF_INET)
+ && name[0] == '[' && (port_str = strchr (name, ']')))
{
- use_udp = 1;
- name = name + 4;
+ name++;
+ *port_str++ = 0;
}
- else if (strncmp (name, "tcp:", 4) == 0)
- name = name + 4;
-
- port_str = strchr (name, ':');
-
- if (!port_str)
- error (_("net_open: No colon in host name!")); /* Shouldn't ever happen */
-
- tmp = min (port_str - name, (int) sizeof hostname - 1);
- strncpy (hostname, name, tmp); /* Don't want colon */
- hostname[tmp] = '\000'; /* Tie off host name */
- port = atoi (port_str + 1);
+ else
+ port_str = strchr (name, ':');
+ /* It may happen with IPv6 for like "[::1]". */
+ if (port_str == NULL || *port_str != ':')
+ error (_("net_open: No colon in host name!"));
+ *port_str++ = 0;
/* default hostname is localhost */
- if (!hostname[0])
- strcpy (hostname, "localhost");
+ if (name[0] == 0)
+ fake_localhost = 1;
- hostent = gethostbyname (hostname);
- if (!hostent)
+ for (address = addresses;
+ address < addresses + sizeof (addresses) / sizeof (*addresses);
+ address++)
{
- fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
- errno = ENOENT;
- return -1;
- }
+ int fatal;
- if (use_udp)
- scb->fd = socket (PF_INET, SOCK_DGRAM, 0);
- else
- scb->fd = socket (PF_INET, SOCK_STREAM, 0);
+ if (fake_localhost)
+ {
+ if (address->family != AF_UNSPEC
+ && hints_p != NULL && hints_p->ai_family != address->family)
+ continue;
+ name = (char *) address->string;
+ fatal = (address + 1
+ >= addresses + sizeof (addresses) / sizeof (*addresses));
+ }
+ else
+ fatal = 1;
- if (scb->fd < 0)
- return -1;
-
- sockaddr.sin_family = PF_INET;
- sockaddr.sin_port = htons (port);
- memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
- sizeof (struct in_addr));
+ n = getaddrinfo (name, port_str, hints_p, &addrinfo_base);
+ if (n != 0)
+ {
+ if (!fatal)
+ continue;
+ fprintf_unfiltered (gdb_stderr, "%s:%s: cannot resolve name: %s\n",
+ name, port_str, gai_strerror (n));
+ errno = ENOENT;
+ free (name_base);
+ return -1;
+ }
+ free (name_base);
+
+ for (addrinfo = addrinfo_base; addrinfo != NULL; addrinfo = addrinfo->ai_next)
+ {
+ scb->fd = socket (addrinfo->ai_family, addrinfo->ai_socktype,
+ addrinfo->ai_protocol);
+ if (scb->fd >= 0)
+ break;
+ }
+ if (addrinfo == NULL)
+ {
+ if (!fatal)
+ continue;
+ freeaddrinfo (addrinfo_base);
+ return -1;
+ }
+ break;
+ }
/* set socket nonblocking */
ioarg = 1;
ioctl (scb->fd, FIONBIO, &ioarg);
/* Use Non-blocking connect. connect() will return 0 if connected already. */
- n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
+ n = connect (scb->fd, addrinfo->ai_addr, addrinfo->ai_addrlen);
if (n < 0
#ifdef USE_WIN32API
@@ -144,6 +206,7 @@ net_open (struct serial *scb, const char
errno = WSAGetLastError();
#endif
net_close (scb);
+ freeaddrinfo (addrinfo_base);
return -1;
}
@@ -166,6 +229,7 @@ net_open (struct serial *scb, const char
{
errno = EINTR;
net_close (scb);
+ freeaddrinfo (addrinfo_base);
return -1;
}
}
@@ -193,6 +257,7 @@ net_open (struct serial *scb, const char
if (polls > TIMEOUT * POLL_INTERVAL)
errno = ETIMEDOUT;
net_close (scb);
+ freeaddrinfo (addrinfo_base);
return -1;
}
}
@@ -212,6 +277,7 @@ net_open (struct serial *scb, const char
if (err)
errno = err;
net_close (scb);
+ freeaddrinfo (addrinfo_base);
return -1;
}
}
@@ -220,7 +286,7 @@ net_open (struct serial *scb, const char
ioarg = 0;
ioctl (scb->fd, FIONBIO, &ioarg);
- if (use_udp == 0)
+ if (addrinfo->ai_protocol == SOCK_STREAM)
{
/* Disable Nagle algorithm. Needed in some cases. */
tmp = 1;
@@ -234,6 +300,7 @@ net_open (struct serial *scb, const char
signal (SIGPIPE, SIG_IGN);
#endif
+ freeaddrinfo (addrinfo_base);
return 0;
}
Index: gdb/gdbserver/gdbreplay.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/gdbreplay.c,v
retrieving revision 1.12
diff -u -p -r1.12 gdbreplay.c
--- gdb/gdbserver/gdbreplay.c 23 Jul 2006 03:52:15 -0000 1.12
+++ gdb/gdbserver/gdbreplay.c 27 Sep 2006 13:11:10 -0000
@@ -115,6 +115,8 @@ remote_close (void)
static void
remote_open (char *name)
{
+ char *name_orig = name;
+
if (!strchr (name, ':'))
{
fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
@@ -127,14 +129,145 @@ remote_open (char *name)
static int winsock_initialized;
#endif
char *port_str;
- int port;
- struct sockaddr_in sockaddr;
socklen_t tmp;
- int tmp_desc;
+ int tmp_desc = -1;
+ struct prefix
+ {
+ const char *string;
+ int family;
+ int socktype;
+ };
+ const struct prefix prefixes[] =
+ {
+ { "udp:", AF_UNSPEC, SOCK_DGRAM },
+ { "tcp:", AF_UNSPEC, SOCK_STREAM },
+ { "udp4:", AF_INET, SOCK_DGRAM },
+ { "tcp4:", AF_INET, SOCK_STREAM },
+ { "udp6:", AF_INET6, SOCK_DGRAM },
+ { "tcp6:", AF_INET6, SOCK_STREAM },
+ };
+ const struct prefix *prefix;
+ struct addrinfo hints, *hints_p = NULL;
+ struct addrinfo *addrinfo_base, *addrinfo = NULL;
+ char back_host[64], back_port[16];
+ int fake_any = 0, err;
+ char *name_base;
+ struct address
+ {
+ const char *string;
+ int family;
+ };
+ const struct address addresses[] =
+ {
+ { "::", AF_INET6 },
+ { "127.0.0.1", AF_INET },
+ { "localhost", AF_UNSPEC },
+ };
+ const struct address *address;
+
+ name_base = strdup (name);
+ name = name_base;
+ for (prefix = prefixes;
+ prefix < prefixes + sizeof (prefixes) / sizeof (*prefixes);
+ prefix++)
+ if (strncmp (name, prefix->string, strlen (prefix->string)) == 0)
+ {
+ name += strlen (prefix->string);
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = prefix->family;
+ hints.ai_socktype = prefix->socktype;
+ hints_p = &hints;
+ break;
+ }
+ if (!(hints_p != NULL && hints_p->ai_family == AF_INET)
+ && name[0] == '[' && (port_str = strchr (name, ']')))
+ {
+ name++;
+ *port_str++ = 0;
+ }
+ else
+ port_str = strchr (name, ':');
+ /* It may happen with IPv6 for like "[::1]". */
+ if (port_str == NULL || *port_str != ':')
+ {
+ fprintf (stderr, "net_open: No colon in host name!\n");
+ fflush (stderr);
+ exit (1);
+ }
+ *port_str++ = 0;
- port_str = strchr (name, ':');
+ /* We need to provide some fake name for resolving.
+ but I am not aware of any universal host string for both
+ `INADDR_ANY' and `in6addr_any'.
+ So we try those from `addresses' in the specified order. */
+ if (name[0] == 0)
+ fake_any = 1;
+
+ for (address = addresses;
+ address < addresses + sizeof (addresses) / sizeof (*addresses);
+ address++)
+ {
+ int fatal;
+
+ if (fake_any)
+ {
+ if (address->family != AF_UNSPEC
+ && hints_p != NULL && hints_p->ai_family != address->family)
+ continue;
+ name = (char *) address->string;
+ fatal = (address + 1
+ >= addresses + sizeof (addresses) / sizeof (*addresses));
+ }
+ else
+ fatal = 1;
+
+ err = getaddrinfo (name, port_str, hints_p, &addrinfo_base);
+ if (err != 0)
+ {
+ if (!fatal)
+ continue;
+ /* `name_base' is used here for `port_str'. */
+ fprintf (stderr, "%s:%s: cannot resolve name: %s\n",
+ name, port_str, gai_strerror (err));
+ fflush (stderr);
+ exit (1);
+ }
+ free (name_base);
+
+ for (addrinfo = addrinfo_base;
+ addrinfo != NULL;
+ addrinfo = addrinfo->ai_next)
+ {
+ tmp_desc = socket (addrinfo->ai_family, addrinfo->ai_socktype,
+ addrinfo->ai_protocol);
+ if (tmp_desc >= 0)
+ break;
+ }
+ if (addrinfo == NULL)
+ {
+ if (!fatal)
+ continue;
+ freeaddrinfo (addrinfo_base);
+ perror_with_name ("Can't open socket");
+ }
+ break;
+ }
- port = atoi (port_str + 1);
+ if (fake_any)
+ switch (addrinfo->ai_family)
+ {
+ case AF_INET:
+ ((struct sockaddr_in *)addrinfo->ai_addr)->sin_addr.s_addr
+ = INADDR_ANY;
+ break;
+ case AF_INET6:
+ memcpy (&((struct sockaddr_in6 *)addrinfo->ai_addr)->sin6_addr,
+ &in6addr_any, sizeof (in6addr_any));
+ break;
+ default:
+ fprintf (stderr, "Error setting 'any' listening for ai_family %d",
+ addrinfo->ai_family);
+ }
#ifdef USE_WIN32API
if (!winsock_initialized)
@@ -146,55 +279,83 @@ remote_open (char *name)
}
#endif
- tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
- if (tmp_desc < 0)
- perror_with_name ("Can't open socket");
-
/* Allow rapid reuse of this port. */
tmp = 1;
setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
sizeof (tmp));
- sockaddr.sin_family = PF_INET;
- sockaddr.sin_port = htons (port);
- sockaddr.sin_addr.s_addr = INADDR_ANY;
-
- if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
- || listen (tmp_desc, 1))
- perror_with_name ("Can't bind address");
-
- tmp = sizeof (sockaddr);
- remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
- if (remote_desc == -1)
- perror_with_name ("Accept failed");
-
- /* Enable TCP keep alive process. */
- tmp = 1;
- setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
-
- /* Tell TCP not to delay small packets. This greatly speeds up
- interactive response. */
- tmp = 1;
- setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
- (char *) &tmp, sizeof (tmp));
+ if (bind (tmp_desc, addrinfo->ai_addr, addrinfo->ai_addrlen)
+ || (addrinfo->ai_socktype != SOCK_DGRAM && listen (tmp_desc, 1)))
+ {
+ freeaddrinfo (addrinfo_base);
+ perror_with_name ("Can't bind address");
+ }
+
+ if (0 != getnameinfo (addrinfo->ai_addr, addrinfo->ai_addrlen,
+ back_host, sizeof (back_host),
+ back_port, sizeof (back_port),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ fprintf (stderr, "Error detecting listening address, trying anyway\n");
+ else
+ fprintf (stderr, "Listening on port %s (on host %s)\n",
+ back_port, back_host);
+ fflush (stderr);
- close (tmp_desc); /* No longer need this */
+ if (addrinfo->ai_socktype == SOCK_DGRAM)
+ remote_desc = tmp_desc;
+ else
+ {
+ struct sockaddr_in6 sockaddr6;
+ socklen_t sockaddr6_len;
+ sockaddr6_len = sizeof (sockaddr6);
+ remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr6, &sockaddr6_len);
+ if (remote_desc == -1)
+ {
+ freeaddrinfo (addrinfo_base);
+ perror_with_name ("Accept failed");
+ }
+
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
+
+ /* Tell TCP not to delay small packets. This greatly speeds up
+ interactive response. */
+ if (addrinfo->ai_socktype == SOCK_STREAM)
+ {
+ tmp = 1;
+ setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (tmp));
+ }
+ freeaddrinfo (addrinfo_base);
#ifndef USE_WIN32API
- close (tmp_desc); /* No longer need this */
+ close (tmp_desc); /* No longer need this */
- signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbreplay simply
- exits when the remote side dies. */
+ signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
+ exits when the remote side dies. */
#else
- closesocket (tmp_desc); /* No longer need this */
+ closesocket (tmp_desc); /* No longer need this */
#endif
+
+ /* Convert IP address to string. */
+ if (0 != getnameinfo ((struct sockaddr *) &sockaddr6, sockaddr6_len,
+ back_host, sizeof (back_host),
+ back_port, sizeof (back_port),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ fprintf (stderr, "Error detecting originating address, trying anyway\n");
+ else
+ fprintf (stderr, "Remote debugging from host %s port %s\n",
+ back_host, back_port);
+ }
+ fflush (stderr);
}
#if defined(F_SETFL) && defined (FASYNC)
fcntl (remote_desc, F_SETFL, FASYNC);
#endif
- fprintf (stderr, "Replay logfile using %s\n", name);
+ fprintf (stderr, "Replay logfile using %s\n", name_orig);
fflush (stderr);
}
Index: gdb/gdbserver/remote-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/remote-utils.c,v
retrieving revision 1.32
diff -u -p -r1.32 remote-utils.c
--- gdb/gdbserver/remote-utils.c 21 Sep 2006 16:09:54 -0000 1.32
+++ gdb/gdbserver/remote-utils.c 27 Sep 2006 13:11:10 -0000
@@ -157,14 +157,139 @@ remote_open (char *name)
static int winsock_initialized;
#endif
char *port_str;
- int port;
- struct sockaddr_in sockaddr;
socklen_t tmp;
- int tmp_desc;
+ int tmp_desc = -1;
+ struct prefix
+ {
+ const char *string;
+ int family;
+ int socktype;
+ };
+ const struct prefix prefixes[] =
+ {
+ { "udp:", AF_UNSPEC, SOCK_DGRAM },
+ { "tcp:", AF_UNSPEC, SOCK_STREAM },
+ { "udp4:", AF_INET, SOCK_DGRAM },
+ { "tcp4:", AF_INET, SOCK_STREAM },
+ { "udp6:", AF_INET6, SOCK_DGRAM },
+ { "tcp6:", AF_INET6, SOCK_STREAM },
+ };
+ const struct prefix *prefix;
+ struct addrinfo hints, *hints_p = NULL;
+ struct addrinfo *addrinfo_base, *addrinfo = NULL;
+ char back_host[64], back_port[16];
+ int fake_any = 0, err;
+ char *name_base;
+ struct address
+ {
+ const char *string;
+ int family;
+ };
+ const struct address addresses[] =
+ {
+ { "::", AF_INET6 },
+ { "127.0.0.1", AF_INET },
+ { "localhost", AF_UNSPEC },
+ };
+ const struct address *address;
+
+ name_base = strdup (name);
+ name = name_base;
+ for (prefix = prefixes;
+ prefix < prefixes + sizeof (prefixes) / sizeof (*prefixes);
+ prefix++)
+ if (strncmp (name, prefix->string, strlen (prefix->string)) == 0)
+ {
+ name += strlen (prefix->string);
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = prefix->family;
+ hints.ai_socktype = prefix->socktype;
+ hints_p = &hints;
+ break;
+ }
+ if (!(hints_p != NULL && hints_p->ai_family == AF_INET)
+ && name[0] == '[' && (port_str = strchr (name, ']')))
+ {
+ name++;
+ *port_str++ = 0;
+ }
+ else
+ port_str = strchr (name, ':');
+ /* It may happen with IPv6 for like "[::1]". */
+ if (port_str == NULL || *port_str != ':')
+ error ("net_open: No colon in host name!");
+ *port_str++ = 0;
+
+ /* We need to provide some fake name for resolving.
+ but I am not aware of any universal host string for both
+ `INADDR_ANY' and `in6addr_any'.
+ So we try those from `addresses' in the specified order. */
+ if (name[0] == 0)
+ fake_any = 1;
+
+ for (address = addresses;
+ address < addresses + sizeof (addresses) / sizeof (*addresses);
+ address++)
+ {
+ int fatal;
+
+ if (fake_any)
+ {
+ if (address->family != AF_UNSPEC
+ && hints_p != NULL && hints_p->ai_family != address->family)
+ continue;
+ name = (char *) address->string;
+ fatal = (address + 1
+ >= addresses + sizeof (addresses) / sizeof (*addresses));
+ }
+ else
+ fatal = 1;
+
+ err = getaddrinfo (name, port_str, hints_p, &addrinfo_base);
+ if (err != 0)
+ {
+ if (!fatal)
+ continue;
+ /* `name_base' is used here for `port_str'. */
+ error ("%s:%s: cannot resolve name: %s\n",
+ name, port_str, gai_strerror (err));
+ }
+ free (name_base);
- port_str = strchr (name, ':');
+ for (addrinfo = addrinfo_base;
+ addrinfo != NULL;
+ addrinfo = addrinfo->ai_next)
+ {
+ tmp_desc = socket (addrinfo->ai_family, addrinfo->ai_socktype,
+ addrinfo->ai_protocol);
+ if (tmp_desc >= 0)
+ break;
+ }
+ if (addrinfo == NULL)
+ {
+ if (!fatal)
+ continue;
+ freeaddrinfo (addrinfo_base);
+ perror_with_name ("Can't open socket");
+ }
+ break;
+ }
- port = atoi (port_str + 1);
+ if (fake_any)
+ switch (addrinfo->ai_family)
+ {
+ case AF_INET:
+ ((struct sockaddr_in *)addrinfo->ai_addr)->sin_addr.s_addr
+ = INADDR_ANY;
+ break;
+ case AF_INET6:
+ memcpy (&((struct sockaddr_in6 *)addrinfo->ai_addr)->sin6_addr,
+ &in6addr_any, sizeof (in6addr_any));
+ break;
+ default:
+ fprintf (stderr, "Error setting 'any' listening for ai_family %d",
+ addrinfo->ai_family);
+ }
#ifdef USE_WIN32API
if (!winsock_initialized)
@@ -176,54 +301,76 @@ remote_open (char *name)
}
#endif
- tmp_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (tmp_desc < 0)
- perror_with_name ("Can't open socket");
-
/* Allow rapid reuse of this port. */
tmp = 1;
setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
sizeof (tmp));
- sockaddr.sin_family = PF_INET;
- sockaddr.sin_port = htons (port);
- sockaddr.sin_addr.s_addr = INADDR_ANY;
-
- if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
- || listen (tmp_desc, 1))
- perror_with_name ("Can't bind address");
+ if (bind (tmp_desc, addrinfo->ai_addr, addrinfo->ai_addrlen)
+ || (addrinfo->ai_socktype != SOCK_DGRAM && listen (tmp_desc, 1)))
+ {
+ freeaddrinfo (addrinfo_base);
+ perror_with_name ("Can't bind address");
+ }
- fprintf (stderr, "Listening on port %d\n", port);
+ if (0 != getnameinfo (addrinfo->ai_addr, addrinfo->ai_addrlen,
+ back_host, sizeof (back_host),
+ back_port, sizeof (back_port),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ fprintf (stderr, "Error detecting listening address, trying anyway\n");
+ else
+ fprintf (stderr, "Listening on port %s (on host %s)\n",
+ back_port, back_host);
fflush (stderr);
- tmp = sizeof (sockaddr);
- remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
- if (remote_desc == -1)
- perror_with_name ("Accept failed");
-
- /* Enable TCP keep alive process. */
- tmp = 1;
- setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
-
- /* Tell TCP not to delay small packets. This greatly speeds up
- interactive response. */
- tmp = 1;
- setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
- (char *) &tmp, sizeof (tmp));
+ if (addrinfo->ai_socktype == SOCK_DGRAM)
+ remote_desc = tmp_desc;
+ else
+ {
+ struct sockaddr_in6 sockaddr6;
+ socklen_t sockaddr6_len;
+ sockaddr6_len = sizeof (sockaddr6);
+ remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr6, &sockaddr6_len);
+ if (remote_desc == -1)
+ {
+ freeaddrinfo (addrinfo_base);
+ perror_with_name ("Accept failed");
+ }
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
+
+ /* Tell TCP not to delay small packets. This greatly speeds up
+ interactive response. */
+ if (addrinfo->ai_socktype == SOCK_STREAM)
+ {
+ tmp = 1;
+ setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (tmp));
+ }
+ freeaddrinfo (addrinfo_base);
#ifndef USE_WIN32API
- close (tmp_desc); /* No longer need this */
+ close (tmp_desc); /* No longer need this */
- signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
- exits when the remote side dies. */
+ signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
+ exits when the remote side dies. */
#else
- closesocket (tmp_desc); /* No longer need this */
+ closesocket (tmp_desc); /* No longer need this */
#endif
- /* Convert IP address to string. */
- fprintf (stderr, "Remote debugging from host %s\n",
- inet_ntoa (sockaddr.sin_addr));
+ /* Convert IP address to string. */
+ if (0 != getnameinfo ((struct sockaddr *) &sockaddr6, sockaddr6_len,
+ back_host, sizeof (back_host),
+ back_port, sizeof (back_port),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ fprintf (stderr, "Error detecting originating address, trying anyway\n");
+ else
+ fprintf (stderr, "Remote debugging from host %s port %s\n",
+ back_host, back_port);
+ }
+ fflush (stderr);
}
#if defined(F_SETFL) && defined (FASYNC)
Index: gdb/doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.355
diff -u -p -r1.355 gdb.texinfo
--- gdb/doc/gdb.texinfo 21 Sep 2006 14:01:12 -0000 1.355
+++ gdb/doc/gdb.texinfo 27 Sep 2006 13:11:10 -0000
@@ -12404,8 +12404,10 @@ If you're using a serial line, you may w
(@pxref{Remote configuration, set remotebaud}) before the
@code{target} command.
-@item target remote @code{@var{host}:@var{port}}
+@item target remote @code{@var{host}:@var{port}}
@itemx target remote @code{tcp:@var{host}:@var{port}}
+@itemx target remote @code{tcp4:@var{host}:@var{port}}
+@itemx target remote @code{tcp6:@var{host}:@var{port}}
@cindex @acronym{TCP} port, @code{target remote}
Debug using a @acronym{TCP} connection to @var{port} on @var{host}.
The @var{host} may be either a host name or a numeric @acronym{IP}
@@ -12414,6 +12416,9 @@ the target machine itself, if it is dire
it might be a terminal server which in turn has a serial line to the
target.
+@code{tcp6:} prefix forces IPv6 network connection while @code{tcp4:} forces
+IPv4, both on the reliable stream TCP connection.
+
For example, to connect to port 2828 on a terminal server named
@code{manyfarms}:
@@ -12434,10 +12439,15 @@ target remote :1234
Note that the colon is still required here.
@item target remote @code{udp:@var{host}:@var{port}}
+@itemx target remote @code{udp6:@var{host}:@var{port}}
+@itemx target remote @code{udp4:@var{host}:@var{port}}
@cindex @acronym{UDP} port, @code{target remote}
Debug using @acronym{UDP} packets to @var{port} on @var{host}. For example, to
connect to @acronym{UDP} port 2828 on a terminal server named @code{manyfarms}:
+@code{udp6:} prefix forces IPv6 network connection while @code{udp4:} forces
+IPv4, both on the unreliable datagram UDP connection.
+
@smallexample
target remote udp:manyfarms:2828
@end smallexample
@@ -12578,14 +12588,30 @@ The only difference from the previous ex
specifying that you are communicating with the host @value{GDBN} via
TCP. The @samp{host:2345} argument means that @code{gdbserver} is to
expect a TCP connection from machine @samp{host} to local TCP port 2345.
-(Currently, the @samp{host} part is ignored.) You can choose any number
-you want for the port number as long as it does not conflict with any
-TCP ports already in use on the target system (for example, @code{23} is
-reserved for @code{telnet}).@footnote{If you choose a port number that
-conflicts with another service, @code{gdbserver} prints an error message
+(The @samp{host} part is usually omitted as it defaults to listen from any
+host. You may use a local address as expected by the @code{bind} syscall.)
+You can choose any number you want for the port number as long as it does not
+conflict with any TCP ports already in use on the target system (for example,
+@code{23} is reserved for @code{telnet}).@footnote{If you choose a port number
+that conflicts with another service, @code{gdbserver} prints an error message
and exits.} You must use the same port number with the host @value{GDBN}
@code{target remote} command.
+@item gdbserver @code{tcp:@var{host}:@var{port}} emacs foo.txt
+@itemx gdbserver @code{tcp6:@var{host}:@var{port}} emacs foo.txt
+@itemx gdbserver @code{tcp4:@var{host}:@var{port}} emacs foo.txt
+@itemx gdbserver @code{udp:@var{host}:@var{port}} emacs foo.txt
+@itemx gdbserver @code{udp6:@var{host}:@var{port}} emacs foo.txt
+@itemx gdbserver @code{udp4:@var{host}:@var{port}} emacs foo.txt
+
+The @code{::} part can be also replaced by the optional @var{host} part as
+in the sample case of @code{tcp:@var{host}:@var{port}}.
+These all alternative syntaxes force either the reliable stream TCP protocol or
+the unreliable datagram UDP protocol appropriately. You may also force the use
+of IPv6 or IPv4 network connections; @code{tcp:} and @code{udp:} select the
+network version type according to the provided @var{host}.
+The connection type defaults to the @code{tcp:} prefix behavior.
+
On some targets, @code{gdbserver} can also attach to running programs.
This is accomplished via the @code{--attach} argument. The syntax is:
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [patch] IPv6 support for gdbserver 2006-09-27 16:33 [patch] IPv6 support for gdbserver Jan Kratochvil @ 2006-09-27 18:20 ` Daniel Jacobowitz 2006-09-27 18:56 ` Jan Kratochvil 0 siblings, 1 reply; 10+ messages in thread From: Daniel Jacobowitz @ 2006-09-27 18:20 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches On Wed, Sep 27, 2006 at 06:33:37PM +0200, Jan Kratochvil wrote: > Hi, > > while it may not make too much sense here is IPv6 support ("tcp6:"/"udp6:" > address prefixes, autodetected if possible) for > target-remote/gdbserver/gdbreplay. Hi Jan, One trend I've noticed in a lot of your patches is that they're very focused on the environment you're working in (Red Hat Linux). It's very important that when you modify the FSF GDB, you consider all the places where it is used and the different possible environments. As a specific example, I suspect that this would break GDB builds on a number of targets - getaddrinfo is not sufficiently widely available to use without testing for it, and I don't know if it requires additional libraries. It's usually better to be safe than sorry with these things. Maybe another list reader knows better than I do what we would need to do to use this support portably. Do you think the GDB support is useful enough to merge? I don't have a feeling either way; I don't use IPv6, but I realize more and more people do, so this might be a good (and NEWS-worthy) feature. The gdbserver/gdbreplay support I am more skeptical about. You've added lots of address parsing code to what is supposed to be a very minimal program. But today gdbserver always binds to any available interface, so there must be a simpler way to check for any INET6 interfaces similarly (assuming the current code won't). Maybe we should add stdin/stdout support to gdbserver and make an external utility handle any more fancy networking scenarios. I'm thinking of "socat" here. What do you think of that idea? We've done stdin/stdout for other stubs in the past and it's quite handy. Or if you want to leave inferior stdout alone you can use two specified file descriptors. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-09-27 18:20 ` Daniel Jacobowitz @ 2006-09-27 18:56 ` Jan Kratochvil 2006-09-27 19:06 ` Daniel Jacobowitz 0 siblings, 1 reply; 10+ messages in thread From: Jan Kratochvil @ 2006-09-27 18:56 UTC (permalink / raw) To: gdb-patches; +Cc: Daniel Jacobowitz On Wed, 27 Sep 2006 20:20:38 +0200, Daniel Jacobowitz wrote: ... > focused on the environment you're working in (Red Hat Linux). ... > I suspect that this would break GDB builds on a number of targets I was thinking about this a bit, forgot to write a not while posting it... Yes, the current patch is not portable - as it does not need to be. I was thinking whether to post the patch at all as IMO it does not make much sense (nowadays) for gdb to support IPv6, just Red Hat requires it. Still I do not want to invest a lot of time for the autoconf/portability stuff if it gets dropped down upstream (like by you) afterwards anyway (sometimes right, no problem with it). It should have been marked more as "RFC" patch. It is fine for me to update the patch upon request if it gets merged this way. Still it is not acceptable for me to rewrite the patch from scratch just for the upstream without reusability for Red Hat (as I was feeling for the case of SIGSTOP vs. ptrace(2) due to a different kernel variant in use). At least I do not think I am expected to do this in RH. I hope I cleared it up; I try to be upstream-cooperative. ... > so there must be a simpler way to check for any INET6 > interfaces similarly (assuming the current code won't). I feel there should be a simpler way. It works now fine, I intend to update it. > Maybe we should add stdin/stdout support to gdbserver and make an > external utility handle any more fancy networking scenarios. I'm > thinking of "socat" here. What do you think of that idea? We've done > stdin/stdout for other stubs in the past and it's quite handy. Or if > you want to leave inferior stdout alone you can use two specified file > descriptors. I do not know, I used only gdb stub or gdbserver on full GNU/Linux. Still I feel it is more complicated to compile both stripped-down gdbserver AND IPv6-enabled socat and connect them together on the target UNIX system than just to compile there the IPv6-enabled (autoconf-configured) gdbserver. Still it looks simple enough to provide the fd interface for gdbserver, if it is going to be imported upstream. Regards, Jan ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-09-27 18:56 ` Jan Kratochvil @ 2006-09-27 19:06 ` Daniel Jacobowitz 2006-09-30 15:28 ` Jan Kratochvil 0 siblings, 1 reply; 10+ messages in thread From: Daniel Jacobowitz @ 2006-09-27 19:06 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches On Wed, Sep 27, 2006 at 08:55:47PM +0200, Jan Kratochvil wrote: > On Wed, 27 Sep 2006 20:20:38 +0200, Daniel Jacobowitz wrote: > ... > > focused on the environment you're working in (Red Hat Linux). > ... > > I suspect that this would break GDB builds on a number of targets > > I was thinking about this a bit, forgot to write a not while posting it... > Yes, the current patch is not portable - as it does not need to be. > I was thinking whether to post the patch at all as IMO it does not make much > sense (nowadays) for gdb to support IPv6, just Red Hat requires it. > > Still I do not want to invest a lot of time for the autoconf/portability stuff > if it gets dropped down upstream (like by you) afterwards anyway (sometimes > right, no problem with it). It should have been marked more as "RFC" patch. > > It is fine for me to update the patch upon request if it gets merged this way. > Still it is not acceptable for me to rewrite the patch from scratch just for > the upstream without reusability for Red Hat (as I was feeling for the case of > SIGSTOP vs. ptrace(2) due to a different kernel variant in use). > At least I do not think I am expected to do this in RH. > > > I hope I cleared it up; I try to be upstream-cooperative. Thanks! The RFC-ness wasnt clear; I'm much happier now :-) I don't have an opinion on whether GDB should support IPv6 connections; it's not an important feature to me, but I think it would be reasonable to add. Let's see if anyone else has a thought on it. > > Maybe we should add stdin/stdout support to gdbserver and make an > > external utility handle any more fancy networking scenarios. I'm > > thinking of "socat" here. What do you think of that idea? We've done > > stdin/stdout for other stubs in the past and it's quite handy. Or if > > you want to leave inferior stdout alone you can use two specified file > > descriptors. > > I do not know, I used only gdb stub or gdbserver on full GNU/Linux. > Still I feel it is more complicated to compile both stripped-down gdbserver AND > IPv6-enabled socat and connect them together on the target UNIX system than > just to compile there the IPv6-enabled (autoconf-configured) gdbserver. > > Still it looks simple enough to provide the fd interface for gdbserver, if it > is going to be imported upstream. The advantage of providing just an fd interface is that you can leave writing complicated networking code to people who are more dedicated to it, and people who don't need ipv6 on their embedded device with gdbserver won't have to include the code. Gdbserver isn't exactly small - in fact as stubs go it's pretty heavyweight! But I do still try to keep the bloat limited. I'd offer to do this, but don't count on my having time for it any time soon. I still need to go through and review a lot of other submissions to gdb-patches since the last time I had a break from work, including yours. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-09-27 19:06 ` Daniel Jacobowitz @ 2006-09-30 15:28 ` Jan Kratochvil 2006-10-08 19:03 ` Jan Kratochvil 0 siblings, 1 reply; 10+ messages in thread From: Jan Kratochvil @ 2006-09-30 15:28 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 676 bytes --] Hi, sanitized version here. On Wed, 27 Sep 2006 21:06:11 +0200, Daniel Jacobowitz wrote: > On Wed, Sep 27, 2006 at 08:55:47PM +0200, Jan Kratochvil wrote: > > On Wed, 27 Sep 2006 20:20:38 +0200, Daniel Jacobowitz wrote: > > ... > > > focused on the environment you're working in (Red Hat Linux). > > ... > > > I suspect that this would break GDB builds on a number of targets This version detects getaddrinfo(3)/getnameinfo(3)/AF_INET6; tested only by hand, not on a real system missing IPv6. ... > The advantage of providing just an fd interface is that you can leave > writing complicated networking code This patch extends the gdbserver part for IPv6. Regards, Jan [-- Attachment #2: gdb-cvs-IPv6.patch --] [-- Type: text/plain, Size: 32608 bytes --] [ gdb/configure and gdb/gdbserver/configure missing ] gdb: 2006-09-30 Jan Kratochvil <jan.kratochvil@redhat.com> * ser-tcp.c (net_open): Support IPv6, "tcp6:"&co. notation. * configure.ac: Check for IPv6 getaddrinfo, getnameinfo and AF_INET6. * configure, config.in: Regenerate. gdb/gdbserver: 2006-09-30 Jan Kratochvil <jan.kratochvil@redhat.com> * gdbreplay.c (remote_open): Support IPv6, "tcp6:"&co. notation. * remote-utils.c (remote_open): Likewise. * configure.ac: Check for IPv6 getaddrinfo, getnameinfo and AF_INET6. * configure, config.in: Regenerate. gdb/doc: 2006-09-30 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.texinfo (Connecting to a remote target): Support IPv6, "tcp6:"&co. notation. (Using the gdbserver program): Likewise. Index: gdb/config.in =================================================================== --- gdb/config.in 8 Aug 2006 20:32:15 -0000 1.84 +++ gdb/config.in 30 Sep 2006 15:13:04 -0000 @@ -67,6 +67,10 @@ /* Define to 1 if you have the <curses.h> header file. */ #undef HAVE_CURSES_H +/* Define to 1 if you have the declaration of `AF_INET6', and to 0 if you + don't. */ +#undef HAVE_DECL_AF_INET6 + /* Define to 1 if you have the declaration of `free', and to 0 if you don't. */ #undef HAVE_DECL_FREE @@ -113,9 +117,15 @@ /* Define if <sys/procfs.h> has fpregset_t. */ #undef HAVE_FPREGSET_T +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + /* Define to 1 if you have the `getgid' function. */ #undef HAVE_GETGID +/* Define to 1 if you have the `getnameinfo' function. */ +#undef HAVE_GETNAMEINFO + /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE Index: gdb/configure.ac =================================================================== --- gdb/configure.ac 8 Aug 2006 20:26:23 -0000 1.34 +++ gdb/configure.ac 30 Sep 2006 15:13:08 -0000 @@ -446,6 +446,12 @@ AC_CHECK_FUNCS(socketpair) AC_CHECK_FUNCS(syscall) AC_CHECK_FUNCS(ttrace) AC_CHECK_FUNCS(wborder) +AC_CHECK_FUNCS(getaddrinfo) +AC_CHECK_FUNCS(getnameinfo) +AC_CHECK_DECLS(AF_INET6, [], [], +[#include <sys/types.h> +#include <sys/socket.h> +]) # Check the return and argument types of ptrace. No canned test for # this, so roll our own. Index: gdb/ser-tcp.c =================================================================== --- gdb/ser-tcp.c 10 Feb 2006 22:01:43 -0000 1.26 +++ gdb/ser-tcp.c 30 Sep 2006 15:13:08 -0000 @@ -68,67 +68,142 @@ void _initialize_ser_tcp (void); int net_open (struct serial *scb, const char *name) { - char *port_str, hostname[100]; - int n, port, tmp; - int use_udp; - struct hostent *hostent; - struct sockaddr_in sockaddr; + char *name_base; + char *port_str; + int n, tmp; #ifdef USE_WIN32API u_long ioarg; #else int ioarg; #endif - - use_udp = 0; - if (strncmp (name, "udp:", 4) == 0) + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = { - use_udp = 1; - name = name + 4; + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, +/* We do not support `AF_INET6' without getaddrinfo(3). */ +#if defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, +#endif /* defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 */ + }; + const struct prefix *prefix; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo *addrinfo_base, *addrinfo = NULL; +#else /* !HAVE_GETADDRINFO */ + struct hostent *hostent; + struct sockaddr_in sockaddr; +#endif /* !HAVE_GETADDRINFO */ + /* Error by default. */ + int retval = -1; + + name_base = xstrdup (name); + name = name_base; +#ifdef HAVE_GETADDRINFO + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; +#endif /* HAVE_GETADDRINFO */ + for (prefix = prefixes; prefix < prefixes + ARRAY_SIZE (prefixes); prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); +#ifdef HAVE_GETADDRINFO + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; +#endif /* HAVE_GETADDRINFO */ + break; + } + if (prefix >= prefixes + ARRAY_SIZE (prefixes)) + prefix = NULL; + if ((prefix == NULL || prefix->family != AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) + { + name++; + *port_str++ = 0; + } + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + error (_("net_open: No colon in host name!")); + *port_str++ = 0; + + /* Default hostname for `node == NULL' is localhost + as we did not specify `hints.ai_flags & AI_PASSIVE'. */ + if (name[0] == 0) + name = NULL; + +#ifdef HAVE_GETADDRINFO + n = getaddrinfo (name, port_str, &hints, &addrinfo_base); + if (n != 0) + { + fprintf_unfiltered (gdb_stderr, "%s:%s: cannot resolve name: %s\n", + (name != NULL ? name : "<local>"), + port_str, gai_strerror (n)); + errno = ENOENT; + free (name_base); + return -1; } - else if (strncmp (name, "tcp:", 4) == 0) - name = name + 4; - - port_str = strchr (name, ':'); - - if (!port_str) - error (_("net_open: No colon in host name!")); /* Shouldn't ever happen */ - - tmp = min (port_str - name, (int) sizeof hostname - 1); - strncpy (hostname, name, tmp); /* Don't want colon */ - hostname[tmp] = '\000'; /* Tie off host name */ - port = atoi (port_str + 1); - /* default hostname is localhost */ - if (!hostname[0]) - strcpy (hostname, "localhost"); + /* Still used for `port_str' above. */ + free (name_base); - hostent = gethostbyname (hostname); - if (!hostent) + for (addrinfo = addrinfo_base; addrinfo != NULL; addrinfo = addrinfo->ai_next) + { + scb->fd = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (scb->fd >= 0) + break; + } + if (addrinfo == NULL) { - fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname); + freeaddrinfo (addrinfo_base); + return -1; + } +#else /* !HAVE_GETADDRINFO */ + hostent = gethostbyname ((name != NULL ? name : "localhost")); + if (hostent == NULL) + { + fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", name); errno = ENOENT; + free (name_base); return -1; } - if (use_udp) - scb->fd = socket (PF_INET, SOCK_DGRAM, 0); - else - scb->fd = socket (PF_INET, SOCK_STREAM, 0); + sockaddr.sin_family = PF_INET; + sockaddr.sin_port = htons (atoi (port_str)); + memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + /* Still used for `port_str' above. */ + free (name_base); + + scb->fd = socket (sockaddr.sin_family, + (prefix != NULL ? prefix->socktype : SOCK_STREAM), + 0); if (scb->fd < 0) return -1; - - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, - sizeof (struct in_addr)); +#endif /* !HAVE_GETADDRINFO */ /* set socket nonblocking */ ioarg = 1; ioctl (scb->fd, FIONBIO, &ioarg); /* Use Non-blocking connect. connect() will return 0 if connected already. */ +#ifdef HAVE_GETADDRINFO + n = connect (scb->fd, addrinfo->ai_addr, addrinfo->ai_addrlen); +#else /* !HAVE_GETADDRINFO */ n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); +#endif /* !HAVE_GETADDRINFO */ if (n < 0 #ifdef USE_WIN32API @@ -143,8 +218,7 @@ net_open (struct serial *scb, const char #ifdef USE_WIN32API errno = WSAGetLastError(); #endif - net_close (scb); - return -1; + goto cleanup_scb; } if (n) @@ -165,8 +239,7 @@ net_open (struct serial *scb, const char if (deprecated_ui_loop_hook (0)) { errno = EINTR; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -192,8 +265,7 @@ net_open (struct serial *scb, const char { if (polls > TIMEOUT * POLL_INTERVAL) errno = ETIMEDOUT; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -211,8 +283,7 @@ net_open (struct serial *scb, const char { if (err) errno = err; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -220,7 +291,7 @@ net_open (struct serial *scb, const char ioarg = 0; ioctl (scb->fd, FIONBIO, &ioarg); - if (use_udp == 0) + if (prefix == NULL || prefix->socktype == SOCK_STREAM) { /* Disable Nagle algorithm. Needed in some cases. */ tmp = 1; @@ -234,7 +305,16 @@ net_open (struct serial *scb, const char signal (SIGPIPE, SIG_IGN); #endif - return 0; + retval = 0; + goto cleanup_addrinfo_base; + +cleanup_scb: + net_close (scb); +cleanup_addrinfo_base: +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ + return retval; } void Index: gdb/doc/gdb.texinfo =================================================================== --- gdb/doc/gdb.texinfo 21 Sep 2006 14:01:12 -0000 1.355 +++ gdb/doc/gdb.texinfo 30 Sep 2006 15:13:19 -0000 @@ -12404,8 +12404,10 @@ If you're using a serial line, you may w (@pxref{Remote configuration, set remotebaud}) before the @code{target} command. -@item target remote @code{@var{host}:@var{port}} +@item target remote @code{@var{host}:@var{port}} @itemx target remote @code{tcp:@var{host}:@var{port}} +@itemx target remote @code{tcp4:@var{host}:@var{port}} +@itemx target remote @code{tcp6:@var{host}:@var{port}} @cindex @acronym{TCP} port, @code{target remote} Debug using a @acronym{TCP} connection to @var{port} on @var{host}. The @var{host} may be either a host name or a numeric @acronym{IP} @@ -12414,6 +12416,9 @@ the target machine itself, if it is dire it might be a terminal server which in turn has a serial line to the target. +@code{tcp6:} prefix forces IPv6 network connection while @code{tcp4:} forces +IPv4, both on the reliable stream TCP connection. + For example, to connect to port 2828 on a terminal server named @code{manyfarms}: @@ -12434,10 +12439,15 @@ target remote :1234 Note that the colon is still required here. @item target remote @code{udp:@var{host}:@var{port}} +@itemx target remote @code{udp6:@var{host}:@var{port}} +@itemx target remote @code{udp4:@var{host}:@var{port}} @cindex @acronym{UDP} port, @code{target remote} Debug using @acronym{UDP} packets to @var{port} on @var{host}. For example, to connect to @acronym{UDP} port 2828 on a terminal server named @code{manyfarms}: +@code{udp6:} prefix forces IPv6 network connection while @code{udp4:} forces +IPv4, both on the unreliable datagram UDP connection. + @smallexample target remote udp:manyfarms:2828 @end smallexample @@ -12578,14 +12588,30 @@ The only difference from the previous ex specifying that you are communicating with the host @value{GDBN} via TCP. The @samp{host:2345} argument means that @code{gdbserver} is to expect a TCP connection from machine @samp{host} to local TCP port 2345. -(Currently, the @samp{host} part is ignored.) You can choose any number -you want for the port number as long as it does not conflict with any -TCP ports already in use on the target system (for example, @code{23} is -reserved for @code{telnet}).@footnote{If you choose a port number that -conflicts with another service, @code{gdbserver} prints an error message +(The @samp{host} part is usually omitted as it defaults to listen from any +host. You may use a local address as expected by the @code{bind} syscall.) +You can choose any number you want for the port number as long as it does not +conflict with any TCP ports already in use on the target system (for example, +@code{23} is reserved for @code{telnet}).@footnote{If you choose a port number +that conflicts with another service, @code{gdbserver} prints an error message and exits.} You must use the same port number with the host @value{GDBN} @code{target remote} command. +@item gdbserver @code{tcp:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{tcp6:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{tcp4:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{udp:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{udp6:@var{host}:@var{port}} emacs foo.txt +@itemx gdbserver @code{udp4:@var{host}:@var{port}} emacs foo.txt + +The @code{::} part can be also replaced by the optional @var{host} part as +in the sample case of @code{tcp:@var{host}:@var{port}}. +These all alternative syntaxes force either the reliable stream TCP protocol or +the unreliable datagram UDP protocol appropriately. You may also force the use +of IPv6 or IPv4 network connections; @code{tcp:} and @code{udp:} select the +network version type according to the provided @var{host}. +The connection type defaults to the @code{tcp:} prefix behavior. + On some targets, @code{gdbserver} can also attach to running programs. This is accomplished via the @code{--attach} argument. The syntax is: Index: gdb/gdbserver/config.in =================================================================== --- gdb/gdbserver/config.in 23 Jul 2006 03:52:15 -0000 1.14 +++ gdb/gdbserver/config.in 30 Sep 2006 15:13:19 -0000 @@ -3,6 +3,10 @@ /* Define to 1 if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H +/* Define to 1 if you have the declaration of `AF_INET6', and to 0 if you + don't. */ +#undef HAVE_DECL_AF_INET6 + /* Define to 1 if you have the declaration of `strerror', and to 0 if you don't. */ #undef HAVE_DECL_STRERROR @@ -10,6 +14,12 @@ /* Define if <sys/procfs.h> has elf_fpregset_t. */ #undef HAVE_ELF_FPREGSET_T +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `getnameinfo' function. */ +#undef HAVE_GETNAMEINFO + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H Index: gdb/gdbserver/configure.ac =================================================================== --- gdb/gdbserver/configure.ac 23 Jul 2006 03:52:15 -0000 1.10 +++ gdb/gdbserver/configure.ac 30 Sep 2006 15:13:21 -0000 @@ -49,6 +49,12 @@ AC_CHECK_TYPES(socklen_t, [], [], #include <sys/socket.h> ]) . ${srcdir}/configure.srv +AC_CHECK_FUNCS(getaddrinfo) +AC_CHECK_FUNCS(getnameinfo) +AC_CHECK_DECLS(AF_INET6, [], [], +[#include <sys/types.h> +#include <sys/socket.h> +]) if test "${srv_mingw}" = "yes"; then LIBS="$LIBS -lwsock32" Index: gdb/gdbserver/gdbreplay.c =================================================================== --- gdb/gdbserver/gdbreplay.c 23 Jul 2006 03:52:15 -0000 1.12 +++ gdb/gdbserver/gdbreplay.c 30 Sep 2006 15:13:21 -0000 @@ -115,6 +115,8 @@ remote_close (void) static void remote_open (char *name) { + char *name_orig = name; + if (!strchr (name, ':')) { fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name); @@ -127,14 +129,81 @@ remote_open (char *name) static int winsock_initialized; #endif char *port_str; - int port; - struct sockaddr_in sockaddr; socklen_t tmp; - int tmp_desc; - - port_str = strchr (name, ':'); + int tmp_desc = -1; + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = + { + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, +/* We do not support `AF_INET6' without getaddrinfo(3). */ +#if defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, +#endif /* defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 */ + }; + const struct prefix *prefix; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo *addrinfo_base, *addrinfo = NULL; + int err; +#else /* !HAVE_GETADDRINFO */ + struct sockaddr_in sockaddr; +#endif /* !HAVE_GETADDRINFO */ +#ifdef HAVE_GETNAMEINFO + char back_host[64], back_port[16]; +#endif /* HAVE_GETNAMEINFO */ + char *name_base; + + name_base = strdup (name); + name = name_base; +#ifdef HAVE_GETADDRINFO + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; +#endif /* HAVE_GETADDRINFO */ + for (prefix = prefixes; + prefix < prefixes + sizeof (prefixes) / sizeof (*prefixes); + prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); +#ifdef HAVE_GETADDRINFO + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; +#endif /* HAVE_GETADDRINFO */ + break; + } + if (prefix >= prefixes + sizeof (prefixes) / sizeof (*prefixes)) + prefix = NULL; + if ((prefix == NULL || prefix->family != AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) + { + name++; + *port_str++ = 0; + } + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + { + fprintf (stderr, "net_open: No colon in host name!\n"); + fflush (stderr); + exit (1); + } + *port_str++ = 0; - port = atoi (port_str + 1); + /* Default hostname for `node == NULL' is `INADDR_ANY'/`in6addr_any'. + as we did specify `hints.ai_flags & AI_PASSIVE'. */ + if (name[0] == 0) + name = NULL; #ifdef USE_WIN32API if (!winsock_initialized) @@ -146,55 +215,162 @@ remote_open (char *name) } #endif - tmp_desc = socket (PF_INET, SOCK_STREAM, 0); +#ifdef HAVE_GETADDRINFO + err = getaddrinfo (name, port_str, &hints, &addrinfo_base); + if (err != 0) + { + /* `name_base' is used here for `port_str'. */ + fprintf (stderr, "%s:%s: cannot resolve name: %s\n", + name, port_str, gai_strerror (err)); + fflush (stderr); + exit (1); + } + + for (addrinfo = addrinfo_base; + addrinfo != NULL; + addrinfo = addrinfo->ai_next) + { + tmp_desc = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (tmp_desc >= 0) + break; + } + if (addrinfo == NULL) + { + freeaddrinfo (addrinfo_base); + perror_with_name ("Can't open socket"); + } +#else /* !HAVE_GETADDRINFO */ + sockaddr.sin_family = PF_INET; + sockaddr.sin_port = htons (atoi (port_str)); + + if (name == NULL) + sockaddr.sin_addr.s_addr = INADDR_ANY; + else + { + struct hostent *hostent; + + hostent = gethostbyname (name); + if (hostent == NULL) + { + fprintf (stderr, "%s: unknown host\n", name); + free (name_base); + perror_with_name ("gethostbyname(3) resolving"); + } + + memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + } + + /* We assume matching `AF_*' and `PF_*'. */ + tmp_desc = socket (sockaddr.sin_family, + (prefix != NULL ? prefix->socktype : SOCK_STREAM), + 0); if (tmp_desc < 0) - perror_with_name ("Can't open socket"); + { + free (name_base); + perror_with_name ("Can't open socket"); + } +#endif /* !HAVE_GETADDRINFO */ /* Allow rapid reuse of this port. */ tmp = 1; setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp)); - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - sockaddr.sin_addr.s_addr = INADDR_ANY; - +#ifdef HAVE_GETADDRINFO + if (bind (tmp_desc, addrinfo->ai_addr, addrinfo->ai_addrlen) + || ((prefix == NULL || prefix->socktype != SOCK_DGRAM) + && listen (tmp_desc, 1))) +#else /* !HAVE_GETADDRINFO */ if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) - || listen (tmp_desc, 1)) - perror_with_name ("Can't bind address"); - - tmp = sizeof (sockaddr); - remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp); - if (remote_desc == -1) - perror_with_name ("Accept failed"); - - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); + || ((prefix == NULL || prefix->socktype != SOCK_DGRAM) + && listen (tmp_desc, 1))) +#endif /* !HAVE_GETADDRINFO */ + { +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ + free (name_base); + perror_with_name ("Can't bind address"); + } + +#ifdef HAVE_GETNAMEINFO + if (0 == getnameinfo (addrinfo->ai_addr, addrinfo->ai_addrlen, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Listening on port %s (on host %s)\n", + back_port, back_host); + else +#endif /* !HAVE_GETNAMEINFO */ + fprintf (stderr, "Listening on port %s (on host %s)\n", + port_str, (name != NULL ? name : "<local>")); + fflush (stderr); - /* Tell TCP not to delay small packets. This greatly speeds up - interactive response. */ - tmp = 1; - setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, - (char *) &tmp, sizeof (tmp)); + /* Used for `port_str' above. */ + free (name_base); - close (tmp_desc); /* No longer need this */ + if (prefix != NULL && prefix->socktype == SOCK_DGRAM) + remote_desc = tmp_desc; + else + { + struct sockaddr_storage sockaddr; + socklen_t sockaddr_len = sizeof (sockaddr); + remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &sockaddr_len); + if (remote_desc == -1) + { +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ + perror_with_name ("Accept failed"); + } + + /* Enable TCP keep alive process. */ + tmp = 1; + setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); + + /* Tell TCP not to delay small packets. This greatly speeds up + interactive response. */ + if (prefix == NULL || prefix->socktype == SOCK_STREAM) + { + tmp = 1; + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, + (char *) &tmp, sizeof (tmp)); + } +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ #ifndef USE_WIN32API - close (tmp_desc); /* No longer need this */ + close (tmp_desc); /* No longer need this */ - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbreplay simply - exits when the remote side dies. */ + signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply + exits when the remote side dies. */ #else - closesocket (tmp_desc); /* No longer need this */ + closesocket (tmp_desc); /* No longer need this */ #endif + +#ifdef HAVE_GETNAMEINFO + /* Convert IP address to string. */ + if (0 == getnameinfo ((struct sockaddr *) &sockaddr, sockaddr_len, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Remote debugging from host %s port %s\n", + back_host, back_port); + else +#endif /* !HAVE_GETNAMEINFO */ + fprintf (stderr, "Remote debugging started\n"); + } + fflush (stderr); } -#if defined(F_SETFL) && defined (FASYNC) +#if defined (F_SETFL) && defined (FASYNC) fcntl (remote_desc, F_SETFL, FASYNC); #endif - fprintf (stderr, "Replay logfile using %s\n", name); + fprintf (stderr, "Replay logfile using %s\n", name_orig); fflush (stderr); } Index: gdb/gdbserver/remote-utils.c =================================================================== --- gdb/gdbserver/remote-utils.c 21 Sep 2006 16:09:54 -0000 1.32 +++ gdb/gdbserver/remote-utils.c 30 Sep 2006 15:13:21 -0000 @@ -157,14 +157,77 @@ remote_open (char *name) static int winsock_initialized; #endif char *port_str; - int port; - struct sockaddr_in sockaddr; socklen_t tmp; - int tmp_desc; - - port_str = strchr (name, ':'); - - port = atoi (port_str + 1); + int tmp_desc = -1; + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = + { + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, +/* We do not support `AF_INET6' without getaddrinfo(3). */ +#if defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, +#endif /* defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 */ + }; + const struct prefix *prefix; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo *addrinfo_base, *addrinfo = NULL; + int err; +#else /* !HAVE_GETADDRINFO */ + struct sockaddr_in sockaddr; +#endif /* !HAVE_GETADDRINFO */ +#ifdef HAVE_GETNAMEINFO + char back_host[64], back_port[16]; +#endif /* HAVE_GETNAMEINFO */ + char *name_base; + + name_base = strdup (name); + name = name_base; +#ifdef HAVE_GETADDRINFO + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; +#endif /* HAVE_GETADDRINFO */ + for (prefix = prefixes; + prefix < prefixes + sizeof (prefixes) / sizeof (*prefixes); + prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); +#ifdef HAVE_GETADDRINFO + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; +#endif /* HAVE_GETADDRINFO */ + break; + } + if (prefix >= prefixes + sizeof (prefixes) / sizeof (*prefixes)) + prefix = NULL; + if ((prefix == NULL || prefix->family != AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) + { + name++; + *port_str++ = 0; + } + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + error ("net_open: No colon in host name!"); + *port_str++ = 0; + + /* Default hostname for `node == NULL' is `INADDR_ANY'/`in6addr_any'. + as we did specify `hints.ai_flags & AI_PASSIVE'. */ + if (name[0] == 0) + name = NULL; #ifdef USE_WIN32API if (!winsock_initialized) @@ -176,54 +239,155 @@ remote_open (char *name) } #endif - tmp_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); +#ifdef HAVE_GETADDRINFO + err = getaddrinfo (name, port_str, &hints, &addrinfo_base); + if (err != 0) + { + /* `name_base' is used here for `port_str'. */ + error ("%s:%s: cannot resolve name: %s\n", + name, port_str, gai_strerror (err)); + } + + for (addrinfo = addrinfo_base; + addrinfo != NULL; + addrinfo = addrinfo->ai_next) + { + tmp_desc = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (tmp_desc >= 0) + break; + } + if (addrinfo == NULL) + { + freeaddrinfo (addrinfo_base); + free (name_base); + perror_with_name ("Can't open socket"); + } +#else /* !HAVE_GETADDRINFO */ + sockaddr.sin_family = PF_INET; + sockaddr.sin_port = htons (atoi (port_str)); + + if (name == NULL) + sockaddr.sin_addr.s_addr = INADDR_ANY; + else + { + struct hostent *hostent; + + hostent = gethostbyname (name); + if (hostent == NULL) + { + fprintf (stderr, "%s: unknown host\n", name); + fflush (stderr); + free (name_base); + perror_with_name ("gethostbyname(3) resolving"); + } + + memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + } + + /* We assume matching `AF_*' and `PF_*'. */ + tmp_desc = socket (sockaddr.sin_family, + (prefix != NULL ? prefix->socktype : SOCK_STREAM), + 0); if (tmp_desc < 0) - perror_with_name ("Can't open socket"); + { + free (name_base); + perror_with_name ("Can't open socket"); + } +#endif /* !HAVE_GETADDRINFO */ /* Allow rapid reuse of this port. */ tmp = 1; setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp)); - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - sockaddr.sin_addr.s_addr = INADDR_ANY; - +#ifdef HAVE_GETADDRINFO + if (bind (tmp_desc, addrinfo->ai_addr, addrinfo->ai_addrlen) + || ((prefix == NULL || prefix->socktype != SOCK_DGRAM) + && listen (tmp_desc, 1))) +#else /* !HAVE_GETADDRINFO */ if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) - || listen (tmp_desc, 1)) - perror_with_name ("Can't bind address"); + || ((prefix == NULL || prefix->socktype != SOCK_DGRAM) + && listen (tmp_desc, 1))) +#endif /* !HAVE_GETADDRINFO */ + { +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ + free (name_base); + perror_with_name ("Can't bind address"); + } - fprintf (stderr, "Listening on port %d\n", port); +#ifdef HAVE_GETNAMEINFO + if (0 == getnameinfo (addrinfo->ai_addr, addrinfo->ai_addrlen, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Listening on port %s (on host %s)\n", + back_port, back_host); + else +#endif /* !HAVE_GETNAMEINFO */ + fprintf (stderr, "Listening on port %s (on host %s)\n", + port_str, (name != NULL ? name : "<local>")); fflush (stderr); - tmp = sizeof (sockaddr); - remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp); - if (remote_desc == -1) - perror_with_name ("Accept failed"); + /* Used for `port_str' above. */ + free (name_base); - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); - - /* Tell TCP not to delay small packets. This greatly speeds up - interactive response. */ - tmp = 1; - setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, - (char *) &tmp, sizeof (tmp)); + if (prefix != NULL && prefix->socktype == SOCK_DGRAM) + remote_desc = tmp_desc; + else + { + struct sockaddr_storage sockaddr; + socklen_t sockaddr_len = sizeof (sockaddr); + remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &sockaddr_len); + if (remote_desc == -1) + { +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ + perror_with_name ("Accept failed"); + } + /* Enable TCP keep alive process. */ + tmp = 1; + setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); + + /* Tell TCP not to delay small packets. This greatly speeds up + interactive response. */ + if (prefix == NULL || prefix->socktype == SOCK_STREAM) + { + tmp = 1; + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, + (char *) &tmp, sizeof (tmp)); + } +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ #ifndef USE_WIN32API - close (tmp_desc); /* No longer need this */ + close (tmp_desc); /* No longer need this */ - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply + signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply exits when the remote side dies. */ #else - closesocket (tmp_desc); /* No longer need this */ + closesocket (tmp_desc); /* No longer need this */ #endif - /* Convert IP address to string. */ - fprintf (stderr, "Remote debugging from host %s\n", - inet_ntoa (sockaddr.sin_addr)); +#ifdef HAVE_GETNAMEINFO + /* Convert IP address to string. */ + if (0 == getnameinfo ((struct sockaddr *) &sockaddr, sockaddr_len, + back_host, sizeof (back_host), + back_port, sizeof (back_port), + NI_NUMERICHOST | NI_NUMERICSERV)) + fprintf (stderr, "Remote debugging from host %s port %s\n", + back_host, back_port); + else +#endif /* !HAVE_GETNAMEINFO */ + fprintf (stderr, "Remote debugging started\n"); + } + fflush (stderr); } #if defined(F_SETFL) && defined (FASYNC) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-09-30 15:28 ` Jan Kratochvil @ 2006-10-08 19:03 ` Jan Kratochvil 2006-10-09 4:33 ` Eli Zaretskii 0 siblings, 1 reply; 10+ messages in thread From: Jan Kratochvil @ 2006-10-08 19:03 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1402 bytes --] Hi, patch for the IPv6 support according to the Daniel Jacobowitz's recommendation: http://sourceware.org/ml/gdb-patches/2006-09/msg00194.html I am primarily interested if the mainline is going to use this "tcp6:" syntax. gdb(1) client: As before - "tcp6:" prefix support, "tcp:" extended by IPv6. gdbserver(1)/gdbreplay(1): Syntax "fd<in><out>" - like: socat EXEC:'gdbserver fd34 emacs foo.txt',fdin=3,fdout=4 'TCP-LISTEN:2345' The first patch "gdb-cvs-IPv6-fds-plus.patch" adds both features listed above. The second patch "gdb-cvs-IPv6-hostport-minus.patch" removes the obsoleted "host:port" syntax from gdbserver(1)/gdbreplay(1). Regards, Jan On Sat, 30 Sep 2006 17:27:57 +0200, Jan Kratochvil wrote: > On Wed, 27 Sep 2006 21:06:11 +0200, Daniel Jacobowitz wrote: > > On Wed, Sep 27, 2006 at 08:55:47PM +0200, Jan Kratochvil wrote: > > > On Wed, 27 Sep 2006 20:20:38 +0200, Daniel Jacobowitz wrote: > > > ... > > > > focused on the environment you're working in (Red Hat Linux). > > > ... > > > > I suspect that this would break GDB builds on a number of targets > > This version detects getaddrinfo(3)/getnameinfo(3)/AF_INET6; > tested only by hand, not on a real system missing IPv6. > > ... > > The advantage of providing just an fd interface is that you can leave > > writing complicated networking code > > This patch extends the gdbserver part for IPv6. > > > Regards, > Jan [-- Attachment #2: gdb-cvs-IPv6-fds-plus.patch --] [-- Type: text/plain, Size: 31706 bytes --] gdb: 2006-10-08 Jan Kratochvil <jan.kratochvil@redhat.com> * ser-tcp.c (net_open): Support IPv6 "tcp6:"&co. notation. * configure.ac: Check for IPv6 getaddrinfo, getnameinfo and AF_INET6. * configure, config.in: Regenerate. gdb/gdbserver: 2006-10-08 Jan Kratochvil <jan.kratochvil@redhat.com> * gdbreplay.c (remote_open, main): Support "fd<in><out>" fds argument. (remote_desc_in, remote_desc_out, remote_close, remote_open, expect, play): Replace `remote_desc' by `remote_desc_in' and `remote_desc_out'. * remote-utils.c (remote_desc_in, remote_desc_out, remote_close, remote_open, putpkt_binary, input_interrupt, readchar, getpkt): Replace `remote_desc' by `remote_desc_in' and `remote_desc_out'. * server.c (gdbserver_usage): Descripe "fd<in><out>" fds argument. gdb/doc: 2006-10-08 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.texinfo (Connecting to a remote target): Describe IPv6 "tcp6:"&co. notation. (Using the gdbserver program): Describe "fd<in><out>" comm notation. diff -u -p -r1.84 config.in --- gdb/config.in 8 Aug 2006 20:32:15 -0000 1.84 +++ gdb/config.in 8 Oct 2006 15:37:00 -0000 @@ -67,6 +67,10 @@ /* Define to 1 if you have the <curses.h> header file. */ #undef HAVE_CURSES_H +/* Define to 1 if you have the declaration of `AF_INET6', and to 0 if you + don't. */ +#undef HAVE_DECL_AF_INET6 + /* Define to 1 if you have the declaration of `free', and to 0 if you don't. */ #undef HAVE_DECL_FREE @@ -113,9 +117,15 @@ /* Define if <sys/procfs.h> has fpregset_t. */ #undef HAVE_FPREGSET_T +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + /* Define to 1 if you have the `getgid' function. */ #undef HAVE_GETGID +/* Define to 1 if you have the `getnameinfo' function. */ +#undef HAVE_GETNAMEINFO + /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE diff -u -p -r1.213 configure --- gdb/configure 8 Aug 2006 20:32:15 -0000 1.213 +++ gdb/configure 8 Oct 2006 15:37:03 -0000 @@ -17453,6 +17453,285 @@ fi done +for ac_func in getaddrinfo +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +for ac_func in getnameinfo +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +echo "$as_me:$LINENO: checking whether AF_INET6 is declared" >&5 +echo $ECHO_N "checking whether AF_INET6 is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl_AF_INET6+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/socket.h> + + +int +main () +{ +#ifndef AF_INET6 + char *p = (char *) AF_INET6; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_AF_INET6=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl_AF_INET6=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl_AF_INET6" >&5 +echo "${ECHO_T}$ac_cv_have_decl_AF_INET6" >&6 +if test $ac_cv_have_decl_AF_INET6 = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AF_INET6 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AF_INET6 0 +_ACEOF + + +fi + + + # Check the return and argument types of ptrace. No canned test for # this, so roll our own. gdb_ptrace_headers=' @@ -22335,7 +22614,7 @@ ac_x_header_dirs=' /usr/openwin/share/include' if test "$ac_x_includes" = no; then - # Guess where to find include files, by looking for Intrinsic.h. + # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -22343,7 +22622,7 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <X11/Intrinsic.h> +#include <X11/Xlib.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -22370,7 +22649,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do - if test -r "$ac_dir/X11/Intrinsic.h"; then + if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi @@ -22384,18 +22663,18 @@ if test "$ac_x_libraries" = no; then # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS - LIBS="-lXt $LIBS" + LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <X11/Intrinsic.h> +#include <X11/Xlib.h> int main () { -XtMalloc (0) +XrmInitialize () ; return 0; } diff -u -p -r1.34 configure.ac --- gdb/configure.ac 8 Aug 2006 20:26:23 -0000 1.34 +++ gdb/configure.ac 8 Oct 2006 15:37:03 -0000 @@ -446,6 +446,12 @@ AC_CHECK_FUNCS(socketpair) AC_CHECK_FUNCS(syscall) AC_CHECK_FUNCS(ttrace) AC_CHECK_FUNCS(wborder) +AC_CHECK_FUNCS(getaddrinfo) +AC_CHECK_FUNCS(getnameinfo) +AC_CHECK_DECLS(AF_INET6, [], [], +[#include <sys/types.h> +#include <sys/socket.h> +]) # Check the return and argument types of ptrace. No canned test for # this, so roll our own. diff -u -p -r1.26 ser-tcp.c --- gdb/ser-tcp.c 10 Feb 2006 22:01:43 -0000 1.26 +++ gdb/ser-tcp.c 8 Oct 2006 15:37:04 -0000 @@ -68,67 +68,142 @@ void _initialize_ser_tcp (void); int net_open (struct serial *scb, const char *name) { - char *port_str, hostname[100]; - int n, port, tmp; - int use_udp; - struct hostent *hostent; - struct sockaddr_in sockaddr; + char *name_base; + char *port_str; + int n, tmp; #ifdef USE_WIN32API u_long ioarg; #else int ioarg; #endif - - use_udp = 0; - if (strncmp (name, "udp:", 4) == 0) + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = { - use_udp = 1; - name = name + 4; + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, +/* We do not support `AF_INET6' without getaddrinfo(3). */ +#if defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, +#endif /* defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 */ + }; + const struct prefix *prefix; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo *addrinfo_base, *addrinfo = NULL; +#else /* !HAVE_GETADDRINFO */ + struct hostent *hostent; + struct sockaddr_in sockaddr; +#endif /* !HAVE_GETADDRINFO */ + /* Error by default. */ + int retval = -1; + + name_base = xstrdup (name); + name = name_base; +#ifdef HAVE_GETADDRINFO + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; +#endif /* HAVE_GETADDRINFO */ + for (prefix = prefixes; prefix < prefixes + ARRAY_SIZE (prefixes); prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); +#ifdef HAVE_GETADDRINFO + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; +#endif /* HAVE_GETADDRINFO */ + break; + } + if (prefix >= prefixes + ARRAY_SIZE (prefixes)) + prefix = NULL; + if ((prefix == NULL || prefix->family != AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) + { + name++; + *port_str++ = 0; + } + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + error (_("net_open: No colon in host name!")); + *port_str++ = 0; + + /* Default hostname for `node == NULL' is localhost + as we did not specify `hints.ai_flags & AI_PASSIVE'. */ + if (name[0] == 0) + name = NULL; + +#ifdef HAVE_GETADDRINFO + n = getaddrinfo (name, port_str, &hints, &addrinfo_base); + if (n != 0) + { + fprintf_unfiltered (gdb_stderr, "%s:%s: cannot resolve name: %s\n", + (name != NULL ? name : "<local>"), + port_str, gai_strerror (n)); + errno = ENOENT; + free (name_base); + return -1; } - else if (strncmp (name, "tcp:", 4) == 0) - name = name + 4; - - port_str = strchr (name, ':'); - - if (!port_str) - error (_("net_open: No colon in host name!")); /* Shouldn't ever happen */ - - tmp = min (port_str - name, (int) sizeof hostname - 1); - strncpy (hostname, name, tmp); /* Don't want colon */ - hostname[tmp] = '\000'; /* Tie off host name */ - port = atoi (port_str + 1); - /* default hostname is localhost */ - if (!hostname[0]) - strcpy (hostname, "localhost"); + /* Still used for `port_str' above. */ + free (name_base); - hostent = gethostbyname (hostname); - if (!hostent) + for (addrinfo = addrinfo_base; addrinfo != NULL; addrinfo = addrinfo->ai_next) + { + scb->fd = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (scb->fd >= 0) + break; + } + if (addrinfo == NULL) { - fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname); + freeaddrinfo (addrinfo_base); + return -1; + } +#else /* !HAVE_GETADDRINFO */ + hostent = gethostbyname ((name != NULL ? name : "localhost")); + if (hostent == NULL) + { + fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", name); errno = ENOENT; + free (name_base); return -1; } - if (use_udp) - scb->fd = socket (PF_INET, SOCK_DGRAM, 0); - else - scb->fd = socket (PF_INET, SOCK_STREAM, 0); + sockaddr.sin_family = PF_INET; + sockaddr.sin_port = htons (atoi (port_str)); + memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + /* Still used for `port_str' above. */ + free (name_base); + + scb->fd = socket (sockaddr.sin_family, + (prefix != NULL ? prefix->socktype : SOCK_STREAM), + 0); if (scb->fd < 0) return -1; - - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, - sizeof (struct in_addr)); +#endif /* !HAVE_GETADDRINFO */ /* set socket nonblocking */ ioarg = 1; ioctl (scb->fd, FIONBIO, &ioarg); /* Use Non-blocking connect. connect() will return 0 if connected already. */ +#ifdef HAVE_GETADDRINFO + n = connect (scb->fd, addrinfo->ai_addr, addrinfo->ai_addrlen); +#else /* !HAVE_GETADDRINFO */ n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); +#endif /* !HAVE_GETADDRINFO */ if (n < 0 #ifdef USE_WIN32API @@ -143,8 +218,7 @@ net_open (struct serial *scb, const char #ifdef USE_WIN32API errno = WSAGetLastError(); #endif - net_close (scb); - return -1; + goto cleanup_scb; } if (n) @@ -165,8 +239,7 @@ net_open (struct serial *scb, const char if (deprecated_ui_loop_hook (0)) { errno = EINTR; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -192,8 +265,7 @@ net_open (struct serial *scb, const char { if (polls > TIMEOUT * POLL_INTERVAL) errno = ETIMEDOUT; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -211,8 +283,7 @@ net_open (struct serial *scb, const char { if (err) errno = err; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -220,7 +291,7 @@ net_open (struct serial *scb, const char ioarg = 0; ioctl (scb->fd, FIONBIO, &ioarg); - if (use_udp == 0) + if (prefix == NULL || prefix->socktype == SOCK_STREAM) { /* Disable Nagle algorithm. Needed in some cases. */ tmp = 1; @@ -234,7 +305,16 @@ net_open (struct serial *scb, const char signal (SIGPIPE, SIG_IGN); #endif - return 0; + retval = 0; + goto cleanup_addrinfo_base; + +cleanup_scb: + net_close (scb); +cleanup_addrinfo_base: +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ + return retval; } void diff -u -p -r1.355 gdb.texinfo --- gdb/doc/gdb.texinfo 21 Sep 2006 14:01:12 -0000 1.355 +++ gdb/doc/gdb.texinfo 8 Oct 2006 15:37:13 -0000 @@ -12404,8 +12404,10 @@ If you're using a serial line, you may w (@pxref{Remote configuration, set remotebaud}) before the @code{target} command. -@item target remote @code{@var{host}:@var{port}} +@item target remote @code{@var{host}:@var{port}} @itemx target remote @code{tcp:@var{host}:@var{port}} +@itemx target remote @code{tcp4:@var{host}:@var{port}} +@itemx target remote @code{tcp6:@var{host}:@var{port}} @cindex @acronym{TCP} port, @code{target remote} Debug using a @acronym{TCP} connection to @var{port} on @var{host}. The @var{host} may be either a host name or a numeric @acronym{IP} @@ -12414,6 +12416,9 @@ the target machine itself, if it is dire it might be a terminal server which in turn has a serial line to the target. +@code{tcp6:} prefix forces IPv6 network connection while @code{tcp4:} forces +IPv4, both on the reliable stream TCP connection. + For example, to connect to port 2828 on a terminal server named @code{manyfarms}: @@ -12434,10 +12439,15 @@ target remote :1234 Note that the colon is still required here. @item target remote @code{udp:@var{host}:@var{port}} +@itemx target remote @code{udp6:@var{host}:@var{port}} +@itemx target remote @code{udp4:@var{host}:@var{port}} @cindex @acronym{UDP} port, @code{target remote} Debug using @acronym{UDP} packets to @var{port} on @var{host}. For example, to connect to @acronym{UDP} port 2828 on a terminal server named @code{manyfarms}: +@code{udp6:} prefix forces IPv6 network connection while @code{udp4:} forces +IPv4, both on the unreliable datagram UDP connection. + @smallexample target remote udp:manyfarms:2828 @end smallexample @@ -12556,9 +12566,9 @@ syntax is: target> gdbserver @var{comm} @var{program} [ @var{args} @dots{} ] @end smallexample -@var{comm} is either a device name (to use a serial line) or a TCP -hostname and portnumber. For example, to debug Emacs with the argument -@samp{foo.txt} and communicate with @value{GDBN} over the serial port +@var{comm} is either a device name (to use a serial line) or file descriptions +numbers or a TCP hostname and portnumber. For example, to debug Emacs with the +argument @samp{foo.txt} and communicate with @value{GDBN} over the serial port @file{/dev/com1}: @smallexample @@ -12571,20 +12581,34 @@ with it. To use a TCP connection instead of a serial line: @smallexample -target> gdbserver host:2345 emacs foo.txt +target> socat EXEC:'gdbserver fd34 emacs foo.txt',fdin=3,fdout=4 'TCP-LISTEN:2345' @end smallexample -The only difference from the previous example is the first argument, -specifying that you are communicating with the host @value{GDBN} via -TCP. The @samp{host:2345} argument means that @code{gdbserver} is to -expect a TCP connection from machine @samp{host} to local TCP port 2345. -(Currently, the @samp{host} part is ignored.) You can choose any number -you want for the port number as long as it does not conflict with any -TCP ports already in use on the target system (for example, @code{23} is -reserved for @code{telnet}).@footnote{If you choose a port number that -conflicts with another service, @code{gdbserver} prints an error message -and exits.} You must use the same port number with the host @value{GDBN} -@code{target remote} command. +This example still debugs the same program just in this case it is specifying +that you are communicating with the host @value{GDBN} via TCP. +The @code{gdbserver} specific part @code{fd34} directs @code{gdbserver} to use +already preopened file descriptor 3 for @value{GDBN} remote serial protocol +input and file descriptor 4 for the protocol output. As the format is +@code{fd<character><character>} you cannot specify file descriptors numbers +above 9. Do not use the file descriptors 0, 1 or 2 as the @value{GDBN} +protocol communication could get corrupted by the inferior program's stdio. + +Please check external @code{socat} program documentation for other available +network options (such as using @code{TCP6-LISTEN} for IPv6 networks). + +You can choose any port number you want (@code{2345} here) as long as it does +not conflict with any TCP ports already in use on the target system (for +example, @code{23} is reserved for @code{telnet}).@footnote{If you choose +a port number that conflicts with another service, @code{socat} prints an error +message and exits.} You must use the same port number with the host +@value{GDBN} @code{target remote} command. + +On IPv4 networks you may also run @code{gdbserver} directly, without the +@code{socat} helper there (equivalent command to the example above): + +@smallexample +target> gdbserver :2345 emacs foo.txt +@end smallexample On some targets, @code{gdbserver} can also attach to running programs. This is accomplished via the @code{--attach} argument. The syntax is: diff -u -p -r1.12 gdbreplay.c --- gdb/gdbserver/gdbreplay.c 23 Jul 2006 03:52:15 -0000 1.12 +++ gdb/gdbserver/gdbreplay.c 8 Oct 2006 15:37:13 -0000 @@ -61,7 +61,7 @@ typedef int socklen_t; /* Sort of a hack... */ #define EOL (EOF - 1) -static int remote_desc; +static int remote_desc_in, remote_desc_out; /* Print the system error message for errno, and also mention STRING as the file name for which the error was encountered. @@ -103,9 +103,13 @@ static void remote_close (void) { #ifdef USE_WIN32API - closesocket (remote_desc); + closesocket (remote_desc_in); + if (remote_desc_in != remote_desc_out) + closesocket (remote_desc_out); #else - close (remote_desc); + close (remote_desc_in); + if (remote_desc_in != remote_desc_out) + close (remote_desc_out); #endif } @@ -115,14 +119,24 @@ remote_close (void) static void remote_open (char *name) { - if (!strchr (name, ':')) + /* "fd01" for STDIO, "fd23" for socat(1) "fdin=2,fdout=3". */ + if (name[0] == 'f' && name[1] == 'd' + && isdigit (name[2]) && isdigit (name[3]) + && name[4] == 0) { - fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name); + remote_desc_in = name[2] - '0'; + remote_desc_out = name[3] - '0'; + } + else if (!strchr (name, ':')) + { + fprintf (stderr, "%s: Must specify tcp connection as host:addr" + " or use fd<in><out>\n", name); fflush (stderr); exit (1); } else { + int remote_desc; #ifdef USE_WIN32API static int winsock_initialized; #endif @@ -188,10 +202,13 @@ remote_open (char *name) #else closesocket (tmp_desc); /* No longer need this */ #endif + remote_desc_in = remote_desc_out = remote_desc; } #if defined(F_SETFL) && defined (FASYNC) - fcntl (remote_desc, F_SETFL, FASYNC); + fcntl (remote_desc_in, F_SETFL, FASYNC); + if (remote_desc_in != remote_desc_out) + fcntl (remote_desc_out, F_SETFL, FASYNC); #endif fprintf (stderr, "Replay logfile using %s\n", name); @@ -299,7 +316,7 @@ expect (FILE *fp) { break; } - read (remote_desc, &fromgdb, 1); + read (remote_desc_in, &fromgdb, 1); } while (fromlog == fromgdb); if (fromlog != EOL) @@ -326,7 +343,7 @@ play (FILE *fp) while ((fromlog = logchar (fp)) != EOL) { ch = fromlog; - write (remote_desc, &ch, 1); + write (remote_desc_out, &ch, 1); } } @@ -338,7 +355,12 @@ main (int argc, char *argv[]) if (argc < 3) { - fprintf (stderr, "Usage: gdbreplay <logfile> <host:port>\n"); + fprintf (stderr, "Usage: gdbreplay <logfile> {<host:port> | fd<in><out>}\n" + "\n" + "Use host:port to listen for a TCP connection, or\n" + "fd<in><out> (such as fd34) for networking over file descriptors:\n" + " " + "socat EXEC:'gdbserver fd34 PROG',fdin=3,fdout=4 TCP6-LISTEN:5000\n"); fflush (stderr); exit (1); } diff -u -p -r1.32 remote-utils.c --- gdb/gdbserver/remote-utils.c 21 Sep 2006 16:09:54 -0000 1.32 +++ gdb/gdbserver/remote-utils.c 8 Oct 2006 15:37:13 -0000 @@ -52,6 +52,7 @@ #if HAVE_ARPA_INET_H #include <arpa/inet.h> #endif +#include <ctype.h> #if USE_WIN32API #include <winsock.h> @@ -79,7 +80,7 @@ int all_symbols_looked_up; int remote_debug = 0; struct ui_file *gdb_stdlog; -static int remote_desc; +static int remote_desc_in, remote_desc_out; /* FIXME headerize? */ extern int using_threads; @@ -95,10 +96,20 @@ remote_open (char *name) int save_fcntl_flags; #endif - if (!strchr (name, ':')) + /* "fd01" for STDIO, "fd23" for socat(1) "fdin=2,fdout=3". */ + if (name[0] == 'f' && name[1] == 'd' + && isdigit (name[2]) && isdigit (name[3]) + && name[4] == 0) { + remote_desc_in = name[2] - '0'; + remote_desc_out = name[3] - '0'; + } + else if (!strchr (name, ':')) + { + int remote_desc; + #ifdef USE_WIN32API - error ("Only <host>:<port> is supported on this platform."); + error ("Only <host>:<port> or fd<in><out> supported on this platform."); #else remote_desc = open (name, O_RDWR); if (remote_desc < 0) @@ -149,10 +160,13 @@ remote_open (char *name) #endif fprintf (stderr, "Remote debugging using %s\n", name); + remote_desc_in = remote_desc_out = remote_desc; #endif /* USE_WIN32API */ } else { + int remote_desc; + #ifdef USE_WIN32API static int winsock_initialized; #endif @@ -224,13 +238,21 @@ remote_open (char *name) /* Convert IP address to string. */ fprintf (stderr, "Remote debugging from host %s\n", inet_ntoa (sockaddr.sin_addr)); + remote_desc_in = remote_desc_out = remote_desc; } #if defined(F_SETFL) && defined (FASYNC) - save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0); - fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC); + save_fcntl_flags = fcntl (remote_desc_in, F_GETFL, 0); + fcntl (remote_desc_in, F_SETFL, save_fcntl_flags | FASYNC); + if (remote_desc_in != remote_desc_out) + { + save_fcntl_flags = fcntl (remote_desc_out, F_GETFL, 0); + fcntl (remote_desc_out, F_SETFL, save_fcntl_flags | FASYNC); + } #if defined (F_SETOWN) - fcntl (remote_desc, F_SETOWN, getpid ()); + fcntl (remote_desc_in, F_SETOWN, getpid ()); + if (remote_desc_in != remote_desc_out) + fcntl (remote_desc_out, F_SETOWN, getpid ()); #endif #endif disable_async_io (); @@ -240,9 +262,13 @@ void remote_close (void) { #ifdef USE_WIN32API - closesocket (remote_desc); + closesocket (remote_desc_in); + if (remote_desc_in != remote_desc_out) + closesocket (remote_desc_out); #else - close (remote_desc); + close (remote_desc_in); + if (remote_desc_in != remote_desc_out) + close (remote_desc_out); #endif } @@ -486,7 +512,7 @@ putpkt_binary (char *buf, int cnt) { int cc; - if (send (remote_desc, buf2, p - buf2, 0) != p - buf2) + if (send (remote_desc_out, buf2, p - buf2, 0) != p - buf2) { perror ("putpkt(write)"); return -1; @@ -497,7 +523,7 @@ putpkt_binary (char *buf, int cnt) fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2); fflush (stderr); } - cc = recv (remote_desc, buf3, 1, 0); + cc = recv (remote_desc_in, buf3, 1, 0); if (remote_debug) { fprintf (stderr, "[received '%c' (0x%x)]\n", buf3[0], buf3[0]); @@ -552,13 +578,13 @@ input_interrupt (int unused) be a problem under NetBSD 1.4 and 1.5. */ FD_ZERO (&readset); - FD_SET (remote_desc, &readset); - if (select (remote_desc + 1, &readset, 0, 0, &immediate) > 0) + FD_SET (remote_desc_in, &readset); + if (select (remote_desc_in + 1, &readset, 0, 0, &immediate) > 0) { int cc; char c = 0; - cc = recv (remote_desc, &c, 1, 0); + cc = recv (remote_desc_in, &c, 1, 0); if (cc != 1 || c != '\003') { @@ -639,7 +665,7 @@ readchar (void) if (bufcnt-- > 0) return *bufp++; - bufcnt = recv (remote_desc, buf, sizeof (buf), 0); + bufcnt = recv (remote_desc_in, buf, sizeof (buf), 0); if (bufcnt <= 0) { @@ -706,7 +732,7 @@ getpkt (char *buf) fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", (c1 << 4) + c2, csum, buf); - send (remote_desc, "-", 1, 0); + send (remote_desc_out, "-", 1, 0); } if (remote_debug) @@ -715,7 +741,7 @@ getpkt (char *buf) fflush (stderr); } - send (remote_desc, "+", 1, 0); + send (remote_desc_out, "+", 1, 0); if (remote_debug) { diff -u -p -r1.39 server.c --- gdb/gdbserver/server.c 8 Aug 2006 16:03:29 -0000 1.39 +++ gdb/gdbserver/server.c 8 Oct 2006 15:37:14 -0000 @@ -435,8 +435,11 @@ gdbserver_usage (void) printf ("Usage:\tgdbserver COMM PROG [ARGS ...]\n" "\tgdbserver COMM --attach PID\n" "\n" - "COMM may either be a tty device (for serial debugging), or \n" - "HOST:PORT to listen for a TCP connection.\n"); + "COMM may either be a tty device (for serial debugging), or\n" + "HOST:PORT to listen for a TCP connection, or\n" + "fd<in><out> (such as fd34) for networking over file descriptors:\n" + " " + "socat EXEC:'gdbserver fd34 PROG',fdin=3,fdout=4 TCP6-LISTEN:5000\n"); } int [-- Attachment #3: gdb-cvs-IPv6-hostport-minus.patch --] [-- Type: text/plain, Size: 9359 bytes --] gdb/gdbserver: 2006-10-08 Jan Kratochvil <jan.kratochvil@redhat.com> * gdbreplay.c (remote_open, main): Remove "host:port" argument support as obsoleted by "fd<in><out>" using socat(1). * remote-utils.c (remote_open): Likewise. * server.c (gdbserver_usage): Likewise. gdb/doc: 2006-10-08 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.texinfo (Using the gdbserver program): Remove "host:port". diff -u -rup gdb-fds-plus/doc/gdb.texinfo gdb/doc/gdb.texinfo --- gdb-fds-plus/doc/gdb.texinfo 2006-10-08 20:27:51.000000000 +0200 +++ gdb/doc/gdb.texinfo 2006-10-08 20:30:51.000000000 +0200 @@ -12567,9 +12567,8 @@ target> gdbserver @var{comm} @var{progra @end smallexample @var{comm} is either a device name (to use a serial line) or file descriptions -numbers or a TCP hostname and portnumber. For example, to debug Emacs with the -argument @samp{foo.txt} and communicate with @value{GDBN} over the serial port -@file{/dev/com1}: +numbers. For example, to debug Emacs with the argument @samp{foo.txt} and +communicate with @value{GDBN} over the serial port @file{/dev/com1}: @smallexample target> gdbserver /dev/com1 emacs foo.txt @@ -12603,13 +12602,6 @@ a port number that conflicts with anothe message and exits.} You must use the same port number with the host @value{GDBN} @code{target remote} command. -On IPv4 networks you may also run @code{gdbserver} directly, without the -@code{socat} helper there (equivalent command to the example above): - -@smallexample -target> gdbserver :2345 emacs foo.txt -@end smallexample - On some targets, @code{gdbserver} can also attach to running programs. This is accomplished via the @code{--attach} argument. The syntax is: diff -u -rup gdb-fds-plus/gdbserver/gdbreplay.c gdb/gdbserver/gdbreplay.c --- gdb-fds-plus/gdbserver/gdbreplay.c 2006-10-08 20:27:51.000000000 +0200 +++ gdb/gdbserver/gdbreplay.c 2006-10-08 20:30:01.000000000 +0200 @@ -129,80 +129,16 @@ remote_open (char *name) } else if (!strchr (name, ':')) { - fprintf (stderr, "%s: Must specify tcp connection as host:addr" - " or use fd<in><out>\n", name); + fprintf (stderr, "%s: Must specify connection as fd<in><out>\n", name); fflush (stderr); exit (1); } else { - int remote_desc; -#ifdef USE_WIN32API - static int winsock_initialized; -#endif - char *port_str; - int port; - struct sockaddr_in sockaddr; - socklen_t tmp; - int tmp_desc; - - port_str = strchr (name, ':'); - - port = atoi (port_str + 1); - -#ifdef USE_WIN32API - if (!winsock_initialized) - { - WSADATA wsad; - - WSAStartup (MAKEWORD (1, 0), &wsad); - winsock_initialized = 1; - } -#endif - - tmp_desc = socket (PF_INET, SOCK_STREAM, 0); - if (tmp_desc < 0) - perror_with_name ("Can't open socket"); - - /* Allow rapid reuse of this port. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, - sizeof (tmp)); - - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - sockaddr.sin_addr.s_addr = INADDR_ANY; - - if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) - || listen (tmp_desc, 1)) - perror_with_name ("Can't bind address"); - - tmp = sizeof (sockaddr); - remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp); - if (remote_desc == -1) - perror_with_name ("Accept failed"); - - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); - - /* Tell TCP not to delay small packets. This greatly speeds up - interactive response. */ - tmp = 1; - setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, - (char *) &tmp, sizeof (tmp)); - - close (tmp_desc); /* No longer need this */ - -#ifndef USE_WIN32API - close (tmp_desc); /* No longer need this */ - - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbreplay simply - exits when the remote side dies. */ -#else - closesocket (tmp_desc); /* No longer need this */ -#endif - remote_desc_in = remote_desc_out = remote_desc; + fprintf (stderr, "%s: tcp host:port no longer supported," + " see the help for fd<in><out>"); + fflush (stderr); + exit (1); } #if defined(F_SETFL) && defined (FASYNC) @@ -357,8 +293,7 @@ main (int argc, char *argv[]) { fprintf (stderr, "Usage: gdbreplay <logfile> {<host:port> | fd<in><out>}\n" "\n" - "Use host:port to listen for a TCP connection, or\n" - "fd<in><out> (such as fd34) for networking over file descriptors:\n" + "Use fd<in><out> (such as fd34) for networking over file descriptors:\n" " " "socat EXEC:'gdbserver fd34 PROG',fdin=3,fdout=4 TCP6-LISTEN:5000\n"); fflush (stderr); diff -u -rup gdb-fds-plus/gdbserver/remote-utils.c gdb/gdbserver/remote-utils.c --- gdb-fds-plus/gdbserver/remote-utils.c 2006-10-08 20:27:51.000000000 +0200 +++ gdb/gdbserver/remote-utils.c 2006-10-08 20:30:01.000000000 +0200 @@ -106,139 +106,11 @@ remote_open (char *name) } else if (!strchr (name, ':')) { - int remote_desc; - -#ifdef USE_WIN32API - error ("Only <host>:<port> or fd<in><out> supported on this platform."); -#else - remote_desc = open (name, O_RDWR); - if (remote_desc < 0) - perror_with_name ("Could not open remote device"); - -#ifdef HAVE_TERMIOS - { - struct termios termios; - tcgetattr (remote_desc, &termios); - - termios.c_iflag = 0; - termios.c_oflag = 0; - termios.c_lflag = 0; - termios.c_cflag &= ~(CSIZE | PARENB); - termios.c_cflag |= CLOCAL | CS8; - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; - - tcsetattr (remote_desc, TCSANOW, &termios); - } -#endif - -#ifdef HAVE_TERMIO - { - struct termio termio; - ioctl (remote_desc, TCGETA, &termio); - - termio.c_iflag = 0; - termio.c_oflag = 0; - termio.c_lflag = 0; - termio.c_cflag &= ~(CSIZE | PARENB); - termio.c_cflag |= CLOCAL | CS8; - termio.c_cc[VMIN] = 1; - termio.c_cc[VTIME] = 0; - - ioctl (remote_desc, TCSETA, &termio); - } -#endif - -#ifdef HAVE_SGTTY - { - struct sgttyb sg; - - ioctl (remote_desc, TIOCGETP, &sg); - sg.sg_flags = RAW; - ioctl (remote_desc, TIOCSETP, &sg); - } -#endif - - fprintf (stderr, "Remote debugging using %s\n", name); - remote_desc_in = remote_desc_out = remote_desc; -#endif /* USE_WIN32API */ + error ("Only fd<in><out> supported on this platform."); } else { - int remote_desc; - -#ifdef USE_WIN32API - static int winsock_initialized; -#endif - char *port_str; - int port; - struct sockaddr_in sockaddr; - socklen_t tmp; - int tmp_desc; - - port_str = strchr (name, ':'); - - port = atoi (port_str + 1); - -#ifdef USE_WIN32API - if (!winsock_initialized) - { - WSADATA wsad; - - WSAStartup (MAKEWORD (1, 0), &wsad); - winsock_initialized = 1; - } -#endif - - tmp_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (tmp_desc < 0) - perror_with_name ("Can't open socket"); - - /* Allow rapid reuse of this port. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, - sizeof (tmp)); - - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - sockaddr.sin_addr.s_addr = INADDR_ANY; - - if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) - || listen (tmp_desc, 1)) - perror_with_name ("Can't bind address"); - - fprintf (stderr, "Listening on port %d\n", port); - fflush (stderr); - - tmp = sizeof (sockaddr); - remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp); - if (remote_desc == -1) - perror_with_name ("Accept failed"); - - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); - - /* Tell TCP not to delay small packets. This greatly speeds up - interactive response. */ - tmp = 1; - setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, - (char *) &tmp, sizeof (tmp)); - - -#ifndef USE_WIN32API - close (tmp_desc); /* No longer need this */ - - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply - exits when the remote side dies. */ -#else - closesocket (tmp_desc); /* No longer need this */ -#endif - - /* Convert IP address to string. */ - fprintf (stderr, "Remote debugging from host %s\n", - inet_ntoa (sockaddr.sin_addr)); - remote_desc_in = remote_desc_out = remote_desc; + error ("tcp host:port no longer supported, see the help for fd<in><out>"); } #if defined(F_SETFL) && defined (FASYNC) diff -u -rup gdb-fds-plus/gdbserver/server.c gdb/gdbserver/server.c --- gdb-fds-plus/gdbserver/server.c 2006-10-08 20:27:51.000000000 +0200 +++ gdb/gdbserver/server.c 2006-10-08 20:30:01.000000000 +0200 @@ -436,7 +436,6 @@ gdbserver_usage (void) "\tgdbserver COMM --attach PID\n" "\n" "COMM may either be a tty device (for serial debugging), or\n" - "HOST:PORT to listen for a TCP connection, or\n" "fd<in><out> (such as fd34) for networking over file descriptors:\n" " " "socat EXEC:'gdbserver fd34 PROG',fdin=3,fdout=4 TCP6-LISTEN:5000\n"); ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-10-08 19:03 ` Jan Kratochvil @ 2006-10-09 4:33 ` Eli Zaretskii 2006-10-09 14:17 ` Jan Kratochvil 0 siblings, 1 reply; 10+ messages in thread From: Eli Zaretskii @ 2006-10-09 4:33 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches > Date: Sun, 8 Oct 2006 21:02:39 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > Cc: gdb-patches@sourceware.org > > patch for the IPv6 support according to the Daniel Jacobowitz's recommendation: > http://sourceware.org/ml/gdb-patches/2006-09/msg00194.html Thanks. I have a few comments about the documentation patch: > -@item target remote @code{@var{host}:@var{port}} > +@item target remote @code{@var{host}:@var{port}} This just changes whitespace; please don't. > +@code{tcp6:} prefix forces IPv6 network connection while @code{tcp4:} forces Please say ``The @code{tcp6:} prefix forces IPv6 network ...''. > +@code{udp6:} prefix forces IPv6 network connection while @code{udp4:} forces Same here. > +@var{comm} is either a device name (to use a serial line) or file descriptions > +numbers or a TCP hostname and portnumber. For example, to debug Emacs with the A better way of putting it would be @var{comm} is a device name (to use a serial line), a file descriptor, or a TCP hostname and portnumber. > -The only difference from the previous example is the first argument, > -specifying that you are communicating with the host @value{GDBN} via > -TCP. The @samp{host:2345} argument means that @code{gdbserver} is to > -expect a TCP connection from machine @samp{host} to local TCP port 2345. > -(Currently, the @samp{host} part is ignored.) You can choose any number > -you want for the port number as long as it does not conflict with any > -TCP ports already in use on the target system (for example, @code{23} is > -reserved for @code{telnet}).@footnote{If you choose a port number that > -conflicts with another service, @code{gdbserver} prints an error message > -and exits.} You must use the same port number with the host @value{GDBN} > -@code{target remote} command. Why did you drop this part? > +This example still debugs the same program just in this case it is specifying > +that you are communicating with the host @value{GDBN} via TCP. > +The @code{gdbserver} specific part @code{fd34} directs @code{gdbserver} to use > +already preopened file descriptor 3 for @value{GDBN} remote serial protocol > +input and file descriptor 4 for the protocol output. As the format is > +@code{fd<character><character>} you cannot specify file descriptors numbers > +above 9. First, please use @var{} instead of <..>, as in @code{fd@var{c1}@var{c2}} (I find <character> too lengthy). And second, isn't there a better way of specifying two descriptors? I find the "fdNM" method inelegant, and the limitation of a single-digit descriptor it requires too high a price to pay. I hope we can come up with a better method. > +You can choose any port number you want (@code{2345} here) as long as it does > +not conflict with any TCP ports already in use on the target system (for > +example, @code{23} is reserved for @code{telnet}).@footnote{If you choose > +a port number that conflicts with another service, @code{socat} prints an error > +message and exits.} You must use the same port number with the host > +@value{GDBN} @code{target remote} command. > + > +On IPv4 networks you may also run @code{gdbserver} directly, without the > +@code{socat} helper there (equivalent command to the example above): > + > +@smallexample > +target> gdbserver :2345 emacs foo.txt > +@end smallexample The example (and the sentence that precedes it) should be before the descriptive text, otherwise the text doesn't make sense. > * gdb.texinfo (Using the gdbserver program): Remove "host:port". Why? I think back-compatibility is important. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-10-09 4:33 ` Eli Zaretskii @ 2006-10-09 14:17 ` Jan Kratochvil 2006-10-09 19:01 ` Daniel Jacobowitz 2006-10-09 19:36 ` Eli Zaretskii 0 siblings, 2 replies; 10+ messages in thread From: Jan Kratochvil @ 2006-10-09 14:17 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 5737 bytes --] Hi Eli, the first patch (formerly "gdb-cvs-IPv6-fds-plus.patch") updated. On Mon, 09 Oct 2006 06:33:09 +0200, Eli Zaretskii wrote: ... > > -@item target remote @code{@var{host}:@var{port}} > > +@item target remote @code{@var{host}:@var{port}} > > This just changes whitespace; please don't. OK. [ Code written before I read such advice from Mark Kettenis. ] > > +@code{tcp6:} prefix forces IPv6 network connection while @code{tcp4:} forces > > Please say ``The @code{tcp6:} prefix forces IPv6 network ...''. OK. > > +@code{udp6:} prefix forces IPv6 network connection while @code{udp4:} forces > > Same here. OK. > > +@var{comm} is either a device name (to use a serial line) or file descriptions > > +numbers or a TCP hostname and portnumber. For example, to debug Emacs with the > > A better way of putting it would be > > @var{comm} is a device name (to use a serial line), a file descriptor, > or a TCP hostname and portnumber. OK. [ Assumed the "hostname" part will get dropped by the second patch. ] > > -The only difference from the previous example is the first argument, > > -specifying that you are communicating with the host @value{GDBN} via > > -TCP. The @samp{host:2345} argument means that @code{gdbserver} is to > > -expect a TCP connection from machine @samp{host} to local TCP port 2345. > > -(Currently, the @samp{host} part is ignored.) You can choose any number > > -you want for the port number as long as it does not conflict with any > > -TCP ports already in use on the target system (for example, @code{23} is > > -reserved for @code{telnet}).@footnote{If you choose a port number that > > -conflicts with another service, @code{gdbserver} prints an error message > > -and exits.} You must use the same port number with the host @value{GDBN} > > -@code{target remote} command. > > Why did you drop this part? Only its first part was dropped - till "You can choose any port number ...". The first sentence was reformulated as it is generally more complicated command using socat(1) and so it is not "the only difference". The part with "@samp{host}" part has been dropped completely as it never got implemented (the "@samp{host}" part is still being ignored nowadays) and it is no longer implementable on top of socat(1), moreover the whole "@samp{host:port}" syntax has been considered as obsolete by the second patch. Patch not changed in this case. > > +This example still debugs the same program just in this case it is specifying > > +that you are communicating with the host @value{GDBN} via TCP. > > +The @code{gdbserver} specific part @code{fd34} directs @code{gdbserver} to use > > +already preopened file descriptor 3 for @value{GDBN} remote serial protocol > > +input and file descriptor 4 for the protocol output. As the format is > > +@code{fd<character><character>} you cannot specify file descriptors numbers > > +above 9. > > First, please use @var{} instead of <..>, as in > @code{fd@var{c1}@var{c2}} (I find <character> too lengthy). > > And second, isn't there a better way of specifying two descriptors? I > find the "fdNM" method inelegant, and the limitation of a single-digit > descriptor it requires too high a price to pay. I hope we can come up > with a better method. Designed for trivia C parsing as the IPv6 support was considered too complicated by Daniel Jacobowitz and the string parsing in C is a lot of lines. The new syntax looks like that of socat(1): socat EXEC:'gdbserver fdin=3,fdout=4 emacs foo.txt',fdin=3,fdout=4 TCP-LISTEN:2345 > > +You can choose any port number you want (@code{2345} here) as long as it does > > +not conflict with any TCP ports already in use on the target system (for > > +example, @code{23} is reserved for @code{telnet}).@footnote{If you choose > > +a port number that conflicts with another service, @code{socat} prints an error > > +message and exits.} You must use the same port number with the host > > +@value{GDBN} @code{target remote} command. > > + > > +On IPv4 networks you may also run @code{gdbserver} directly, without the > > +@code{socat} helper there (equivalent command to the example above): > > + > > +@smallexample > > +target> gdbserver :2345 emacs foo.txt > > +@end smallexample > > The example (and the sentence that precedes it) should be before the > descriptive text, otherwise the text doesn't make sense. The first paragraph describes the line above it: socat EXEC:'gdbserver fdin=3,fdout=4 emacs foo.txt',fdin=3,fdout=4 TCP-LISTEN:2345 It looks weird to me to move the deprecated syntax above the first paragraph describing the port in 2345 general (primarily for the new socat(1) syntax). Moreover even the following paragraph starting "On some targets, @code{gdbserver} can also attach ..." precedes its sample code below it. Text reshuffled although the port description is still above - for the socat(1) syntax. Otherwise the whole text should be reorganized to keep the IPv4 "host:port" syntax as the preferred one and socat(1) syntax as the secondary one. For example I personally do not like the requirement to use socat(1) at the resource-limited embedded systems running gdbserver(1) at all. > > * gdb.texinfo (Using the gdbserver program): Remove "host:port". > > Why? I think back-compatibility is important. It looks broken to me to support IPv4 without supporting IPv6, moreover if the IPv6 functions to use are simpler. I hope you are aware of the former full IPv6 support posted here: http://sourceware.org/ml/gdb-patches/2006-09/msg00216.html The second patch "gdb-cvs-IPv6-hostport-minus.patch" was not updated for this one as it looks as the IPv4 legacy code is not going to be dropped even with the socat(1) support there. Thanks, Jan [-- Attachment #2: gdb-cvs-IPv6-fds.patch --] [-- Type: text/plain, Size: 33838 bytes --] gdb: 2006-10-09 Jan Kratochvil <jan.kratochvil@redhat.com> * ser-tcp.c (net_open): Support IPv6 "tcp6:"&co. notation. * configure.ac: Check for IPv6 getaddrinfo, getnameinfo and AF_INET6. * configure, config.in: Regenerate. gdb/gdbserver: 2006-10-09 Jan Kratochvil <jan.kratochvil@redhat.com> * gdbreplay.c (remote_open, main): Support "fdin=...," fds argument. (remote_desc_in, remote_desc_out, remote_close, remote_open, expect, play): Replace `remote_desc' by `remote_desc_in' and `remote_desc_out'. * remote-utils.c (remote_desc_in, remote_desc_out, remote_close, remote_open, putpkt_binary, input_interrupt, readchar, getpkt): Replace `remote_desc' by `remote_desc_in' and `remote_desc_out'. * server.c (gdbserver_usage): Descripe "fdin=...," fds argument. gdb/doc: 2006-10-09 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.texinfo (Connecting to a remote target): Describe IPv6 "tcp6:"&co. notation. (Using the gdbserver program): Describe "fdin=...," comm notation. diff -u -p -r1.84 config.in --- gdb/config.in 8 Aug 2006 20:32:15 -0000 1.84 +++ gdb/config.in 9 Oct 2006 14:02:29 -0000 @@ -67,6 +67,10 @@ /* Define to 1 if you have the <curses.h> header file. */ #undef HAVE_CURSES_H +/* Define to 1 if you have the declaration of `AF_INET6', and to 0 if you + don't. */ +#undef HAVE_DECL_AF_INET6 + /* Define to 1 if you have the declaration of `free', and to 0 if you don't. */ #undef HAVE_DECL_FREE @@ -113,9 +117,15 @@ /* Define if <sys/procfs.h> has fpregset_t. */ #undef HAVE_FPREGSET_T +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + /* Define to 1 if you have the `getgid' function. */ #undef HAVE_GETGID +/* Define to 1 if you have the `getnameinfo' function. */ +#undef HAVE_GETNAMEINFO + /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE diff -u -p -r1.213 configure --- gdb/configure 8 Aug 2006 20:32:15 -0000 1.213 +++ gdb/configure 9 Oct 2006 14:02:32 -0000 @@ -17453,6 +17453,285 @@ fi done +for ac_func in getaddrinfo +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +for ac_func in getnameinfo +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +echo "$as_me:$LINENO: checking whether AF_INET6 is declared" >&5 +echo $ECHO_N "checking whether AF_INET6 is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl_AF_INET6+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/socket.h> + + +int +main () +{ +#ifndef AF_INET6 + char *p = (char *) AF_INET6; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_AF_INET6=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl_AF_INET6=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl_AF_INET6" >&5 +echo "${ECHO_T}$ac_cv_have_decl_AF_INET6" >&6 +if test $ac_cv_have_decl_AF_INET6 = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AF_INET6 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AF_INET6 0 +_ACEOF + + +fi + + + # Check the return and argument types of ptrace. No canned test for # this, so roll our own. gdb_ptrace_headers=' @@ -22335,7 +22614,7 @@ ac_x_header_dirs=' /usr/openwin/share/include' if test "$ac_x_includes" = no; then - # Guess where to find include files, by looking for Intrinsic.h. + # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -22343,7 +22622,7 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <X11/Intrinsic.h> +#include <X11/Xlib.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -22370,7 +22649,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do - if test -r "$ac_dir/X11/Intrinsic.h"; then + if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi @@ -22384,18 +22663,18 @@ if test "$ac_x_libraries" = no; then # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS - LIBS="-lXt $LIBS" + LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <X11/Intrinsic.h> +#include <X11/Xlib.h> int main () { -XtMalloc (0) +XrmInitialize () ; return 0; } diff -u -p -r1.34 configure.ac --- gdb/configure.ac 8 Aug 2006 20:26:23 -0000 1.34 +++ gdb/configure.ac 9 Oct 2006 14:02:32 -0000 @@ -446,6 +446,12 @@ AC_CHECK_FUNCS(socketpair) AC_CHECK_FUNCS(syscall) AC_CHECK_FUNCS(ttrace) AC_CHECK_FUNCS(wborder) +AC_CHECK_FUNCS(getaddrinfo) +AC_CHECK_FUNCS(getnameinfo) +AC_CHECK_DECLS(AF_INET6, [], [], +[#include <sys/types.h> +#include <sys/socket.h> +]) # Check the return and argument types of ptrace. No canned test for # this, so roll our own. diff -u -p -r1.26 ser-tcp.c --- gdb/ser-tcp.c 10 Feb 2006 22:01:43 -0000 1.26 +++ gdb/ser-tcp.c 9 Oct 2006 14:02:32 -0000 @@ -68,67 +68,142 @@ void _initialize_ser_tcp (void); int net_open (struct serial *scb, const char *name) { - char *port_str, hostname[100]; - int n, port, tmp; - int use_udp; - struct hostent *hostent; - struct sockaddr_in sockaddr; + char *name_base; + char *port_str; + int n, tmp; #ifdef USE_WIN32API u_long ioarg; #else int ioarg; #endif - - use_udp = 0; - if (strncmp (name, "udp:", 4) == 0) + struct prefix + { + const char *string; + int family; + int socktype; + }; + const struct prefix prefixes[] = { - use_udp = 1; - name = name + 4; + { "udp:", AF_UNSPEC, SOCK_DGRAM }, + { "tcp:", AF_UNSPEC, SOCK_STREAM }, + { "udp4:", AF_INET, SOCK_DGRAM }, + { "tcp4:", AF_INET, SOCK_STREAM }, +/* We do not support `AF_INET6' without getaddrinfo(3). */ +#if defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 + { "udp6:", AF_INET6, SOCK_DGRAM }, + { "tcp6:", AF_INET6, SOCK_STREAM }, +#endif /* defined (HAVE_GETADDRINFO) && HAVE_DECL_AF_INET6 */ + }; + const struct prefix *prefix; +#ifdef HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo *addrinfo_base, *addrinfo = NULL; +#else /* !HAVE_GETADDRINFO */ + struct hostent *hostent; + struct sockaddr_in sockaddr; +#endif /* !HAVE_GETADDRINFO */ + /* Error by default. */ + int retval = -1; + + name_base = xstrdup (name); + name = name_base; +#ifdef HAVE_GETADDRINFO + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; +#endif /* HAVE_GETADDRINFO */ + for (prefix = prefixes; prefix < prefixes + ARRAY_SIZE (prefixes); prefix++) + if (strncmp (name, prefix->string, strlen (prefix->string)) == 0) + { + name += strlen (prefix->string); +#ifdef HAVE_GETADDRINFO + hints.ai_family = prefix->family; + hints.ai_socktype = prefix->socktype; +#endif /* HAVE_GETADDRINFO */ + break; + } + if (prefix >= prefixes + ARRAY_SIZE (prefixes)) + prefix = NULL; + if ((prefix == NULL || prefix->family != AF_INET) + && name[0] == '[' && (port_str = strchr (name, ']'))) + { + name++; + *port_str++ = 0; + } + else + port_str = strchr (name, ':'); + /* It may happen with IPv6 for like "[::1]". */ + if (port_str == NULL || *port_str != ':') + error (_("net_open: No colon in host name!")); + *port_str++ = 0; + + /* Default hostname for `node == NULL' is localhost + as we did not specify `hints.ai_flags & AI_PASSIVE'. */ + if (name[0] == 0) + name = NULL; + +#ifdef HAVE_GETADDRINFO + n = getaddrinfo (name, port_str, &hints, &addrinfo_base); + if (n != 0) + { + fprintf_unfiltered (gdb_stderr, "%s:%s: cannot resolve name: %s\n", + (name != NULL ? name : "<local>"), + port_str, gai_strerror (n)); + errno = ENOENT; + free (name_base); + return -1; } - else if (strncmp (name, "tcp:", 4) == 0) - name = name + 4; - - port_str = strchr (name, ':'); - - if (!port_str) - error (_("net_open: No colon in host name!")); /* Shouldn't ever happen */ - - tmp = min (port_str - name, (int) sizeof hostname - 1); - strncpy (hostname, name, tmp); /* Don't want colon */ - hostname[tmp] = '\000'; /* Tie off host name */ - port = atoi (port_str + 1); - /* default hostname is localhost */ - if (!hostname[0]) - strcpy (hostname, "localhost"); + /* Still used for `port_str' above. */ + free (name_base); - hostent = gethostbyname (hostname); - if (!hostent) + for (addrinfo = addrinfo_base; addrinfo != NULL; addrinfo = addrinfo->ai_next) + { + scb->fd = socket (addrinfo->ai_family, addrinfo->ai_socktype, + addrinfo->ai_protocol); + if (scb->fd >= 0) + break; + } + if (addrinfo == NULL) { - fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname); + freeaddrinfo (addrinfo_base); + return -1; + } +#else /* !HAVE_GETADDRINFO */ + hostent = gethostbyname ((name != NULL ? name : "localhost")); + if (hostent == NULL) + { + fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", name); errno = ENOENT; + free (name_base); return -1; } - if (use_udp) - scb->fd = socket (PF_INET, SOCK_DGRAM, 0); - else - scb->fd = socket (PF_INET, SOCK_STREAM, 0); + sockaddr.sin_family = PF_INET; + sockaddr.sin_port = htons (atoi (port_str)); + memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + /* Still used for `port_str' above. */ + free (name_base); + + scb->fd = socket (sockaddr.sin_family, + (prefix != NULL ? prefix->socktype : SOCK_STREAM), + 0); if (scb->fd < 0) return -1; - - sockaddr.sin_family = PF_INET; - sockaddr.sin_port = htons (port); - memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, - sizeof (struct in_addr)); +#endif /* !HAVE_GETADDRINFO */ /* set socket nonblocking */ ioarg = 1; ioctl (scb->fd, FIONBIO, &ioarg); /* Use Non-blocking connect. connect() will return 0 if connected already. */ +#ifdef HAVE_GETADDRINFO + n = connect (scb->fd, addrinfo->ai_addr, addrinfo->ai_addrlen); +#else /* !HAVE_GETADDRINFO */ n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); +#endif /* !HAVE_GETADDRINFO */ if (n < 0 #ifdef USE_WIN32API @@ -143,8 +218,7 @@ net_open (struct serial *scb, const char #ifdef USE_WIN32API errno = WSAGetLastError(); #endif - net_close (scb); - return -1; + goto cleanup_scb; } if (n) @@ -165,8 +239,7 @@ net_open (struct serial *scb, const char if (deprecated_ui_loop_hook (0)) { errno = EINTR; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -192,8 +265,7 @@ net_open (struct serial *scb, const char { if (polls > TIMEOUT * POLL_INTERVAL) errno = ETIMEDOUT; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -211,8 +283,7 @@ net_open (struct serial *scb, const char { if (err) errno = err; - net_close (scb); - return -1; + goto cleanup_scb; } } @@ -220,7 +291,7 @@ net_open (struct serial *scb, const char ioarg = 0; ioctl (scb->fd, FIONBIO, &ioarg); - if (use_udp == 0) + if (prefix == NULL || prefix->socktype == SOCK_STREAM) { /* Disable Nagle algorithm. Needed in some cases. */ tmp = 1; @@ -234,7 +305,16 @@ net_open (struct serial *scb, const char signal (SIGPIPE, SIG_IGN); #endif - return 0; + retval = 0; + goto cleanup_addrinfo_base; + +cleanup_scb: + net_close (scb); +cleanup_addrinfo_base: +#ifdef HAVE_GETADDRINFO + freeaddrinfo (addrinfo_base); +#endif /* HAVE_GETADDRINFO */ + return retval; } void diff -u -p -r1.355 gdb.texinfo --- gdb/doc/gdb.texinfo 21 Sep 2006 14:01:12 -0000 1.355 +++ gdb/doc/gdb.texinfo 9 Oct 2006 14:02:42 -0000 @@ -12406,6 +12406,8 @@ If you're using a serial line, you may w @item target remote @code{@var{host}:@var{port}} @itemx target remote @code{tcp:@var{host}:@var{port}} +@itemx target remote @code{tcp4:@var{host}:@var{port}} +@itemx target remote @code{tcp6:@var{host}:@var{port}} @cindex @acronym{TCP} port, @code{target remote} Debug using a @acronym{TCP} connection to @var{port} on @var{host}. The @var{host} may be either a host name or a numeric @acronym{IP} @@ -12414,6 +12416,9 @@ the target machine itself, if it is dire it might be a terminal server which in turn has a serial line to the target. +The @code{tcp6:} prefix forces IPv6 network connection while @code{tcp4:} +forces IPv4, both on the reliable stream TCP connection. + For example, to connect to port 2828 on a terminal server named @code{manyfarms}: @@ -12434,10 +12439,15 @@ target remote :1234 Note that the colon is still required here. @item target remote @code{udp:@var{host}:@var{port}} +@itemx target remote @code{udp6:@var{host}:@var{port}} +@itemx target remote @code{udp4:@var{host}:@var{port}} @cindex @acronym{UDP} port, @code{target remote} Debug using @acronym{UDP} packets to @var{port} on @var{host}. For example, to connect to @acronym{UDP} port 2828 on a terminal server named @code{manyfarms}: +The @code{udp6:} prefix forces IPv6 network connection while @code{udp4:} +forces IPv4, both on the unreliable datagram UDP connection. + @smallexample target remote udp:manyfarms:2828 @end smallexample @@ -12556,9 +12566,9 @@ syntax is: target> gdbserver @var{comm} @var{program} [ @var{args} @dots{} ] @end smallexample -@var{comm} is either a device name (to use a serial line) or a TCP -hostname and portnumber. For example, to debug Emacs with the argument -@samp{foo.txt} and communicate with @value{GDBN} over the serial port +@var{comm} is a device name (to use a serial line), a file descriptor, +or a TCP hostname and portnumber. For example, to debug Emacs with the +argument @samp{foo.txt} and communicate with @value{GDBN} over the serial port @file{/dev/com1}: @smallexample @@ -12571,20 +12581,33 @@ with it. To use a TCP connection instead of a serial line: @smallexample -target> gdbserver host:2345 emacs foo.txt +target> socat EXEC:'gdbserver fdin=3,fdout=4 emacs foo.txt',fdin=3,fdout=4 TCP-LISTEN:2345 +@end smallexample + +This example still debugs the same program just in this case it is specifying +that you are communicating with the host @value{GDBN} via TCP. +The @code{gdbserver} specific part @code{fd34} directs @code{gdbserver} to use +already preopened file descriptor 3 for @value{GDBN} remote serial protocol +input and file descriptor 4 for the protocol output. Do not use the file +descriptors 0, 1 or 2 as the @value{GDBN} protocol communication could get +corrupted by the inferior program's stdio. + +Please check external @code{socat} program documentation for other available +network options (such as using @code{TCP6-LISTEN} for IPv6 networks). + +You can choose any port number you want (@code{2345} here) as long as it does +not conflict with any TCP ports already in use on the target system (for +example, @code{23} is reserved for @code{telnet}).@footnote{If you choose +a port number that conflicts with another service, @code{socat} prints an error +message and exits.} You must use the same port number with the host +@value{GDBN} @code{target remote} command. + +@smallexample +target> gdbserver :2345 emacs foo.txt @end smallexample -The only difference from the previous example is the first argument, -specifying that you are communicating with the host @value{GDBN} via -TCP. The @samp{host:2345} argument means that @code{gdbserver} is to -expect a TCP connection from machine @samp{host} to local TCP port 2345. -(Currently, the @samp{host} part is ignored.) You can choose any number -you want for the port number as long as it does not conflict with any -TCP ports already in use on the target system (for example, @code{23} is -reserved for @code{telnet}).@footnote{If you choose a port number that -conflicts with another service, @code{gdbserver} prints an error message -and exits.} You must use the same port number with the host @value{GDBN} -@code{target remote} command. +On IPv4 networks you may also run @code{gdbserver} directly as shown above, +without the @code{socat} helper there. On some targets, @code{gdbserver} can also attach to running programs. This is accomplished via the @code{--attach} argument. The syntax is: diff -u -p -r1.12 gdbreplay.c --- gdb/gdbserver/gdbreplay.c 23 Jul 2006 03:52:15 -0000 1.12 +++ gdb/gdbserver/gdbreplay.c 9 Oct 2006 14:02:42 -0000 @@ -61,7 +61,7 @@ typedef int socklen_t; /* Sort of a hack... */ #define EOL (EOF - 1) -static int remote_desc; +static int remote_desc_in, remote_desc_out; /* Print the system error message for errno, and also mention STRING as the file name for which the error was encountered. @@ -103,26 +103,80 @@ static void remote_close (void) { #ifdef USE_WIN32API - closesocket (remote_desc); + closesocket (remote_desc_in); + if (remote_desc_in != remote_desc_out) + closesocket (remote_desc_out); #else - close (remote_desc); + close (remote_desc_in); + if (remote_desc_in != remote_desc_out) + close (remote_desc_out); #endif } +/* Parse the string "fdin=<#>,fdout=<#>" into `remote_desc_in' and + `remote_desc_out' file descripts. Return non-zero for success. */ + +static int +parse_fds (char *name) +{ + const char *fdin_string = "fdin="; + size_t fdin_string_len = strlen (fdin_string); + const char *comma_fdout_string = ",fdout="; + size_t comma_fdout_string_len = strlen (comma_fdout_string); + long l; + + if (strncmp (name, fdin_string, fdin_string_len) != 0) + return 0; + name += fdin_string_len; + + if (*name == 0 || *name == ',') + return 0; + errno = 0; + l = strtol (name, &name, 10); + remote_desc_in = l; + if (errno != 0 || name == NULL || l < 0 || remote_desc_in != l) + return 0; + + if (strncmp (name, comma_fdout_string, comma_fdout_string_len) != 0) + return 0; + name += comma_fdout_string_len; + + if (*name == 0 || *name == ',') + return 0; + errno = 0; + l = strtol (name, &name, 10); + remote_desc_out = l; + if (errno != 0 || name == NULL || l < 0 || remote_desc_out != l) + return 0; + + if (*name != 0) + return 0; + + return 1; +} + /* Open a connection to a remote debugger. NAME is the filename used for communication. */ static void remote_open (char *name) { - if (!strchr (name, ':')) + /* "fdin=<#>,fdout=<#>" */ + if (parse_fds (name)) + { + fprintf (stderr, "Remote debugging using file descriptors" + " (input = %d, output = %d)\n", remote_desc_in, remote_desc_out); + } + else if (!strchr (name, ':')) { - fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name); + fprintf (stderr, "%s: Must specify tcp connection as host:addr" + " or use fdin=<fd #>,fdout=<fd #>\n", name); fflush (stderr); exit (1); } else { + int remote_desc; #ifdef USE_WIN32API static int winsock_initialized; #endif @@ -188,10 +242,13 @@ remote_open (char *name) #else closesocket (tmp_desc); /* No longer need this */ #endif + remote_desc_in = remote_desc_out = remote_desc; } #if defined(F_SETFL) && defined (FASYNC) - fcntl (remote_desc, F_SETFL, FASYNC); + fcntl (remote_desc_in, F_SETFL, FASYNC); + if (remote_desc_in != remote_desc_out) + fcntl (remote_desc_out, F_SETFL, FASYNC); #endif fprintf (stderr, "Replay logfile using %s\n", name); @@ -299,7 +356,7 @@ expect (FILE *fp) { break; } - read (remote_desc, &fromgdb, 1); + read (remote_desc_in, &fromgdb, 1); } while (fromlog == fromgdb); if (fromlog != EOL) @@ -326,7 +383,7 @@ play (FILE *fp) while ((fromlog = logchar (fp)) != EOL) { ch = fromlog; - write (remote_desc, &ch, 1); + write (remote_desc_out, &ch, 1); } } @@ -338,7 +395,13 @@ main (int argc, char *argv[]) if (argc < 3) { - fprintf (stderr, "Usage: gdbreplay <logfile> <host:port>\n"); + fprintf (stderr, "Usage: gdbreplay <logfile>" + " {<host:port> | fdin=<fd #>,fdout=<fd #>}\n" + "\n" + "Use host:port to listen for a TCP connection, or\n" + "fdin=<fd #>,fdout=<fd #> for networking over file descriptors:\n" + " socat EXEC:'gdbserver fdin=3,fdout=4 PROG',fdin=3,fdout=4" + " TCP6-LISTEN:5000\n"); fflush (stderr); exit (1); } diff -u -p -r1.32 remote-utils.c --- gdb/gdbserver/remote-utils.c 21 Sep 2006 16:09:54 -0000 1.32 +++ gdb/gdbserver/remote-utils.c 9 Oct 2006 14:02:42 -0000 @@ -52,6 +52,7 @@ #if HAVE_ARPA_INET_H #include <arpa/inet.h> #endif +#include <ctype.h> #if USE_WIN32API #include <winsock.h> @@ -79,12 +80,54 @@ int all_symbols_looked_up; int remote_debug = 0; struct ui_file *gdb_stdlog; -static int remote_desc; +static int remote_desc_in, remote_desc_out; /* FIXME headerize? */ extern int using_threads; extern int debug_threads; +/* Parse the string "fdin=<#>,fdout=<#>" into `remote_desc_in' and + `remote_desc_out' file descripts. Return non-zero for success. */ + +static int +parse_fds (char *name) +{ + const char *fdin_string = "fdin="; + size_t fdin_string_len = strlen (fdin_string); + const char *comma_fdout_string = ",fdout="; + size_t comma_fdout_string_len = strlen (comma_fdout_string); + long l; + + if (strncmp (name, fdin_string, fdin_string_len) != 0) + return 0; + name += fdin_string_len; + + if (*name == 0 || *name == ',') + return 0; + errno = 0; + l = strtol (name, &name, 10); + remote_desc_in = l; + if (errno != 0 || name == NULL || l < 0 || remote_desc_in != l) + return 0; + + if (strncmp (name, comma_fdout_string, comma_fdout_string_len) != 0) + return 0; + name += comma_fdout_string_len; + + if (*name == 0 || *name == ',') + return 0; + errno = 0; + l = strtol (name, &name, 10); + remote_desc_out = l; + if (errno != 0 || name == NULL || l < 0 || remote_desc_out != l) + return 0; + + if (*name != 0) + return 0; + + return 1; +} + /* Open a connection to a remote debugger. NAME is the filename used for communication. */ @@ -94,11 +137,20 @@ remote_open (char *name) #if defined(F_SETFL) && defined (FASYNC) int save_fcntl_flags; #endif - - if (!strchr (name, ':')) + + /* "fdin=<#>,fdout=<#>" */ + if (parse_fds (name)) { + fprintf (stderr, "Remote debugging using file descriptors" + " (input = %d, output = %d)\n", remote_desc_in, remote_desc_out); + } + else if (!strchr (name, ':')) + { + int remote_desc; + #ifdef USE_WIN32API - error ("Only <host>:<port> is supported on this platform."); + error ("Only <host>:<port> or fdin=<fd #>,fdout=<fd #>" + " supported on this platform."); #else remote_desc = open (name, O_RDWR); if (remote_desc < 0) @@ -149,10 +201,13 @@ remote_open (char *name) #endif fprintf (stderr, "Remote debugging using %s\n", name); + remote_desc_in = remote_desc_out = remote_desc; #endif /* USE_WIN32API */ } else { + int remote_desc; + #ifdef USE_WIN32API static int winsock_initialized; #endif @@ -224,13 +279,21 @@ remote_open (char *name) /* Convert IP address to string. */ fprintf (stderr, "Remote debugging from host %s\n", inet_ntoa (sockaddr.sin_addr)); + remote_desc_in = remote_desc_out = remote_desc; } #if defined(F_SETFL) && defined (FASYNC) - save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0); - fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC); + save_fcntl_flags = fcntl (remote_desc_in, F_GETFL, 0); + fcntl (remote_desc_in, F_SETFL, save_fcntl_flags | FASYNC); + if (remote_desc_in != remote_desc_out) + { + save_fcntl_flags = fcntl (remote_desc_out, F_GETFL, 0); + fcntl (remote_desc_out, F_SETFL, save_fcntl_flags | FASYNC); + } #if defined (F_SETOWN) - fcntl (remote_desc, F_SETOWN, getpid ()); + fcntl (remote_desc_in, F_SETOWN, getpid ()); + if (remote_desc_in != remote_desc_out) + fcntl (remote_desc_out, F_SETOWN, getpid ()); #endif #endif disable_async_io (); @@ -240,9 +303,13 @@ void remote_close (void) { #ifdef USE_WIN32API - closesocket (remote_desc); + closesocket (remote_desc_in); + if (remote_desc_in != remote_desc_out) + closesocket (remote_desc_out); #else - close (remote_desc); + close (remote_desc_in); + if (remote_desc_in != remote_desc_out) + close (remote_desc_out); #endif } @@ -486,7 +553,7 @@ putpkt_binary (char *buf, int cnt) { int cc; - if (send (remote_desc, buf2, p - buf2, 0) != p - buf2) + if (send (remote_desc_out, buf2, p - buf2, 0) != p - buf2) { perror ("putpkt(write)"); return -1; @@ -497,7 +564,7 @@ putpkt_binary (char *buf, int cnt) fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2); fflush (stderr); } - cc = recv (remote_desc, buf3, 1, 0); + cc = recv (remote_desc_in, buf3, 1, 0); if (remote_debug) { fprintf (stderr, "[received '%c' (0x%x)]\n", buf3[0], buf3[0]); @@ -552,13 +619,13 @@ input_interrupt (int unused) be a problem under NetBSD 1.4 and 1.5. */ FD_ZERO (&readset); - FD_SET (remote_desc, &readset); - if (select (remote_desc + 1, &readset, 0, 0, &immediate) > 0) + FD_SET (remote_desc_in, &readset); + if (select (remote_desc_in + 1, &readset, 0, 0, &immediate) > 0) { int cc; char c = 0; - cc = recv (remote_desc, &c, 1, 0); + cc = recv (remote_desc_in, &c, 1, 0); if (cc != 1 || c != '\003') { @@ -639,7 +706,7 @@ readchar (void) if (bufcnt-- > 0) return *bufp++; - bufcnt = recv (remote_desc, buf, sizeof (buf), 0); + bufcnt = recv (remote_desc_in, buf, sizeof (buf), 0); if (bufcnt <= 0) { @@ -706,7 +773,7 @@ getpkt (char *buf) fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", (c1 << 4) + c2, csum, buf); - send (remote_desc, "-", 1, 0); + send (remote_desc_out, "-", 1, 0); } if (remote_debug) @@ -715,7 +782,7 @@ getpkt (char *buf) fflush (stderr); } - send (remote_desc, "+", 1, 0); + send (remote_desc_out, "+", 1, 0); if (remote_debug) { diff -u -p -r1.39 server.c --- gdb/gdbserver/server.c 8 Aug 2006 16:03:29 -0000 1.39 +++ gdb/gdbserver/server.c 9 Oct 2006 14:02:45 -0000 @@ -435,8 +435,11 @@ gdbserver_usage (void) printf ("Usage:\tgdbserver COMM PROG [ARGS ...]\n" "\tgdbserver COMM --attach PID\n" "\n" - "COMM may either be a tty device (for serial debugging), or \n" - "HOST:PORT to listen for a TCP connection.\n"); + "COMM may either be a tty device (for serial debugging), or\n" + "HOST:PORT to listen for a TCP connection, or\n" + "fdin=<fd #>,fdout=<fd #> for networking over file descriptors:\n" + " socat EXEC:'gdbserver fdin=3,fdout=4 PROG',fdin=3,fdout=4" + " TCP6-LISTEN:5000\n"); } int ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-10-09 14:17 ` Jan Kratochvil @ 2006-10-09 19:01 ` Daniel Jacobowitz 2006-10-09 19:36 ` Eli Zaretskii 1 sibling, 0 replies; 10+ messages in thread From: Daniel Jacobowitz @ 2006-10-09 19:01 UTC (permalink / raw) To: Jan Kratochvil; +Cc: Eli Zaretskii, gdb-patches On Mon, Oct 09, 2006 at 04:16:34PM +0200, Jan Kratochvil wrote: > > And second, isn't there a better way of specifying two descriptors? I > > find the "fdNM" method inelegant, and the limitation of a single-digit > > descriptor it requires too high a price to pay. I hope we can come up > > with a better method. > > Designed for trivia C parsing as the IPv6 support was considered too > complicated by Daniel Jacobowitz and the string parsing in C is a lot of lines. > The new syntax looks like that of socat(1): > socat EXEC:'gdbserver fdin=3,fdout=4 emacs foo.txt',fdin=3,fdout=4 TCP-LISTEN:2345 We're a GNU program. We should use the standard GNU style for command line options wherever possible. Anyway, I don't think we need another update of this patch; let's get answers to the big picture questions first. I've asked the general questions I want feedback about on the gdb@ mailing list, in another message. Then, if it needs any big reworking, I'll volunteer to finish it. We've made you jump through enough hoops already! I'd prefer to avoid the "tcp6:" syntax if we can, and have things work transparently. It's been about a year since I last looked at IPv6 support in anything, though. Do you think this is feasible? In particular, "target remote hostname:port" ought to work fine for IPv6. > > > * gdb.texinfo (Using the gdbserver program): Remove "host:port". > > > > Why? I think back-compatibility is important. > > It looks broken to me to support IPv4 without supporting IPv6, moreover if the > IPv6 functions to use are simpler. I hope you are aware of the former full > IPv6 support posted here: > http://sourceware.org/ml/gdb-patches/2006-09/msg00216.html > > > The second patch "gdb-cvs-IPv6-hostport-minus.patch" was not updated for this > one as it looks as the IPv4 legacy code is not going to be dropped even with > the socat(1) support there. Plenty of people use gdbserver with IPv4, and up until now, no one has even asked us for IPv6 support. I think it's absurd to say that IPv6 is as essential as IPv4 support here. Maybe I was wrong, and we should go ahead and add IPv6 directly to gdbserver. I need to understand the usefulness first. Let's give it a few days. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] IPv6 support for gdbserver 2006-10-09 14:17 ` Jan Kratochvil 2006-10-09 19:01 ` Daniel Jacobowitz @ 2006-10-09 19:36 ` Eli Zaretskii 1 sibling, 0 replies; 10+ messages in thread From: Eli Zaretskii @ 2006-10-09 19:36 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches > Date: Mon, 9 Oct 2006 16:16:34 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > Cc: gdb-patches@sourceware.org > > > And second, isn't there a better way of specifying two descriptors? I > > find the "fdNM" method inelegant, and the limitation of a single-digit > > descriptor it requires too high a price to pay. I hope we can come up > > with a better method. > > Designed for trivia C parsing as the IPv6 support was considered too > complicated by Daniel Jacobowitz and the string parsing in C is a lot of lines. > The new syntax looks like that of socat(1): > socat EXEC:'gdbserver fdin=3,fdout=4 emacs foo.txt',fdin=3,fdout=4 TCP-LISTEN:2345 I'd prefer to lift the limitation of one-digit descriptor. > > > +You can choose any port number you want (@code{2345} here) as long as it does > > > +not conflict with any TCP ports already in use on the target system (for > > > +example, @code{23} is reserved for @code{telnet}).@footnote{If you choose > > > +a port number that conflicts with another service, @code{socat} prints an error > > > +message and exits.} You must use the same port number with the host > > > +@value{GDBN} @code{target remote} command. > > > + > > > +On IPv4 networks you may also run @code{gdbserver} directly, without the > > > +@code{socat} helper there (equivalent command to the example above): > > > + > > > +@smallexample > > > +target> gdbserver :2345 emacs foo.txt > > > +@end smallexample > > > > The example (and the sentence that precedes it) should be before the > > descriptive text, otherwise the text doesn't make sense. > > The first paragraph describes the line above it: > socat EXEC:'gdbserver fdin=3,fdout=4 emacs foo.txt',fdin=3,fdout=4 TCP-LISTEN:2345 Sorry, I didn't see the "2345" at the end of that line. Which reminds me: lines in @smallexample should be shorter than 64 characters; anything longer will overflow the page margin. So please break the long lines in @smallexample into two lines. > > > * gdb.texinfo (Using the gdbserver program): Remove "host:port". > > > > Why? I think back-compatibility is important. > > It looks broken to me to support IPv4 without supporting IPv6, moreover if the > IPv6 functions to use are simpler. That's not a reason good enough to drop back-compatibility, even if I'd agree with your assertion about IPv6 (which I don't, and neither does Daniel, I think). ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2006-10-09 19:36 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2006-09-27 16:33 [patch] IPv6 support for gdbserver Jan Kratochvil 2006-09-27 18:20 ` Daniel Jacobowitz 2006-09-27 18:56 ` Jan Kratochvil 2006-09-27 19:06 ` Daniel Jacobowitz 2006-09-30 15:28 ` Jan Kratochvil 2006-10-08 19:03 ` Jan Kratochvil 2006-10-09 4:33 ` Eli Zaretskii 2006-10-09 14:17 ` Jan Kratochvil 2006-10-09 19:01 ` Daniel Jacobowitz 2006-10-09 19:36 ` Eli Zaretskii
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox