[21/23] Add "info connections" command, "info inferiors" connection number/string

Message ID 20190906232807.6191-22-palves@redhat.com
State New, archived
Headers

Commit Message

Pedro Alves Sept. 6, 2019, 11:28 p.m. UTC
  This commit extends the CLI a bit for multi-target, in three ways.

#1 - New "info connections" command.

This is a new command that lists the open connections (process_stratum
targets).  For example, if you're debugging two remote connections, a
couple local/native processes, and a core dump, all at the same time,
you might see something like this:

 (gdb) info connections
   Num  Name                     Description
   1    remote 192.168.0.1:9999  Remote serial target in gdb-specific protocol
   2    remote 192.168.0.2:9998  Remote serial target in gdb-specific protocol
 * 3    native                   Native process
   4    core                     Local core dump file

#2 - New "info inferiors" "Connection" column

You'll also see a new matching "Connection" column in "info
inferiors", showing you which connection an inferior is bound to:

 (gdb) info inferiors
   Num  Description       Connection                   Executable
   1    process 18526     1 (remote 192.168.0.1:9999)  target:/tmp/a.out
   2    process 18531     2 (remote 192.168.0.2:9998)  target:/tmp/a.out
   3    process 19115     3 (native)                   /tmp/prog1
   4    process 6286      4 (core)                     myprogram
 * 5    process 19122     3 (native)                   /bin/hello

#3 - Makes "add-inferior" show the inferior's target connection

"add-inferior" now shows you the connection you've just bound the
inferior to, which is the current process_stratum target:

 (gdb) add-inferior
 [New inferior 2]
 Added inferior 2 on connection 1 (extended-remote localhost:2346)

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* Makefile.in (COMMON_SFILES): Add target-connection.c.
	* inferior.c (uiout_field_connection): New function.
	(print_inferior): Add new "connection-id" column.
	(add_inferior_command): Show connection number/string of added
	inferior.
	* process-stratum-target.h
	(process_stratum_target::connection_string): New virtual method.
	(process_stratum_target::connection_number): New field.
	* remote.c (remote_target::connection_string): New override.
	* target-connection.c: New file.
	* target-connection.h: New file.
	* target.c (decref_target): Remove process_stratum targets from
	the connection list.
	(target_stack::push): Add process_stratum targets to the
	connection list.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* gdb.base/kill-detach-inferiors-cmd.exp: Adjust expected output
	of "add-inferior".
	* gdb.base/quit-live.exp: Likewise.
	* gdb.base/remote-exec-file.exp: Likewise.
	* gdb.guile/scm-progspace.exp: Likewise.
	* gdb.linespec/linespec.exp: Likewise.
	* gdb.mi/new-ui-mi-sync.exp: Likewise.
	* gdb.mi/user-selected-context-sync.exp: Likewise.
	* gdb.multi/multi-target.exp (setup): Add "info connection" and
	"info inferiors" tests.
	* gdb.multi/remove-inferiors.exp: Adjust expected output of
	"add-inferior".
	* gdb.multi/watchpoint-multi.exp: Likewise.
	* gdb.python/py-inferior.exp: Likewise.
	* gdb.server/extended-remote-restart.exp: Likewise.
	* gdb.threads/fork-plus-threads.exp: Adjust expected output of
	"info inferiors".
	* gdb.threads/forking-threads-plus-breakpoint.exp: Likewise.
	* gdb.trace/report.exp: Likewise.
