public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Sergio Durigan Junior <sergiodj@redhat.com>
To: GDB Patches <gdb-patches@sourceware.org>
Cc: Pedro Alves <palves@redhat.com>, 	Eli Zaretskii <eliz@gnu.org>,
		Jan Kratochvil <jan.kratochvil@redhat.com>,
		Paul Fertser <fercerpav@gmail.com>,
		Tsutomu Seki <sekiriki@gmail.com>
Subject: Re: [PATCH] Implement IPv6 support for GDB/gdbserver
Date: Thu, 31 May 2018 20:10:00 -0000	[thread overview]
Message-ID: <87a7sfvfjv.fsf@redhat.com> (raw)
In-Reply-To: <20180523185719.22832-1-sergiodj@redhat.com> (Sergio Durigan	Junior's message of "Wed, 23 May 2018 14:57:19 -0400")

On Wednesday, May 23 2018, I wrote:

> This patch implements IPv6 support for both GDB and gdbserver.  Based
> on my research, it is the fourth attempt to do that since 2006.  Since
> I used ideas from all of the previous patches, I also added their
> authors's names on the ChangeLogs as a way to recognize their
> efforts.  For reference sake, you can find the previous attempts at:
>
>   https://sourceware.org/ml/gdb-patches/2006-09/msg00192.html
>
>   https://sourceware.org/ml/gdb-patches/2014-02/msg00248.html
>
>   https://sourceware.org/ml/gdb-patches/2016-02/msg00226.html

Ping.

> The basic idea behind the patch is to start using the new
> 'getaddrinfo'/'getnameinfo' calls, which are responsible for
> translating names and addresses in a protocol-independent way.  This
> means that if we ever have an IPv8, we won't need to change the code
> again.
>
> The function 'getaddrinfo' returns a linked list of possible addresses
> to connect to, so I modified ser-tcp.c:net_open's code to loop through
> the linked list and try all the addresses until it finds a valid one.
> The same rationale was used for gdbserver, but without the "retry"
> mechanism that GDB has.
>
> I also implemented some hostname parsing functions which are used to
> help GDB and gdbserver to parse hostname strings provided by the user.
> These new functions are living inside common/netstuff.[ch].  I've had
> to do that since IPv6 introduces a new URL scheme, which defines that
> square brackets can be used to enclose the host part and differentiate
> it from the port (e.g., "[::1]:1234" means "host ::1, port 1234").  I
> spent some time thinking about a reasonable way to interpret what the
> user wants, and I came up with the following:
>
> - If the user has provided a prefix that doesn't specify the protocol
>   version (i.e., "tcp:" or "udp:"), or if the user has not provided
>   any prefix, don't make any assumptions (i.e., assume AF_UNSPEC when
>   dealing with 'getaddrinfo') *unless* the host starts with "[" (in
>   which case, assume it's an IPv6 host).
>
> - If the user has provided a prefix that does specify the protocol
>   version (i.e., "tcp4:", "tcp6:", "udp4:" or "udp6:"), then respect
>   that.
>
> This method doesn't follow strictly what RFC 2732 proposes (that
> literal IPv6 addresses should be provided enclosed in "[" and "]")
> because IPv6 addresses still can be provided without square brackets
> in our case, but since we have prefixes to specify protocol versions I
> think this is not an issue.
>
> Another thing worth mentioning is the new 'GDB_TEST_IPV6' testcase
> parameter, which instructs GDB and gdbserver to use IPv6 for
> connections.  This way, if you want to run IPv6 tests, you do:
>
>   $ make check-gdb RUNTESTFLAGS='GDB_TEST_IPV6=1'
>
> This required a few changes on the gdbserver-base.exp,
> native-gdbserver.exp and native-extended-gdbserver.exp boards, and
> also a minimal adjustment on gdb.server/run-without-local-binary.exp.
>
> This patch has been regression-tested on BuildBot and locally, and
> also built using a x86_64-w64-mingw32 GCC, and no problems were found.
>
> gdb/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Paul Fertser  <fercerpav@gmail.com>
> 	    Tsutomu Seki  <sekiriki@gmail.com>
>
> 	* Makefile.in (COMMON_SFILES): Add 'common/netstuff.c'.
> 	(HFILES_NO_SRCDIR): Add 'common/netstuff.h'.
> 	* NEWS (Changes since GDB 8.1): Mention IPv6 support.
> 	* common/netstuff.c: New file.
> 	* common/netstuff.h: New file.
> 	* ser-tcp.c: Include 'netstuff.h' and 'wspiapi.h'.
> 	(net_open): Handle IPv6-style hostnames; implement support for
> 	IPv6 connections.
>
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Paul Fertser  <fercerpav@gmail.com>
> 	    Tsutomu Seki  <sekiriki@gmail.com>
>
> 	* Makefile.in (SFILES): Add '$(srcdir)/common/netstuff.c'.
> 	(OBS): Add 'common/netstuff.o'.
> 	* gdbreplay.c: Include 'wspiapi.h'.
> 	(remote_open): Implement support for IPv6
> 	connections.
> 	* remote-utils.c: Include 'netstuff.h', 'filestuff.h'
> 	and 'wspiapi.h'.
> 	(handle_accept_event): Accept connections from IPv6 sources.
> 	(remote_prepare): Handle IPv6-style hostnames; implement
> 	support for IPv6 connections.
> 	(remote_open): Implement support for printing connections from
> 	IPv6 sources.
>
> gdb/testsuite/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Paul Fertser  <fercerpav@gmail.com>
> 	    Tsutomu Seki  <sekiriki@gmail.com>
>
> 	* README (Testsuite Parameters): Mention new 'GDB_TEST_IPV6'
> 	parameter.
> 	* boards/gdbserver-base.exp (get_comm_port_localhost_ipv6):
> 	New procedure.
> 	* boards/native-extended-gdbserver.exp: Detect 'GDB_TEST_IPV6'
> 	and change board info accordingly.
> 	* boards/native-gdbserver.exp: Likewise.
> 	* gdb.server/run-without-local-binary.exp: Improve regexp used
> 	for detecting when a remote debugging connection succeeds.
>
> gdb/doc/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Paul Fertser  <fercerpav@gmail.com>
> 	    Tsutomu Seki  <sekiriki@gmail.com>
>
> 	* gdb.texinfo (Remote Connection Commands): Add explanation
> 	about new IPv6 support.  Add new connection prefixes.
> ---
>  gdb/Makefile.in                                    |   2 +
>  gdb/NEWS                                           |   4 +
>  gdb/common/netstuff.c                              | 136 +++++++++++++
>  gdb/common/netstuff.h                              |  52 +++++
>  gdb/doc/gdb.texinfo                                |  48 ++++-
>  gdb/gdbserver/Makefile.in                          |   2 +
>  gdb/gdbserver/gdbreplay.c                          | 181 +++++++++++++----
>  gdb/gdbserver/remote-utils.c                       | 119 +++++++----
>  gdb/ser-tcp.c                                      | 217 ++++++++++-----------
>  gdb/testsuite/README                               |   7 +
>  gdb/testsuite/boards/gdbserver-base.exp            |   5 +
>  gdb/testsuite/boards/native-extended-gdbserver.exp |   7 +-
>  gdb/testsuite/boards/native-gdbserver.exp          |   7 +-
>  .../gdb.server/run-without-local-binary.exp        |   2 +-
>  14 files changed, 602 insertions(+), 187 deletions(-)
>  create mode 100644 gdb/common/netstuff.c
>  create mode 100644 gdb/common/netstuff.h
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index df6ebab851..06ce12a4ee 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -962,6 +962,7 @@ COMMON_SFILES = \
>  	common/job-control.c \
>  	common/gdb_tilde_expand.c \
>  	common/gdb_vecs.c \
> +	common/netstuff.c \
>  	common/new-op.c \
>  	common/pathstuff.c \
>  	common/print-utils.c \
> @@ -1443,6 +1444,7 @@ HFILES_NO_SRCDIR = \
>  	common/gdb_vecs.h \
>  	common/gdb_wait.h \
>  	common/common-inferior.h \
> +	common/netstuff.h \
>  	common/host-defs.h \
>  	common/pathstuff.h \
>  	common/print-utils.h \
> diff --git a/gdb/NEWS b/gdb/NEWS
> index cef558039e..1f95ced912 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -3,6 +3,10 @@
>  
>  *** Changes since GDB 8.1
>  
> +* GDB and GDBserver now support IPv6 connections.  IPv6 hostnames
> +  can be passed using the '[ADDRESS]:PORT' notation, or the regular
> +  'ADDRESS:PORT' method.
> +
>  * The commands 'info variables/functions/types' now show the source line
>    numbers of symbol definitions when available.
>  
> diff --git a/gdb/common/netstuff.c b/gdb/common/netstuff.c
> new file mode 100644
> index 0000000000..cdf4b611db
> --- /dev/null
> +++ b/gdb/common/netstuff.c
> @@ -0,0 +1,136 @@
> +/* Operations on network stuff.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "common-defs.h"
> +#include "netstuff.h"
> +
> +#ifdef USE_WIN32API
> +#include <winsock2.h>
> +#include <wspiapi.h>
> +#else
> +#include <netinet/in.h>
> +#include <arpa/inet.h>
> +#include <netdb.h>
> +#include <sys/socket.h>
> +#include <netinet/tcp.h>
> +#endif
> +
> +/* See common/netstuff.h.  */
> +
> +scoped_free_addrinfo::scoped_free_addrinfo (struct addrinfo *a)
> +{
> +  m_res = a;
> +}
> +/* See common/netstuff.h.  */
> +
> +scoped_free_addrinfo::~scoped_free_addrinfo ()
> +{
> +  freeaddrinfo (m_res);
> +}
> +
> +/* See common/netstuff.h.  */
> +
> +void
> +parse_hostname_without_prefix (const char *hostname, std::string &host_str,
> +			       std::string &port_str, struct addrinfo *hint)
> +{
> +  std::string strname (hostname);
> +
> +  if (hint->ai_family != AF_INET && strname[0] == '[')
> +    {
> +      /* IPv6 addresses can be written as '[ADDR]:PORT', and we
> +	 support this notation.  */
> +      size_t close_bracket_pos = strname.find_first_of (']');
> +
> +      if (close_bracket_pos == std::string::npos)
> +	error (_("Missing close bracket in hostname '%s'"),
> +	       strname.c_str ());
> +
> +      /* Erase both '[' and ']'.  */
> +      strname.erase (0, 1);
> +      strname.erase (close_bracket_pos - 1, 1);
> +
> +      hint->ai_family = AF_INET6;
> +    }
> +
> +  /* The length of the hostname part.  */
> +  size_t host_len;
> +
> +  size_t last_colon_pos = strname.find_last_of (':');
> +
> +  if (last_colon_pos != std::string::npos)
> +    {
> +      /* The user has provided a port.  */
> +      host_len = last_colon_pos;
> +      port_str = strname.substr (last_colon_pos + 1);
> +    }
> +  else
> +    host_len = strname.size ();
> +
> +  host_str = strname.substr (0, host_len);
> +
> +  /* Default hostname is localhost.  */
> +  if (host_str.empty ())
> +    host_str = "localhost";
> +}
> +
> +/* See common/netstuff.h.  */
> +
> +void
> +parse_hostname (const char *hostname, std::string &host_str,
> +		std::string &port_str, struct addrinfo *hint)
> +{
> +  /* Struct to hold the association between valid prefixes, their
> +     family and socktype.  */
> +  struct host_prefix
> +    {
> +      /* The prefix.  */
> +      const char *prefix;
> +
> +      /* The 'ai_family'.  */
> +      int family;
> +
> +      /* The 'ai_socktype'.  */
> +      int socktype;
> +    };
> +  static const struct host_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 },
> +      { NULL, 0, 0 },
> +    };
> +
> +  for (const struct host_prefix *prefix = prefixes;
> +       prefix->prefix != NULL;
> +       ++prefix)
> +    if (startswith (hostname, prefix->prefix))
> +      {
> +	hostname += strlen (prefix->prefix);
> +	hint->ai_family = prefix->family;
> +	hint->ai_socktype = prefix->socktype;
> +	hint->ai_protocol
> +	  = hint->ai_socktype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
> +	break;
> +      }
> +
> +  parse_hostname_without_prefix (hostname, host_str, port_str, hint);
> +}
> diff --git a/gdb/common/netstuff.h b/gdb/common/netstuff.h
> new file mode 100644
> index 0000000000..1ac2433f11
> --- /dev/null
> +++ b/gdb/common/netstuff.h
> @@ -0,0 +1,52 @@
> +/* Operations on network stuff.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef NETSTUFF_H
> +#define NETSTUFF_H
> +
> +#include <string>
> +
> +/* Helper class to guarantee that we always call 'freeaddrinfo'.  */
> +
> +class scoped_free_addrinfo
> +{
> +public:
> +  scoped_free_addrinfo (struct addrinfo *a);
> +
> +  ~scoped_free_addrinfo ();
> +
> +  DISABLE_COPY_AND_ASSIGN (scoped_free_addrinfo);
> +
> +private:
> +  struct addrinfo *m_res;
> +};
> +
> +/* Parse HOSTNAME (which is a string in the of "ADDR:PORT") and fill
> +   in HOST_STR, PORT_STR and HINT accordingly.  */
> +extern void parse_hostname_without_prefix (const char *hostname,
> +					   std::string &host_str,
> +					   std::string &port_str,
> +					   struct addrinfo *hint);
> +
> +/* Parse HOSTNAME (which is a string in the form of
> +   "[tcp[6]:|udp[6]:]ADDR:PORT") and fill in HOST_STR, PORT_STR and
> +   HINT accordingly.  */
> +extern void parse_hostname (const char *hostname, std::string &host_str,
> +			    std::string &port_str, struct addrinfo *hint);
> +
> +#endif /* ! NETSTUFF_H */
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 28f083f96e..7994204140 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -20496,16 +20496,27 @@ If you're using a serial line, you may want to give @value{GDBN} the
>  @code{target} command.
>  
>  @item target remote @code{@var{host}:@var{port}}
> +@itemx target remote @code{@var{@r{[}host@r{]}}:@var{port}}
>  @itemx target remote @code{tcp:@var{host}:@var{port}}
> +@itemx target remote @code{tcp:@var{@r{[}host@r{]}}:@var{port}}
> +@itemx target remote @code{tcp4:@var{host}:@var{port}}
> +@itemx target remote @code{tcp6:@var{host}:@var{port}}
> +@itemx target remote @code{tcp6:@var{@r{[}host@r{]}}:@var{port}}
>  @itemx target extended-remote @code{@var{host}:@var{port}}
> +@itemx target extended-remote @code{@var{@r{[}host@r{]}}:@var{port}}
>  @itemx target extended-remote @code{tcp:@var{host}:@var{port}}
> +@itemx target extended-remote @code{tcp:@var{@r{[}host@r{]}}:@var{port}}
> +@itemx target extended-remote @code{tcp4:@var{host}:@var{port}}
> +@itemx target extended-remote @code{tcp6:@var{host}:@var{port}}
> +@itemx target extended-remote @code{tcp6:@var{@r{[}host@r{]}}:@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}
> -address; @var{port} must be a decimal number.  The @var{host} could be
> -the target machine itself, if it is directly connected to the net, or
> -it might be a terminal server which in turn has a serial line to the
> -target.
> +The @var{host} may be either a host name, a numeric @acronym{IPv4}
> +address, or a numeric @acronym{IPv6} address (with or without the
> +square brackets to separate the address from the port); @var{port}
> +must be a decimal number.  The @var{host} could be the target machine
> +itself, if it is directly connected to the net, or it might be a
> +terminal server which in turn has a serial line to the target.
>  
>  For example, to connect to port 2828 on a terminal server named
>  @code{manyfarms}:
> @@ -20514,6 +20525,24 @@ For example, to connect to port 2828 on a terminal server named
>  target remote manyfarms:2828
>  @end smallexample
>  
> +To connect to port 2828 on a terminal server whose address is
> +@code{2001::f8ff::67cf}, you can either use the square bracket syntax:
> +
> +@smallexample
> +target remote [2001::f8ff::67cf]:2828
> +@end smallexample
> +
> +Or explicitly specify the @acronym{IPv6} protocol:
> +
> +@smallexample
> +target remote tcp6:2001::f8ff::67cf:2828
> +@end smallexample
> +
> +This last example may be confusing to the reader, because there is no
> +visible separation between the hostname and the port number.
> +Therefore, we recommend the user to provide @acronym{IPv6} addresses
> +using square brackets for clarity.
> +
>  If your remote target is actually running on the same machine as your
>  debugger session (e.g.@: a simulator for your target running on the
>  same host), you can omit the hostname.  For example, to connect to
> @@ -20527,7 +20556,16 @@ target remote :1234
>  Note that the colon is still required here.
>  
>  @item target remote @code{udp:@var{host}:@var{port}}
> +@itemx target remote @code{udp:@var{host}:@var{port}}
> +@itemx target remote @code{udp:@var{@r{[}host@r{]}}:@var{port}}
> +@itemx target remote @code{udp4:@var{host}:@var{port}}
> +@itemx target remote @code{udp6:@var{@r{[}host@r{]}}:@var{port}}
> +@itemx target extended-remote @code{udp:@var{host}:@var{port}}
>  @itemx target extended-remote @code{udp:@var{host}:@var{port}}
> +@itemx target extended-remote @code{udp:@var{@r{[}host@r{]}}:@var{port}}
> +@itemx target extended-remote @code{udp4:@var{host}:@var{port}}
> +@itemx target extended-remote @code{udp6:@var{host}:@var{port}}
> +@itemx target extended-remote @code{udp6:@var{@r{[}host@r{]}}:@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}:
> diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
> index 675faa4364..d65346a357 100644
> --- a/gdb/gdbserver/Makefile.in
> +++ b/gdb/gdbserver/Makefile.in
> @@ -211,6 +211,7 @@ SFILES = \
>  	$(srcdir)/common/job-control.c \
>  	$(srcdir)/common/gdb_tilde_expand.c \
>  	$(srcdir)/common/gdb_vecs.c \
> +	$(srcdir)/common/netstuff.c \
>  	$(srcdir)/common/new-op.c \
>  	$(srcdir)/common/pathstuff.c \
>  	$(srcdir)/common/print-utils.c \
> @@ -253,6 +254,7 @@ OBS = \
>  	common/format.o \
>  	common/gdb_tilde_expand.o \
>  	common/gdb_vecs.o \
> +	common/netstuff.o \
>  	common/new-op.o \
>  	common/pathstuff.o \
>  	common/print-utils.o \
> diff --git a/gdb/gdbserver/gdbreplay.c b/gdb/gdbserver/gdbreplay.c
> index c1a639069a..01b70d49f4 100644
> --- a/gdb/gdbserver/gdbreplay.c
> +++ b/gdb/gdbserver/gdbreplay.c
> @@ -53,6 +53,7 @@
>  
>  #if USE_WIN32API
>  #include <winsock2.h>
> +#include <wspiapi.h>
>  #endif
>  
>  #ifndef HAVE_SOCKLEN_T
> @@ -175,56 +176,159 @@ remote_close (void)
>  static void
>  remote_open (char *name)
>  {
> -  if (!strchr (name, ':'))
> +  char *last_colon = strrchr (name, ':');
> +
> +  if (last_colon == NULL)
>      {
>        fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
>        fflush (stderr);
>        exit (1);
>      }
> -  else
> -    {
> +
>  #ifdef USE_WIN32API
> -      static int winsock_initialized;
> +  static int winsock_initialized;
>  #endif
> -      char *port_str;
> -      int port;
> -      struct sockaddr_in sockaddr;
> -      socklen_t tmp;
> -      int tmp_desc;
> +  char *port_str;
> +  int tmp;
> +  int tmp_desc;
> +  struct addrinfo hint;
> +  struct addrinfo *ainfo;
> +  char *orig_name = strdup (name);
> +
> +  struct prefix
> +  {
> +    /* The prefix to be parsed.  */
> +    const char *str;
> +
> +    /* The address family.  */
> +    int ai_family;
> +
> +    /* The socktype.  */
> +    int ai_socktype;
> +  };
> +  static 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 },
> +	{ NULL, 0, 0 } };
> +
> +  memset (&hint, 0, sizeof (hint));
> +  /* Assume no prefix will be passed, therefore we should use
> +     AF_UNSPEC.  */
> +  hint.ai_family = AF_UNSPEC;
> +  hint.ai_socktype = SOCK_STREAM;
> +  hint.ai_protocol = IPPROTO_TCP;
> +
> +  for (const struct prefix *p = prefixes; p->str != NULL; ++p)
> +    if (strncmp (name, p->str, strlen (p->str)) == 0)
> +      {
> +	name += strlen (p->str);
> +	hint.ai_family = p->ai_family;
> +	hint.ai_socktype = p->ai_socktype;
> +	hint.ai_protocol
> +	  = p->ai_socktype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
> +	break;
> +      }
>  
> -      port_str = strchr (name, ':');
> +  if (hint.ai_family != AF_INET && *name == '[')
> +    {
> +      ++name;
> +      port_str = strchr (name, ']');
> +      if (port_str == NULL)
> +	{
> +	  fprintf (stderr, "Missing closing bracket on hostname: %s\n",
> +		   orig_name);
> +	  exit (1);
> +	}
> +      /* Skip closing bracket.  */
> +      *port_str = '\0';
> +      ++port_str;
> +      if (*port_str != ':')
> +	{
> +	  fprintf (stderr, "Missing port number on hostname: %s\n",
> +		   orig_name);
> +	  exit (1);
> +	}
> +      hint.ai_family = AF_INET6;
> +    }
> +  else
> +    port_str = last_colon;
>  
> -      port = atoi (port_str + 1);
> +  /* Skip the colon.  */
> +  *port_str = '\0';
> +  ++port_str;
>  
>  #ifdef USE_WIN32API
> -      if (!winsock_initialized)
> -	{
> -	  WSADATA wsad;
> +  if (!winsock_initialized)
> +    {
> +      WSADATA wsad;
>  
> -	  WSAStartup (MAKEWORD (1, 0), &wsad);
> -	  winsock_initialized = 1;
> -	}
> +      WSAStartup (MAKEWORD (1, 0), &wsad);
> +      winsock_initialized = 1;
> +    }
>  #endif
>  
> -      tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
> -      if (tmp_desc == -1)
> -	perror_with_name ("Can't open socket");
> +  int r = getaddrinfo (name, port_str, &hint, &ainfo);
>  
> -      /* Allow rapid reuse of this port. */
> -      tmp = 1;
> -      setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
> -		  sizeof (tmp));
> +  if (r != 0)
> +    {
> +      fprintf (stderr, "%s:%s: cannot resolve name: %s\n",
> +	       name, port_str, gai_strerror (r));
> +      fflush (stderr);
> +      exit (1);
> +    }
>  
> -      sockaddr.sin_family = PF_INET;
> -      sockaddr.sin_port = htons (port);
> -      sockaddr.sin_addr.s_addr = INADDR_ANY;
> +  struct addrinfo *p;
>  
> -      if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
> -	  || listen (tmp_desc, 1))
> -	perror_with_name ("Can't bind address");
> +  for (p = ainfo; p != NULL; p = p->ai_next)
> +    {
> +      tmp_desc = socket (p->ai_family, p->ai_socktype, p->ai_protocol);
> +
> +      if (tmp_desc >= 0)
> +	break;
> +    }
> +
> +  if (p == NULL)
> +    perror_with_name ("Cannot open socket");
> +
> +  /* Allow rapid reuse of this port. */
> +  tmp = 1;
> +  setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
> +	      sizeof (tmp));
> +
> +  switch (p->ai_family)
> +    {
> +    case AF_INET:
> +      ((struct sockaddr_in *) p->ai_addr)->sin_addr.s_addr = INADDR_ANY;
> +      break;
> +    case AF_INET6:
> +      ((struct sockaddr_in6 *) p->ai_addr)->sin6_addr = in6addr_any;
> +      break;
> +    default:
> +      fprintf (stderr, "Invalid 'ai_family' %d\n", p->ai_family);
> +      exit (1);
> +    }
> +
> +  if (bind (tmp_desc, p->ai_addr, p->ai_addrlen) != 0)
> +    perror_with_name ("Can't bind address");
> +
> +  if (p->ai_socktype == SOCK_DGRAM)
> +    remote_desc = tmp_desc;
> +  else
> +    {
> +      struct sockaddr_storage sockaddr;
> +      socklen_t sockaddrsize = sizeof (sockaddr);
> +      char orig_host[64], orig_port[16];
> +
> +      if (listen (tmp_desc, 1) != 0)
> +	perror_with_name ("Can't listen on socket");
> +
> +      remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr,
> +			    &sockaddrsize);
>  
> -      tmp = sizeof (sockaddr);
> -      remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
>        if (remote_desc == -1)
>  	perror_with_name ("Accept failed");
>  
> @@ -239,6 +343,16 @@ remote_open (char *name)
>        setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
>  		  (char *) &tmp, sizeof (tmp));
>  
> +      if (getnameinfo ((struct sockaddr *) &sockaddr, sockaddrsize,
> +		       orig_host, sizeof (orig_host),
> +		       orig_port, sizeof (orig_port),
> +		       NI_NUMERICHOST | NI_NUMERICSERV) == 0)
> +	{
> +	  fprintf (stderr, "Remote debugging from host %s, port %s\n",
> +		   orig_host, orig_port);
> +	  fflush (stderr);
> +	}
> +
>  #ifndef USE_WIN32API
>        close (tmp_desc);		/* No longer need this */
>  
> @@ -254,8 +368,9 @@ remote_open (char *name)
>    fcntl (remote_desc, F_SETFL, FASYNC);
>  #endif
>  
> -  fprintf (stderr, "Replay logfile using %s\n", name);
> +  fprintf (stderr, "Replay logfile using %s\n", orig_name);
>    fflush (stderr);
> +  free (orig_name);
>  }
>  
>  static int
> diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
> index 3b5a459ae4..c8b5dcdbba 100644
> --- a/gdb/gdbserver/remote-utils.c
> +++ b/gdb/gdbserver/remote-utils.c
> @@ -26,6 +26,8 @@
>  #include "dll.h"
>  #include "rsp-low.h"
>  #include "gdbthread.h"
> +#include "netstuff.h"
> +#include "filestuff.h"
>  #include <ctype.h>
>  #if HAVE_SYS_IOCTL_H
>  #include <sys/ioctl.h>
> @@ -63,6 +65,7 @@
>  
>  #if USE_WIN32API
>  #include <winsock2.h>
> +#include <wspiapi.h>
>  #endif
>  
>  #if __QNX__
> @@ -156,19 +159,18 @@ enable_async_notification (int fd)
>  static int
>  handle_accept_event (int err, gdb_client_data client_data)
>  {
> -  struct sockaddr_in sockaddr;
> -  socklen_t tmp;
> +  struct sockaddr_storage sockaddr;
> +  socklen_t len = sizeof (sockaddr);
>  
>    if (debug_threads)
>      debug_printf ("handling possible accept event\n");
>  
> -  tmp = sizeof (sockaddr);
> -  remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &tmp);
> +  remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &len);
>    if (remote_desc == -1)
>      perror_with_name ("Accept failed");
>  
>    /* Enable TCP keep alive process. */
> -  tmp = 1;
> +  socklen_t tmp = 1;
>    setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE,
>  	      (char *) &tmp, sizeof (tmp));
>  
> @@ -197,8 +199,19 @@ handle_accept_event (int err, gdb_client_data client_data)
>    delete_file_handler (listen_desc);
>  
>    /* Convert IP address to string.  */
> -  fprintf (stderr, "Remote debugging from host %s\n",
> -	   inet_ntoa (sockaddr.sin_addr));
> +  char orig_host[64], orig_port[16];
> +
> +  int r = getnameinfo ((struct sockaddr *) &sockaddr, len,
> +		       orig_host, sizeof (orig_host),
> +		       orig_port, sizeof (orig_port),
> +		       NI_NUMERICHOST | NI_NUMERICSERV);
> +
> +  if (r != 0)
> +    fprintf (stderr, _("Could not obtain remote address: %s\n"),
> +	     gai_strerror (r));
> +  else
> +    fprintf (stderr, "Remote debugging from host %s, port %s\n", orig_host,
> +	     orig_port);
>  
>    enable_async_notification (remote_desc);
>  
> @@ -222,14 +235,10 @@ handle_accept_event (int err, gdb_client_data client_data)
>  void
>  remote_prepare (const char *name)
>  {
> -  const char *port_str;
>  #ifdef USE_WIN32API
>    static int winsock_initialized;
>  #endif
> -  int port;
> -  struct sockaddr_in sockaddr;
>    socklen_t tmp;
> -  char *port_end;
>  
>    remote_is_stdio = 0;
>    if (strcmp (name, STDIO_CONNECTION_NAME) == 0)
> @@ -242,17 +251,25 @@ remote_prepare (const char *name)
>        return;
>      }
>  
> -  port_str = strchr (name, ':');
> -  if (port_str == NULL)
> +  struct addrinfo hint;
> +  struct addrinfo *ainfo;
> +  std::string host_str, port_str;
> +
> +  memset (&hint, 0, sizeof (hint));
> +  /* Assume no prefix will be passed, therefore we should use
> +     AF_UNSPEC.  */
> +  hint.ai_family = AF_UNSPEC;
> +  hint.ai_socktype = SOCK_STREAM;
> +  hint.ai_protocol = IPPROTO_TCP;
> +
> +  parse_hostname_without_prefix (name, host_str, port_str, &hint);
> +
> +  if (port_str.empty ())
>      {
>        transport_is_reliable = 0;
>        return;
>      }
>  
> -  port = strtoul (port_str + 1, &port_end, 10);
> -  if (port_str[1] == '\0' || *port_end != '\0')
> -    error ("Bad port argument: %s", name);
> -
>  #ifdef USE_WIN32API
>    if (!winsock_initialized)
>      {
> @@ -263,8 +280,25 @@ remote_prepare (const char *name)
>      }
>  #endif
>  
> -  listen_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
> -  if (listen_desc == -1)
> +  int r = getaddrinfo (host_str.c_str (), port_str.c_str (), &hint, &ainfo);
> +
> +  if (r != 0)
> +    error (_("%s: cannot resolve name: %s"), name, gai_strerror (r));
> +
> +  scoped_free_addrinfo freeaddrinfo (ainfo);
> +
> +  struct addrinfo *iter;
> +
> +  for (iter = ainfo; iter != NULL; iter = iter->ai_next)
> +    {
> +      listen_desc = gdb_socket_cloexec (iter->ai_family, iter->ai_socktype,
> +					iter->ai_protocol);
> +
> +      if (listen_desc >= 0)
> +	break;
> +    }
> +
> +  if (iter == NULL)
>      perror_with_name ("Can't open socket");
>  
>    /* Allow rapid reuse of this port. */
> @@ -272,14 +306,25 @@ remote_prepare (const char *name)
>    setsockopt (listen_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;
> +  switch (iter->ai_family)
> +    {
> +    case AF_INET:
> +      ((struct sockaddr_in *) iter->ai_addr)->sin_addr.s_addr = INADDR_ANY;
> +      break;
> +    case AF_INET6:
> +      ((struct sockaddr_in6 *) iter->ai_addr)->sin6_addr = in6addr_any;
> +      break;
> +    default:
> +      internal_error (__FILE__, __LINE__,
> +		      _("Invalid 'ai_family' %d\n"), iter->ai_family);
> +    }
>  
> -  if (bind (listen_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
> -      || listen (listen_desc, 1))
> +  if (bind (listen_desc, iter->ai_addr, iter->ai_addrlen) != 0)
>      perror_with_name ("Can't bind address");
>  
> +  if (listen (listen_desc, 1) != 0)
> +    perror_with_name ("Can't listen on socket");
> +
>    transport_is_reliable = 1;
>  }
>  
> @@ -354,18 +399,24 @@ remote_open (const char *name)
>  #endif /* USE_WIN32API */
>    else
>      {
> -      int port;
> -      socklen_t len;
> -      struct sockaddr_in sockaddr;
> -
> -      len = sizeof (sockaddr);
> -      if (getsockname (listen_desc,
> -		       (struct sockaddr *) &sockaddr, &len) < 0
> -	  || len < sizeof (sockaddr))
> +      char listen_port[16];
> +      struct sockaddr_storage sockaddr;
> +      socklen_t len = sizeof (sockaddr);
> +
> +      if (getsockname (listen_desc, (struct sockaddr *) &sockaddr, &len) < 0)
>  	perror_with_name ("Can't determine port");
> -      port = ntohs (sockaddr.sin_port);
>  
> -      fprintf (stderr, "Listening on port %d\n", port);
> +      int r = getnameinfo ((struct sockaddr *) &sockaddr, len,
> +			   NULL, 0,
> +			   listen_port, sizeof (listen_port),
> +			   NI_NUMERICSERV);
> +
> +      if (r != 0)
> +	fprintf (stderr, _("Can't obtain port where we are listening: %s"),
> +		 gai_strerror (r));
> +      else
> +	fprintf (stderr, "Listening on port %s\n", listen_port);
> +
>        fflush (stderr);
>  
>        /* Register the event loop handler.  */
> diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
> index 23ef3b04b8..3d9fbd866f 100644
> --- a/gdb/ser-tcp.c
> +++ b/gdb/ser-tcp.c
> @@ -25,6 +25,7 @@
>  #include "cli/cli-decode.h"
>  #include "cli/cli-setshow.h"
>  #include "filestuff.h"
> +#include "netstuff.h"
>  
>  #include <sys/types.h>
>  
> @@ -39,6 +40,7 @@
>  
>  #ifdef USE_WIN32API
>  #include <winsock2.h>
> +#include <wspiapi.h>
>  #ifndef ETIMEDOUT
>  #define ETIMEDOUT WSAETIMEDOUT
>  #endif
> @@ -158,166 +160,157 @@ wait_for_connect (struct serial *scb, unsigned int *polls)
>  int
>  net_open (struct serial *scb, const char *name)
>  {
> -  char hostname[100];
> -  const char *port_str;
> -  int n, port, tmp;
> -  int use_udp;
> -  struct hostent *hostent;
> -  struct sockaddr_in sockaddr;
> +  int n;
> +  bool use_udp;
>  #ifdef USE_WIN32API
>    u_long ioarg;
>  #else
>    int ioarg;
>  #endif
>    unsigned int polls = 0;
> +  struct addrinfo hint;
> +  struct addrinfo *ainfo;
> +  std::string host_str, port_str;
>  
> -  use_udp = 0;
> -  if (startswith (name, "udp:"))
> -    {
> -      use_udp = 1;
> -      name = name + 4;
> -    }
> -  else if (startswith (name, "tcp:"))
> -    name = name + 4;
> -
> -  port_str = strchr (name, ':');
> +  memset (&hint, 0, sizeof (hint));
> +  /* Assume no prefix will be passed, therefore we should use
> +     AF_UNSPEC.  */
> +  hint.ai_family = AF_INET;
> +  hint.ai_socktype = SOCK_STREAM;
> +  hint.ai_protocol = IPPROTO_TCP;
>  
> -  if (!port_str)
> -    error (_("net_open: No colon in host name!"));  /* Shouldn't ever
> -						       happen.  */
> +  parse_hostname (name, host_str, port_str, &hint);
>  
> -  tmp = std::min (port_str - name, (ptrdiff_t) sizeof hostname - 1);
> -  strncpy (hostname, name, tmp);	/* Don't want colon.  */
> -  hostname[tmp] = '\000';	/* Tie off host name.  */
> -  port = atoi (port_str + 1);
> +  if (port_str.empty ())
> +    error (_("Missing port on hostname '%s'"), name);
>  
> -  /* Default hostname is localhost.  */
> -  if (!hostname[0])
> -    strcpy (hostname, "localhost");
> +  int r = getaddrinfo (host_str.c_str (), port_str.c_str (), &hint, &ainfo);
>  
> -  hostent = gethostbyname (hostname);
> -  if (!hostent)
> +  if (r != 0)
>      {
> -      fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
> +      fprintf_unfiltered (gdb_stderr, _("%s: cannot resolve name: %s\n"),
> +			  name, gai_strerror (r));
>        errno = ENOENT;
>        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));
> +  scoped_free_addrinfo free_ainfo (ainfo);
>  
> - retry:
> +  struct addrinfo *cur_ainfo;
>  
> -  if (use_udp)
> -    scb->fd = gdb_socket_cloexec (PF_INET, SOCK_DGRAM, 0);
> -  else
> -    scb->fd = gdb_socket_cloexec (PF_INET, SOCK_STREAM, 0);
> +  for (cur_ainfo = ainfo; cur_ainfo != NULL; cur_ainfo = cur_ainfo->ai_next)
> +    {
> +retry:
> +      scb->fd = gdb_socket_cloexec (cur_ainfo->ai_family,
> +				    cur_ainfo->ai_socktype,
> +				    cur_ainfo->ai_protocol);
>  
> -  if (scb->fd == -1)
> -    return -1;
> -  
> -  /* Set socket nonblocking.  */
> -  ioarg = 1;
> -  ioctl (scb->fd, FIONBIO, &ioarg);
> +      if (scb->fd < 0)
> +	continue;
>  
> -  /* Use Non-blocking connect.  connect() will return 0 if connected
> -     already.  */
> -  n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
> +      /* Set socket nonblocking.  */
> +      ioarg = 1;
> +      ioctl (scb->fd, FIONBIO, &ioarg);
>  
> -  if (n < 0)
> -    {
> +      /* Use Non-blocking connect.  connect() will return 0 if connected
> +	 already.  */
> +      n = connect (scb->fd, cur_ainfo->ai_addr, cur_ainfo->ai_addrlen);
> +
> +      if (n < 0)
> +	{
>  #ifdef USE_WIN32API
> -      int err = WSAGetLastError();
> +	  int err = WSAGetLastError();
>  #else
> -      int err = errno;
> +	  int err = errno;
>  #endif
>  
> -      /* Maybe we're waiting for the remote target to become ready to
> -	 accept connections.  */
> -      if (tcp_auto_retry
> +	  /* Maybe we're waiting for the remote target to become ready to
> +	     accept connections.  */
> +	  if (tcp_auto_retry
>  #ifdef USE_WIN32API
> -	  && err == WSAECONNREFUSED
> +	      && err == WSAECONNREFUSED
>  #else
> -	  && err == ECONNREFUSED
> +	      && err == ECONNREFUSED
>  #endif
> -	  && wait_for_connect (NULL, &polls) >= 0)
> -	{
> -	  close (scb->fd);
> -	  goto retry;
> -	}
> +	      && wait_for_connect (NULL, &polls) >= 0)
> +	    {
> +	      close (scb->fd);
> +	      goto retry;
> +	    }
>  
> -      if (
> +	  if (
>  #ifdef USE_WIN32API
> -	  /* Under Windows, calling "connect" with a non-blocking socket
> -	     results in WSAEWOULDBLOCK, not WSAEINPROGRESS.  */
> -	  err != WSAEWOULDBLOCK
> +	      /* Under Windows, calling "connect" with a non-blocking socket
> +		 results in WSAEWOULDBLOCK, not WSAEINPROGRESS.  */
> +	      err != WSAEWOULDBLOCK
>  #else
> -	  err != EINPROGRESS
> +	      err != EINPROGRESS
>  #endif
> -	  )
> -	{
> -	  errno = err;
> -	  net_close (scb);
> -	  return -1;
> +	      )
> +	    {
> +	      errno = err;
> +	      continue;
> +	    }
> +
> +	  /* Looks like we need to wait for the connect.  */
> +	  do 
> +	    {
> +	      n = wait_for_connect (scb, &polls);
> +	    } 
> +	  while (n == 0);
> +	  if (n < 0)
> +	    continue;
>  	}
>  
> -      /* Looks like we need to wait for the connect.  */
> -      do 
> -	{
> -	  n = wait_for_connect (scb, &polls);
> -	} 
> -      while (n == 0);
> -      if (n < 0)
> -	{
> -	  net_close (scb);
> -	  return -1;
> -	}
> -    }
> -
> -  /* Got something.  Is it an error?  */
> -  {
> -    int res, err;
> -    socklen_t len;
> -
> -    len = sizeof (err);
> -    /* On Windows, the fourth parameter to getsockopt is a "char *";
> -       on UNIX systems it is generally "void *".  The cast to "char *"
> -       is OK everywhere, since in C++ any data pointer type can be
> -       implicitly converted to "void *".  */
> -    res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (char *) &err, &len);
> -    if (res < 0 || err)
> +      /* Got something.  Is it an error?  */
>        {
> -	/* Maybe the target still isn't ready to accept the connection.  */
> -	if (tcp_auto_retry
> +	int res, err;
> +	socklen_t len = sizeof (err);
> +
> +	/* On Windows, the fourth parameter to getsockopt is a "char *";
> +	   on UNIX systems it is generally "void *".  The cast to "char *"
> +	   is OK everywhere, since in C++ any data pointer type can be
> +	   implicitly converted to "void *".  */
> +	res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (char *) &err, &len);
> +	if (res < 0 || err)
> +	  {
> +	    /* Maybe the target still isn't ready to accept the connection.  */
> +	    if (tcp_auto_retry
>  #ifdef USE_WIN32API
> -	    && err == WSAECONNREFUSED
> +		&& err == WSAECONNREFUSED
>  #else
> -	    && err == ECONNREFUSED
> +		&& err == ECONNREFUSED
>  #endif
> -	    && wait_for_connect (NULL, &polls) >= 0)
> -	  {
> -	    close (scb->fd);
> -	    goto retry;
> +		&& wait_for_connect (NULL, &polls) >= 0)
> +	      {
> +		close (scb->fd);
> +		goto retry;
> +	      }
> +	    if (err)
> +	      errno = err;
> +	    continue;
>  	  }
> -	if (err)
> -	  errno = err;
> -	net_close (scb);
> -	return -1;
>        }
> -  } 
> +      break;
> +    }
> +
> +  if (cur_ainfo == NULL)
> +    {
> +      net_close (scb);
> +      return -1;
> +    }
>  
>    /* Turn off nonblocking.  */
>    ioarg = 0;
>    ioctl (scb->fd, FIONBIO, &ioarg);
>  
> -  if (use_udp == 0)
> +  if (cur_ainfo->ai_socktype == IPPROTO_TCP)
>      {
>        /* Disable Nagle algorithm.  Needed in some cases.  */
> -      tmp = 1;
> +      int tmp = 1;
> +
>        setsockopt (scb->fd, IPPROTO_TCP, TCP_NODELAY,
> -		  (char *)&tmp, sizeof (tmp));
> +		  (char *) &tmp, sizeof (tmp));
>      }
>  
>  #ifdef SIGPIPE
> diff --git a/gdb/testsuite/README b/gdb/testsuite/README
> index 4475ac21a9..37f676d252 100644
> --- a/gdb/testsuite/README
> +++ b/gdb/testsuite/README
> @@ -259,6 +259,13 @@ This make (not runtest) variable is used to specify whether the
>  testsuite preloads the read1.so library into expect.  Any non-empty
>  value means true.  See "Race detection" below.
>  
> +GDB_TEST_IPV6
> +
> +This variable makes the tests related to GDBserver to run with IPv6
> +local addresses, instead of IPv4.  This is useful to test the IPv6
> +support, and only makes sense for the native-gdbserver and the
> +native-extended-gdbserver boards.
> +
>  Race detection
>  **************
>  
> diff --git a/gdb/testsuite/boards/gdbserver-base.exp b/gdb/testsuite/boards/gdbserver-base.exp
> index 52ad698b3f..f738c90e8e 100644
> --- a/gdb/testsuite/boards/gdbserver-base.exp
> +++ b/gdb/testsuite/boards/gdbserver-base.exp
> @@ -32,3 +32,8 @@ set_board_info gdb,nofileio 1
>  set_board_info gdb,predefined_tsv "\\\$trace_timestamp"
>  
>  set GDBFLAGS "${GDBFLAGS} -ex \"set auto-connect-native-target off\""
> +
> +# Helper function that returns a local IPv6 address to connect to.
> +proc get_comm_port_localhost_ipv6 { port } {
> +    return "\\\[::1\\\]:${port}"
> +}
> diff --git a/gdb/testsuite/boards/native-extended-gdbserver.exp b/gdb/testsuite/boards/native-extended-gdbserver.exp
> index df949994fd..9ec053c9d6 100644
> --- a/gdb/testsuite/boards/native-extended-gdbserver.exp
> +++ b/gdb/testsuite/boards/native-extended-gdbserver.exp
> @@ -24,7 +24,12 @@ load_generic_config "extended-gdbserver"
>  load_board_description "gdbserver-base"
>  load_board_description "local-board"
>  
> -set_board_info sockethost "localhost:"
> +if { [info exists GDB_TEST_IPV6] } {
> +    set_board_info sockethost "tcp6:\[::1\]:"
> +    set_board_info gdbserver,get_comm_port get_comm_port_localhost_ipv6
> +} else {
> +    set_board_info sockethost "localhost:"
> +}
>  
>  # We will be using the extended GDB remote protocol.
>  set_board_info gdb_protocol "extended-remote"
> diff --git a/gdb/testsuite/boards/native-gdbserver.exp b/gdb/testsuite/boards/native-gdbserver.exp
> index ef9316007e..d491aa451a 100644
> --- a/gdb/testsuite/boards/native-gdbserver.exp
> +++ b/gdb/testsuite/boards/native-gdbserver.exp
> @@ -30,7 +30,12 @@ set_board_info gdb,do_reload_on_run 1
>  # There's no support for argument-passing (yet).
>  set_board_info noargs 1
>  
> -set_board_info sockethost "localhost:"
> +if { [info exists GDB_TEST_IPV6] } {
> +    set_board_info sockethost "tcp6:\[::1\]:"
> +    set_board_info gdbserver,get_comm_port get_comm_port_localhost_ipv6
> +} else {
> +    set_board_info sockethost "localhost:"
> +}
>  set_board_info use_gdb_stub 1
>  set_board_info exit_is_reliable 1
>  
> diff --git a/gdb/testsuite/gdb.server/run-without-local-binary.exp b/gdb/testsuite/gdb.server/run-without-local-binary.exp
> index 1665ca9912..6ba3e711d9 100644
> --- a/gdb/testsuite/gdb.server/run-without-local-binary.exp
> +++ b/gdb/testsuite/gdb.server/run-without-local-binary.exp
> @@ -53,7 +53,7 @@ save_vars { GDBFLAGS } {
>      set use_gdb_stub 0
>  
>      gdb_test "target ${gdbserver_protocol} ${gdbserver_gdbport}" \
> -	"Remote debugging using $gdbserver_gdbport" \
> +	"Remote debugging using [string_to_regexp $gdbserver_gdbport]" \
>  	"connect to gdbserver"
>  
>      gdb_test "run" \
> -- 
> 2.14.3

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/

  parent reply	other threads:[~2018-05-31 18:35 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-23 21:48 Sergio Durigan Junior
2018-05-23 23:40 ` Eli Zaretskii
2018-05-24  0:41   ` Sergio Durigan Junior
2018-05-24 16:54     ` Eli Zaretskii
2018-05-25  1:57       ` Sergio Durigan Junior
2018-05-31 20:10 ` Sergio Durigan Junior [this message]
2018-06-06 12:26 ` Pedro Alves
2018-06-08  1:13   ` Sergio Durigan Junior
2018-06-08 13:53     ` Pedro Alves
2018-06-08 17:47       ` Sergio Durigan Junior
2018-06-08 18:44         ` Pedro Alves
2018-06-08 19:28           ` Pedro Alves
2018-06-08 19:51             ` Pedro Alves
2018-06-08 20:43               ` Sergio Durigan Junior
2018-06-08 21:21           ` Sergio Durigan Junior
2018-06-08 21:51             ` Pedro Alves
2018-06-08 22:01               ` Sergio Durigan Junior
2018-06-15  0:25 ` [PATCH v2] " Sergio Durigan Junior
2018-06-15  7:12   ` Eli Zaretskii
2018-06-20 15:24   ` Pedro Alves
2018-06-21  4:54     ` Sergio Durigan Junior
2018-07-07 20:47 ` [PATCH v3] " Sergio Durigan Junior
2018-07-11 12:55   ` Pedro Alves
2018-07-11 19:13     ` Sergio Durigan Junior
2018-07-11 19:16 ` [PATCH v4] " Sergio Durigan Junior
2018-07-11 21:48   ` Pedro Alves
2018-07-11 23:43     ` Sergio Durigan Junior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87a7sfvfjv.fsf@redhat.com \
    --to=sergiodj@redhat.com \
    --cc=eliz@gnu.org \
    --cc=fercerpav@gmail.com \
    --cc=gdb-patches@sourceware.org \
    --cc=jan.kratochvil@redhat.com \
    --cc=palves@redhat.com \
    --cc=sekiriki@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).