---
 gdb/Makefile.in                                    |   1 +
 gdb/inferior.c                                     |  56 +++++++-
 gdb/process-stratum-target.h                       |  13 ++
 gdb/remote.c                                       |  13 ++
 gdb/target-connection.c                            | 156 +++++++++++++++++++++
 gdb/target-connection.h                            |  32 +++++
 gdb/target.c                                       |  10 +-
 .../gdb.base/kill-detach-inferiors-cmd.exp         |   4 +-
 gdb/testsuite/gdb.base/quit-live.exp               |   2 +-
 gdb/testsuite/gdb.base/remote-exec-file.exp        |   2 +-
 gdb/testsuite/gdb.guile/scm-progspace.exp          |   2 +-
 gdb/testsuite/gdb.linespec/linespec.exp            |   2 +-
 gdb/testsuite/gdb.mi/new-ui-mi-sync.exp            |   2 +-
 .../gdb.mi/user-selected-context-sync.exp          |   2 +-
 gdb/testsuite/gdb.multi/multi-target.exp           |  28 +++-
 gdb/testsuite/gdb.multi/remove-inferiors.exp       |   2 +-
 gdb/testsuite/gdb.multi/watchpoint-multi.exp       |   2 +-
 gdb/testsuite/gdb.python/py-inferior.exp           |   4 +-
 .../gdb.server/extended-remote-restart.exp         |  18 ++-
 gdb/testsuite/gdb.threads/fork-plus-threads.exp    |   2 +-
 .../forking-threads-plus-breakpoint.exp            |   2 +-
 gdb/testsuite/gdb.trace/report.exp                 |   2 +-
 22 files changed, 329 insertions(+), 28 deletions(-)
 create mode 100644 gdb/target-connection.c
 create mode 100644 gdb/target-connection.h
  

Comments

Tom Tromey Sept. 9, 2019, 8:18 p.m. UTC | #1
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> This commit extends the CLI a bit for multi-target, in three ways.
Pedro> #1 - New "info connections" command.

This looks good to me.  Just one question below.

FWIW I'm fine with the names you chose.

Pedro> +  uiout->table_header (name_len + 1, ui_left, "name", "Name");

Why the "+ 1" here?

Tom
  
Pedro Alves Oct. 17, 2019, 2:21 a.m. UTC | #2
On 9/9/19 9:18 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> This commit extends the CLI a bit for multi-target, in three ways.
> Pedro> #1 - New "info connections" command.
> 
> This looks good to me.  Just one question below.
> 
> FWIW I'm fine with the names you chose.
> 
> Pedro> +  uiout->table_header (name_len + 1, ui_left, "name", "Name");
> 
> Why the "+ 1" here?

Without it, we get:

(gdb) info connections 
  Num  What         Description       
* 1    remote :9999 Remote serial target in gdb-specific protocol 

Since the "name" column can include spaces in the middle of its
string, it seemed to me that an extra space would make the separation
more obvious.  

With the extra space we get:

(gdb) info connections 
  Num  What          Description       
* 1    remote :9999  Remote serial target in gdb-specific protocol 

We don't do that in "info threads", for example, so maybe
that was misguided.

WDYT?  Keep the extra space or remove it?

I'll add a comment if we keep it.

Thanks,
Pedro Alves
  
Tom Tromey Oct. 17, 2019, 2:23 p.m. UTC | #3
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> (gdb) info connections 
Pedro>   Num  What          Description       
Pedro> * 1    remote :9999  Remote serial target in gdb-specific protocol 

Pedro> We don't do that in "info threads", for example, so maybe
Pedro> that was misguided.

Pedro> WDYT?  Keep the extra space or remove it?

Looks better with it, so keep IMO.

Tom
  

Patch

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index e7e26a44a0..4fa84fa16c 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1119,6 +1119,7 @@  COMMON_SFILES = \
 	symmisc.c \
 	symtab.c \
 	target.c \
+	target-connection.c \
 	target-dcache.c \
 	target-descriptions.c \
 	target-memory.c \
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 6f4f396453..96d38f865d 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -429,6 +429,31 @@  print_selected_inferior (struct ui_out *uiout)
 		  inf->num, inferior_pid_to_str (inf->pid).c_str (), filename);
 }
 
+/* Helper for print_inferior.  Returns the 'connection-id' string for
+   PROC_TARGET.  */
+
+static std::string
+uiout_field_connection (process_stratum_target *proc_target)
+{
+  if (proc_target == NULL)
+    {
+      return {};
+    }
+  else if (proc_target->connection_string () != NULL)
+    {
+      return string_printf ("%d (%s %s)",
+			    proc_target->connection_number,
+			    proc_target->shortname (),
+			    proc_target->connection_string ());
+    }
+  else
+    {
+      return string_printf ("%d (%s)",
+			    proc_target->connection_number,
+			    proc_target->shortname ());
+    }
+}
+
 /* Prints the list of inferiors and their details on UIOUT.  This is a
    version of 'info_inferior_command' suitable for use from MI.
 
@@ -440,6 +465,7 @@  static void
 print_inferior (struct ui_out *uiout, const char *requested_inferiors)
 {
   int inf_count = 0;
+  size_t connection_id_len = 20;
 
   /* Compute number of inferiors we will print.  */
   for (inferior *inf : all_inferiors ())
@@ -447,6 +473,10 @@  print_inferior (struct ui_out *uiout, const char *requested_inferiors)
       if (!number_is_in_list (requested_inferiors, inf->num))
 	continue;
 
+      std::string conn = uiout_field_connection (inf->process_target ());
+      if (connection_id_len < conn.size ())
+	connection_id_len = conn.size ();
+
       ++inf_count;
     }
 
@@ -456,10 +486,12 @@  print_inferior (struct ui_out *uiout, const char *requested_inferiors)
       return;
     }
 
-  ui_out_emit_table table_emitter (uiout, 4, inf_count, "inferiors");
+  ui_out_emit_table table_emitter (uiout, 5, inf_count, "inferiors");
   uiout->table_header (1, ui_left, "current", "");
   uiout->table_header (4, ui_left, "number", "Num");
   uiout->table_header (17, ui_left, "target-id", "Description");
+  uiout->table_header (connection_id_len, ui_left,
+		       "connection-id", "Connection");
   uiout->table_header (17, ui_left, "exec", "Executable");
 
   uiout->table_body ();
@@ -479,6 +511,9 @@  print_inferior (struct ui_out *uiout, const char *requested_inferiors)
 
       uiout->field_string ("target-id", inferior_pid_to_str (inf->pid));
 
+      std::string conn = uiout_field_connection (inf->process_target ());
+      uiout->field_string ("connection-id", conn.c_str ());
+
       if (inf->pspace->pspace_exec_filename != NULL)
 	uiout->field_string ("exec", inf->pspace->pspace_exec_filename);
       else
@@ -713,9 +748,22 @@  switch_to_inferior_and_push_target (inferior *new_inf,
 
   /* Reuse the target for new inferior.  */
   if (!no_connection && proc_target != NULL)
-    push_target (proc_target);
-
-  printf_filtered (_("Added inferior %d\n"), new_inf->num);
+    {
+      push_target (proc_target);
+      if (proc_target->connection_string () != NULL)
+	printf_filtered (_("Added inferior %d on connection %d (%s %s)\n"),
+			 new_inf->num,
+			 proc_target->connection_number,
+			 proc_target->shortname (),
+			 proc_target->connection_string ());
+      else
+	printf_filtered (_("Added inferior %d on connection %d (%s)\n"),
+			 new_inf->num,
+			 proc_target->connection_number,
+			 proc_target->shortname ());
+    }
+  else
+    printf_filtered (_("Added inferior %d\n"), new_inf->num);
 }
 
 /* add-inferior [-copies N] [-exec FILENAME] [-no-connection] */
diff --git a/gdb/process-stratum-target.h b/gdb/process-stratum-target.h
index 6081c0a927..53e1c6a618 100644
--- a/gdb/process-stratum-target.h
+++ b/gdb/process-stratum-target.h
@@ -31,6 +31,16 @@  public:
 
   strata stratum () const final override { return process_stratum; }
 
+  /* Return a string representation of this target's open connection.
+     This string is used to distinguish different instances of a given
+     target type.  For example, when remote debugging, the target is
+     called "remote", but since we may have more than one remote
+     target open, connection_string() returns the connection serial
+     connection name, e.g., "localhost:10001", "192.168.0.1:20000",
+     etc.  This string is shown in several places, e.g., in "info
+     connections" and "info inferiors".  */
+  virtual const char *connection_string () { return nullptr; }
+
   /* We must default these because they must be implemented by any
      target that can run.  */
   bool can_async_p () override { return false; }
@@ -58,6 +68,9 @@  public:
      stop events for all known threads, because any of those threads
      may have spawned new threads we haven't heard of yet.  */
   bool threads_executing = false;
+
+  /* The connection number.  Visible in "info connections".  */
+  int connection_number = 0;
 };
 
 /* Downcast TARGET to process_stratum_target.  */
diff --git a/gdb/remote.c b/gdb/remote.c
index 168fff3047..ff75204ee8 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -404,6 +404,8 @@  public:
   const target_info &info () const override
   { return remote_target_info; }
 
+  const char *connection_string () override;
+
   thread_control_capabilities get_thread_control_capabilities () override
   { return tc_schedlock; }
 
@@ -4860,6 +4862,17 @@  remote_target::start_remote (int from_tty, int extended_p)
     insert_breakpoints ();
 }
 
+const char *
+remote_target::connection_string ()
+{
+  remote_state *rs = get_remote_state ();
+
+  if (rs->remote_desc->name != NULL)
+    return rs->remote_desc->name;
+  else
+    return NULL;
+}
+
 /* Open a connection to a remote debugger.
    NAME is the filename used for communication.  */
 
diff --git a/gdb/target-connection.c b/gdb/target-connection.c
new file mode 100644
index 0000000000..f13e649977
--- /dev/null
+++ b/gdb/target-connection.c
@@ -0,0 +1,156 @@ 
+/* List of target connections for GDB.
+
+   Copyright (C) 2017-2019 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 "defs.h"
+#include "target-connection.h"
+
+#include <map>
+
+#include "inferior.h"
+#include "target.h"
+
+/* A map between connection number and representative process_stratum
+   target.  */
+static std::map<int, process_stratum_target *> process_targets;
+
+/* The highest connection number ever given to a target.  */
+static int highest_target_connection_num;
+
+/* See target-connection.h.  */
+
+void
+connection_list_add (process_stratum_target *t)
+{
+  if (t->connection_number == 0)
+    {
+      t->connection_number = ++highest_target_connection_num;
+      process_targets[t->connection_number] = t;
+    }
+}
+
+/* See target-connection.h.  */
+
+void
+connection_list_remove (process_stratum_target *t)
+{
+  process_targets.erase (t->connection_number);
+  t->connection_number = 0;
+}
+
+/* Make a target connection string for T.  This is usually T's
+   shortname, but it includes the result of
+   process_stratum_target::connection_string() too if T supports
+   it.  */
+
+static std::string
+make_target_connection_string (process_stratum_target *t)
+{
+  if (t->connection_string () != NULL)
+    return string_printf ("%s %s", t->shortname (),
+			  t->connection_string ());
+  else
+    return t->shortname ();
+}
+
+/* Prints the list of target connections and their details on UIOUT.
+
+   If REQUESTED_CONNECTIONS is not NULL, it's a list of GDB ids of the
+   target connections that should be printed.  Otherwise, all target
+   connections are printed.  */
+
+static void
+print_connection (struct ui_out *uiout, const char *requested_connections)
+{
+  int count = 0;
+  size_t name_len = 0;
+
+  /* Compute number of lines we will print.  */
+  for (const auto &it : process_targets)
+    {
+      if (!number_is_in_list (requested_connections, it.first))
+	continue;
+
+      ++count;
+
+      process_stratum_target *t = it.second;
+
+      size_t l = strlen (t->shortname ());
+      if (t->connection_string () != NULL)
+	l += 1 + strlen (t->connection_string ());
+
+      if (l > name_len)
+	name_len = l;
+    }
+
+  if (count == 0)
+    {
+      uiout->message (_("No connections.\n"));
+      return;
+    }
+
+  ui_out_emit_table table_emitter (uiout, 4, process_targets.size (),
+				   "connections");
+
+  uiout->table_header (1, ui_left, "current", "");
+  uiout->table_header (4, ui_left, "number", "Num");
+  uiout->table_header (name_len + 1, ui_left, "name", "Name");
+  uiout->table_header (17, ui_left, "description", "Description");
+
+  uiout->table_body ();
+
+  for (const auto &it : process_targets)
+    {
+      process_stratum_target *t = it.second;
+
+      if (!number_is_in_list (requested_connections, t->connection_number))
+	continue;
+
+      ui_out_emit_tuple tuple_emitter (uiout, NULL);
+
+      if (current_inferior ()->process_target () == t)
+	uiout->field_string ("current", "*");
+      else
+	uiout->field_skip ("current");
+
+      uiout->field_signed ("number", t->connection_number);
+
+      uiout->field_string ("name", make_target_connection_string (t).c_str ());
+
+      uiout->field_string ("description", t->longname ());
+
+      uiout->text ("\n");
+    }
+}
+
+/* The "info connections" command.  */
+
+static void
+info_connections_command (const char *args, int from_tty)
+{
+  print_connection (current_uiout, args);
+}
+
+void
+_initialize_target_connection ()
+{
+  add_info ("connections", info_connections_command,
+	    _("\
+Names of target connections being debugged.\n\
+Shows the list of targets currently in use as well as their description."));
+}
diff --git a/gdb/target-connection.h b/gdb/target-connection.h
new file mode 100644
index 0000000000..0e2dc128d8
--- /dev/null
+++ b/gdb/target-connection.h
@@ -0,0 +1,32 @@ 
+/* List of target connections for GDB.
+
+   Copyright (C) 2017-2019 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 TARGET_CONNECTION_H
+#define TARGET_CONNECTION_H
+
+struct process_stratum_target;
+
+/* Add a process target to the connection list, if not already
+   added.  */
+void connection_list_add (process_stratum_target *t);
+
+/* Remove a process target from the connection list.  */
+void connection_list_remove (process_stratum_target *t);
+
+#endif /* TARGET_CONNECTION_H */
diff --git a/gdb/target.c b/gdb/target.c
index 541b95bc10..ba01148d7a 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -49,6 +49,7 @@ 
 #include "gdbsupport/byte-vector.h"
 #include "terminal.h"
 #include <unordered_map>
+#include "target-connection.h"
 
 static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
@@ -561,7 +562,11 @@  decref_target (target_ops *t)
 {
   t->decref ();
   if (t->refcount () == 0)
-    target_close (t);
+    {
+      if (t->stratum () == process_stratum)
+	connection_list_remove (as_process_stratum_target (t));
+      target_close (t);
+    }
 }
 
 /* See target.h.  */
@@ -573,6 +578,9 @@  target_stack::push (target_ops *t)
 
   strata stratum = t->stratum ();
 
+  if (stratum == process_stratum)
+    connection_list_add (as_process_stratum_target (t));
+
   /* If there's already a target at this stratum, remove it.  */
 
   if (m_stack[stratum] != NULL)
diff --git a/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp b/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp
index 63045cb504..bd50a60c7f 100644
--- a/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp
+++ b/gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp
@@ -32,7 +32,7 @@  if [prepare_for_testing "failed to prepare" $executable] {
 runto_main
 
 # Add another forked inferior process.
-gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
+gdb_test "add-inferior" "Added inferior 2 on target .*" "add inferior 2"
 gdb_test "inferior 2" "Switching to inferior 2.*"
 gdb_test "file $binfile" "Reading symbols from .*" "load binary"
 gdb_test "start" "Temporary breakpoint.*Starting program.*"
@@ -40,7 +40,7 @@  gdb_test "start" "Temporary breakpoint.*Starting program.*"
 # Add an attached inferior process.
 set test_spawn_id [spawn_wait_for_attach $binfile]
 set test_pid [spawn_id_get_pid $test_spawn_id]
-gdb_test "add-inferior" "Added inferior 3" "add inferior 3"
+gdb_test "add-inferior" "Added inferior 3 on connection .*" "add inferior 3"
 gdb_test "inferior 3" "Switching to inferior 3.*"
 gdb_test "attach $test_pid" "Attaching to process.*" "attach to pid"
 
diff --git a/gdb/testsuite/gdb.base/quit-live.exp b/gdb/testsuite/gdb.base/quit-live.exp
index c0eba44d43..7b23a9c013 100644
--- a/gdb/testsuite/gdb.base/quit-live.exp
+++ b/gdb/testsuite/gdb.base/quit-live.exp
@@ -120,7 +120,7 @@  proc quit_with_live_inferior {appear_how extra_inferior quit_how} {
     }
 
     if {$extra_inferior} {
-	gdb_test "add-inferior" "Added inferior 2*" \
+	gdb_test "add-inferior" "Added inferior 2 on connection .*" \
 	    "add empty inferior 2"
 	gdb_test "inferior 2" "Switching to inferior 2.*" \
 	    "switch to inferior 2"
diff --git a/gdb/testsuite/gdb.base/remote-exec-file.exp b/gdb/testsuite/gdb.base/remote-exec-file.exp
index 3db009b830..6af8afcc5a 100644
--- a/gdb/testsuite/gdb.base/remote-exec-file.exp
+++ b/gdb/testsuite/gdb.base/remote-exec-file.exp
@@ -27,7 +27,7 @@  with_test_prefix "set inf 1" {
 
 # Set remote exec-file in inferior 2.
 with_test_prefix "set inf 2" {
-    gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
+    gdb_test "add-inferior" "Added inferior 2.*" "add inferior 2"
     gdb_test "inferior 2" "Switching to inferior 2.*"
     gdb_test_no_output "set remote exec-file prog2"
 }
diff --git a/gdb/testsuite/gdb.guile/scm-progspace.exp b/gdb/testsuite/gdb.guile/scm-progspace.exp
index cb8384f83d..19520943c0 100644
--- a/gdb/testsuite/gdb.guile/scm-progspace.exp
+++ b/gdb/testsuite/gdb.guile/scm-progspace.exp
@@ -73,7 +73,7 @@  with_test_prefix "program unloaded" {
 # deleted.  We need to, for example, delete an inferior to get the progspace
 # to go away.
 
-gdb_test "add-inferior" "Added inferior 2" "create new inferior"
+gdb_test "add-inferior" "Added inferior 2.*" "create new inferior"
 gdb_test "inferior 2" ".*" "switch to new inferior"
 gdb_test_no_output "remove-inferiors 1" "remove first inferior"
 
diff --git a/gdb/testsuite/gdb.linespec/linespec.exp b/gdb/testsuite/gdb.linespec/linespec.exp
index 45982ddeff..08be8f606f 100644
--- a/gdb/testsuite/gdb.linespec/linespec.exp
+++ b/gdb/testsuite/gdb.linespec/linespec.exp
@@ -201,7 +201,7 @@  gdb_test "break lspec.h:$line" \
 # Multi-inferior tests.
 #
 
-gdb_test "add-inferior" "Added inferior 2" \
+gdb_test "add-inferior" "Added inferior 2.*" \
     "add inferior for linespec tests"
 
 gdb_test "inferior 2" "Switching to inferior 2 .*" \
diff --git a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
index 5560a8be96..7eb4fb3716 100644
--- a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
+++ b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
@@ -83,7 +83,7 @@  proc do_test {sync_command} {
     # in the separate MI UI.  Note the "run" variant usually triggers
     # =thread-group-started/=thread-created/=library-loaded as well.
     with_spawn_id $gdb_main_spawn_id {
-	gdb_test "add-inferior" "Added inferior 2"
+	gdb_test "add-inferior" "Added inferior 2 on connection .*"
     }
 
     # Interrupt the program.
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index 621b4c5163..19dd4c9493 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -415,7 +415,7 @@  proc_with_prefix test_setup { mode } {
 	# Add the second inferior now.  While this is not mandatory, it allows
 	# us to assume that per-inferior thread numbering will be used,
 	# simplifying test_continue_to_start a bit (Thread 1.2 and not Thread 2).
-	gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
+	gdb_test "add-inferior" "Added inferior 2 on connection .*" "add inferior 2"
 
 	# Prepare the first inferior for the test.
 	test_continue_to_start $mode 1
diff --git a/gdb/testsuite/gdb.multi/multi-target.exp b/gdb/testsuite/gdb.multi/multi-target.exp
index 3b71e7446b..78a43d8c2e 100644
--- a/gdb/testsuite/gdb.multi/multi-target.exp
+++ b/gdb/testsuite/gdb.multi/multi-target.exp
@@ -137,8 +137,34 @@  proc setup {non-stop} {
 	return 0
     }
 
+    set ws "\[ \t\]+"
+    global decimal
+
+    # Test "info connections" and "info inferior"'s "Connection"
+    # column, while at it.
+
+    gdb_test "info connections" \
+	[multi_line \
+	     "Num${ws}Name${ws}Description${ws}" \
+	     "  1${ws}native${ws}Native process${ws}" \
+	     "  2${ws}extended-remote localhost:$decimal${ws}Extended remote serial target in gdb-specific protocol${ws}" \
+	     "  3${ws}core${ws}Local core dump file${ws}" \
+	     "  4${ws}extended-remote localhost:$decimal${ws}Extended remote serial target in gdb-specific protocol${ws}" \
+	   "\\* 5${ws}core${ws}Local core dump file${ws}" \
+	    ]
+
+    gdb_test "info inferiors" \
+	[multi_line \
+	     "Num${ws}Description${ws}Connection${ws}Executable${ws}" \
+	     "  1${ws}process ${decimal}${ws}1 \\(native\\)${ws}${binfile}${ws}" \
+	     "  2${ws}process ${decimal}${ws}2 \\(extended-remote localhost:$decimal\\)${ws}${binfile}${ws}" \
+	     "  3${ws}process ${decimal}${ws}3 \\(core\\)${ws}${binfile}${ws}" \
+	     "  4${ws}process ${decimal}${ws}1 \\(native\\)${ws}${binfile}${ws}" \
+	     "  5${ws}process ${decimal}${ws}4 \\(extended-remote localhost:$decimal\\)${ws}${binfile}${ws}" \
+	   "\\* 6${ws}process ${decimal}${ws}5 \\(core\\)${ws}${binfile}${ws}" \
+	    ]
+
     # For debugging.
-    gdb_test "info inferiors" ".*"
     gdb_test "info threads" ".*"
 
     # Make "continue" resume all inferiors.
diff --git a/gdb/testsuite/gdb.multi/remove-inferiors.exp b/gdb/testsuite/gdb.multi/remove-inferiors.exp
index 18f6c90225..ef3def7b5b 100644
--- a/gdb/testsuite/gdb.multi/remove-inferiors.exp
+++ b/gdb/testsuite/gdb.multi/remove-inferiors.exp
@@ -26,7 +26,7 @@  proc switch_to_inferior { num message } {
 }
 
 proc add_inferior { expected_num message } {
-    gdb_test "add-inferior" "Added inferior ${expected_num}" "${message}"
+    gdb_test "add-inferior" "Added inferior ${expected_num}( on connection .*)?" "${message}"
 }
 
 proc test_remove_inferiors { } {
diff --git a/gdb/testsuite/gdb.multi/watchpoint-multi.exp b/gdb/testsuite/gdb.multi/watchpoint-multi.exp
index b0f47db374..f3f9ca58fc 100644
--- a/gdb/testsuite/gdb.multi/watchpoint-multi.exp
+++ b/gdb/testsuite/gdb.multi/watchpoint-multi.exp
@@ -53,7 +53,7 @@  if [support_displaced_stepping] {
 gdb_breakpoint main {temporary}
 gdb_test "run" "Temporary breakpoint.* main .*" "start to main inferior 1"
 
-gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
+gdb_test "add-inferior" "Added inferior 2 on connection .*" "add inferior 2"
 gdb_test "inferior 2" "witching to inferior 2 .*" "switch to inferior 2, first time"
 gdb_load $binfile
 
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
index 72ec1f2186..a4839c83d6 100644
--- a/gdb/testsuite/gdb.python/py-inferior.exp
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -279,7 +279,7 @@  with_test_prefix "selected_inferior" {
     gdb_test "inferior 1" ".*" "switch to first inferior"
     gdb_test "py print (gdb.selected_inferior().num)" "1" "first inferior selected"
 
-    gdb_test "add-inferior" "Added inferior 3" "create new inferior"
+    gdb_test "add-inferior" "Added inferior 3 on connection .*" "create new inferior"
     gdb_test "inferior 3" ".*" "switch to third inferior"
     gdb_test "py print (gdb.selected_inferior().num)" "3" "third inferior selected"
     gdb_test "inferior 1" ".*" "switch back to first inferior"
@@ -288,7 +288,7 @@  with_test_prefix "selected_inferior" {
 
 # Test repr()/str()
 with_test_prefix "__repr__" {
-    gdb_test "add-inferior" "Added inferior 4" "add inferior 4"
+    gdb_test "add-inferior" "Added inferior 4 on connection .*" "add inferior 4"
     gdb_py_test_silent_cmd "python infs = gdb.inferiors()" "get inferior list" 1
     gdb_test "python print (infs\[0\])" "<gdb.Inferior num=1, pid=$decimal>"
     gdb_test "python print (infs)" \
diff --git a/gdb/testsuite/gdb.server/extended-remote-restart.exp b/gdb/testsuite/gdb.server/extended-remote-restart.exp
index c78342c010..c1010a9358 100644
--- a/gdb/testsuite/gdb.server/extended-remote-restart.exp
+++ b/gdb/testsuite/gdb.server/extended-remote-restart.exp
@@ -88,12 +88,16 @@  proc test_reload { do_kill_p follow_child_p } {
     gdb_breakpoint "breakpt"
     gdb_continue_to_breakpoint "breakpt"
 
-    # Check we have the expected inferiors.
+    set ws "\[ \t\]+"
+    set any_re "\[^\r\n\]+"
+    set connection_re $any_re
+    set executable_re $any_re
+
     gdb_test "info inferiors" \
 	[multi_line \
-	     "  Num  Description       Executable.*" \
-	     "${parent_prefix} 1 +${live_inf_ptn} \[^\r\n\]+" \
-	     "${child_prefix} 2 +${live_inf_ptn} \[^\r\n\]+" ] \
+	     "  Num${ws}Description${ws}Connection${ws}Executable${ws}" \
+	     "${parent_prefix} 1${ws}${live_inf_ptn}${ws}${connection_re}${executable_re}" \
+	     "${child_prefix} 2${ws}${live_inf_ptn}${ws}${connection_re}${executable_re}" ] \
 	"Check inferiors at breakpoint"
 
     if { $do_kill_p } {
@@ -107,9 +111,9 @@  proc test_reload { do_kill_p follow_child_p } {
 	# Check the first inferior really did die.
 	gdb_test "info inferiors" \
 	    [multi_line \
-		 "  Num  Description       Executable.*" \
-		 "${parent_prefix} 1 +${parent_inf_after_kill_ptn} \[^\r\n\]+" \
-		 "${child_prefix} 2 +${child_inf_after_kill_ptn} \[^\r\n\]+" ] \
+		 "  Num${ws}Description${ws}Connection${ws}Executable${ws}" \
+		 "${parent_prefix} 1${ws}${parent_inf_after_kill_ptn}${ws}${connection_re}${executable_re}" \
+		 "${child_prefix} 2${ws}${child_inf_after_kill_ptn}${ws}${connection_re}${executable_re}" ] \
 	    "Check inferior was killed"
     }
 
diff --git a/gdb/testsuite/gdb.threads/fork-plus-threads.exp b/gdb/testsuite/gdb.threads/fork-plus-threads.exp
index 340a8df266..d488bb9d39 100644
--- a/gdb/testsuite/gdb.threads/fork-plus-threads.exp
+++ b/gdb/testsuite/gdb.threads/fork-plus-threads.exp
@@ -109,7 +109,7 @@  proc do_test { detach_on_fork } {
 	"no threads left"
 
     gdb_test "info inferiors" \
-	"Num\[ \t\]+Description\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
+	"Num\[ \t\]+Description\[ \t\]+Connection\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
 	"only inferior 1 left"
 }
 
diff --git a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
index 1d1378234e..6d24af401b 100644
--- a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
+++ b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
@@ -142,7 +142,7 @@  proc do_test { cond_bp_target detach_on_fork displaced } {
 	"no threads left"
 
     gdb_test "info inferiors" \
-	"Num\[ \t\]+Description\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
+	"Num\[ \t\]+Description\[ \t\]+Connection\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
 	"only inferior 1 left"
 }
 
diff --git a/gdb/testsuite/gdb.trace/report.exp b/gdb/testsuite/gdb.trace/report.exp
index c847ab0c5b..2949f1bb0d 100644
--- a/gdb/testsuite/gdb.trace/report.exp
+++ b/gdb/testsuite/gdb.trace/report.exp
@@ -391,7 +391,7 @@  proc use_collected_data { data_source } {
 	# There is always a thread of an inferior, either a live one or
 	# a faked one.
 	gdb_test "info threads" "\\* ${decimal}    (process|Thread) \[0-9\.\]+\[ \t\].*"
-	gdb_test "info inferiors" "\\* 1    process ${decimal} \[ \t\]+${binfile}.*"
+	gdb_test "info inferiors" "\\* 1    process ${decimal} \[ \t\]+\[^\r\n\]*\[ \t\]+${binfile}.*"
     }
 }