public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 4/7] Remove linux_proc_pid_get_ns
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
@ 2015-04-16 12:19 ` Gary Benson
  2015-04-17  4:36   ` Doug Evans
  2015-04-16 12:20 ` [PATCH 1/7] Move make_cleanup_close to common code Gary Benson
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-16 12:19 UTC (permalink / raw)
  To: gdb-patches

This commit removes linux_proc_pid_get_ns, and updates its only
use to use linux_ns_same instead.

gdb/ChangeLog:

	* linux-thread-db.c (nat/linux-namespaces.h): New include.
	(check_pid_namespace_match): Use linux_ns_same rather than
	linux_proc_pid_get_ns to spot PID namespace mismatches.
	* nat/linux-procfs.h (linux_proc_pid_get_ns): Remove.
	* nat/linux-procfs.c (linux_proc_pid_get_ns): Likewise.
---
 gdb/ChangeLog          |    8 ++++++++
 gdb/linux-thread-db.c  |   13 +++----------
 gdb/nat/linux-procfs.c |   19 -------------------
 gdb/nat/linux-procfs.h |    6 ------
 4 files changed, 11 insertions(+), 35 deletions(-)

diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 886d8ac..74db74d 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -42,9 +42,9 @@
 #include "nat/linux-osdata.h"
 #include "auto-load.h"
 #include "cli/cli-utils.h"
-
 #include <signal.h>
 #include <ctype.h>
+#include "nat/linux-namespaces.h"
 
 /* GNU/Linux libthread_db support.
 
@@ -1211,20 +1211,13 @@ check_pid_namespace_match (void)
 	 child's thread list, we'll mistakenly think it has no threads
 	 since the thread PID fields won't match the PID we give to
 	 libthread_db.  */
-      char *our_pid_ns = linux_proc_pid_get_ns (getpid (), "pid");
-      char *inferior_pid_ns = linux_proc_pid_get_ns (
-	ptid_get_pid (inferior_ptid), "pid");
-
-      if (our_pid_ns != NULL && inferior_pid_ns != NULL
-	  && strcmp (our_pid_ns, inferior_pid_ns) != 0)
+      if (!linux_ns_same (getpid (), ptid_get_pid (inferior_ptid),
+			  LINUX_NS_PID))
 	{
 	  warning (_ ("Target and debugger are in different PID "
 		      "namespaces; thread lists and other data are "
 		      "likely unreliable"));
 	}
-
-      xfree (our_pid_ns);
-      xfree (inferior_pid_ns);
     }
 }
 
diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c
index 44364c5..24bcb01 100644
--- a/gdb/nat/linux-procfs.c
+++ b/gdb/nat/linux-procfs.c
@@ -185,25 +185,6 @@ linux_proc_pid_is_zombie (pid_t pid)
   return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
 }
 
-/* See linux-procfs.h declaration.  */
-
-char *
-linux_proc_pid_get_ns (pid_t pid, const char *ns)
-{
-  char buf[100];
-  char nsval[64];
-  int ret;
-  xsnprintf (buf, sizeof (buf), "/proc/%d/ns/%s", (int) pid, ns);
-  ret = readlink (buf, nsval, sizeof (nsval));
-  if (0 < ret && ret < sizeof (nsval))
-    {
-      nsval[ret] = '\0';
-      return xstrdup (nsval);
-    }
-
-  return NULL;
-}
-
 /* See linux-procfs.h.  */
 
 void
diff --git a/gdb/nat/linux-procfs.h b/gdb/nat/linux-procfs.h
index fdbf383..f9cad39 100644
--- a/gdb/nat/linux-procfs.h
+++ b/gdb/nat/linux-procfs.h
@@ -54,12 +54,6 @@ extern int linux_proc_pid_is_zombie_nowarn (pid_t pid);
 
 extern int linux_proc_pid_is_gone (pid_t pid);
 
-/* Return an opaque string identifying PID's NS namespace or NULL if
- * the information is unavailable.  The returned string must be
- * released with xfree.  */
-
-extern char *linux_proc_pid_get_ns (pid_t pid, const char *ns);
-
 /* Callback function for linux_proc_attach_tgid_threads.  If the PTID
    thread is not yet known, try to attach to it and return true,
    otherwise return false.  */
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 0/7] GNU/Linux mount namespace support
@ 2015-04-16 12:19 Gary Benson
  2015-04-16 12:19 ` [PATCH 4/7] Remove linux_proc_pid_get_ns Gary Benson
                   ` (18 more replies)
  0 siblings, 19 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-16 12:19 UTC (permalink / raw)
  To: gdb-patches

Hi all,

This series allows GDB and gdbserver on GNU/Linux systems to attach
to processes in mount namespaces other than the debugger's own when
invoked with the appropriate permissions.  This allows an application
running in a container to be debugged by running GDB or gdbserver on
the host, or by running GDB or gdbserver from within another container
that shares the host's PID namespace.

This series builds on the 'Do not require "file" commands for remote
targets' series that is currently under review:

  https://sourceware.org/ml/gdb-patches/2015-04/msg00015.html

It also requires the 'Do not manipulate "target:" filenames as local
paths' patch to function correctly:

  https://sourceware.org/ml/gdb-patches/2015-04/msg00547.html

A tree with the latest versions of all these patches applied is
available here:

  https://github.com/gbenson/binutils-gdb/tree/namespaces

The patches in this series are as follows:

 - Patch 1 (Move make_cleanup_close to common code) is a minor
   refactoring required for patch 3.

 - Patch 2 (Introduce target_fileio_set_fs) adds target-layer
   support for systems where different processes can have different
   views of the filesystem.  The new function target_fileio_set_fs
   sets the context in which target_filesystem_is_local and the
   other target_fileio_* functions operate, and can be called to
   select the filesystem of a specific inferior or the filesystem
   of the debugger (GDB or gdbserver).  The default implementation
   of target_fileio_set_fs does nothing, which means that targets
   where inferiors and the debugger share the same filesystem will
   work without modification.

 - Patch 3 (Introduce nat/linux-namespaces.[ch]) introduces some
   shared code that GDB and gdbserver can use to query and enter
   Linux namespaces.

 - GDB contained a small amount of namespace-aware code used to
   display a warning.  Patch 4 (Remove linux_proc_pid_get_ns)
   replaces the querying part of this code with a call to the
   new code introduced by patch 3.

 - Patch 5 (Implement multiple-filesystem support for Linux targets)
   does exactly what it says on the tin.  With this patch you can
   attach to processes in containers using the native Linux target
   using, e.g., "gdb -p PID".

 - Patch 6 (Implement multiple-filesystem support for remote targets)
   adds remote protocol support for remote targets where different
   processes can have different views of the filesystem.  A new
   vFile:setfs packet is introduced that passes the context set using
   target_fileio_set_fs to the remote target.  Caching is used to
   avoid sending unnecessary vFile:setfs packets.

 - Patch 7 (Implement vFile:setfs in gdbserver) implements the
   vFile:setfs packet in gdbserver.  Currently only GNU/Linux systems
   support this; gdbserver on other systems will return empty
   responses in reply to vFile:setfs packets.

Built and regtested on RHEL 6.6 x86_64.

Ok to commit?

Thanks,
Gary

--
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 1/7] Move make_cleanup_close to common code
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
  2015-04-16 12:19 ` [PATCH 4/7] Remove linux_proc_pid_get_ns Gary Benson
@ 2015-04-16 12:20 ` Gary Benson
  2015-04-17  2:47   ` Doug Evans
  2015-04-16 12:20 ` [PATCH 2/7] Introduce target_fileio_set_fs Gary Benson
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-16 12:20 UTC (permalink / raw)
  To: gdb-patches

This commit moves the function make_cleanup_close from gdb/utils.[ch]
to gdb/common/cleanup-utils.[ch] to make it usable from common code.
A new file was created over putting the function in common-utils.[ch]
to avoid having to build cleanups.c into the in-process agent.

gdb/ChangeLog:

	* common/cleanup-utils.h: New file.
	* common/cleanup-utils.c: Likewise.
	* Makefile.in (SFILES): Add common/cleanup-utils.c.
	(HFILES_NO_SRCDIR): Add common/cleanup-utils.h.
	(COMMON_OBS): Add cleanup-utils.o.
	(cleanup-utils.o): New rule.
	* common/common-utils.h (cleanup-utils.h): New include.
	* utils.h (make_cleanup_close): Moved to cleanup-utils.h.
	* utils.c (do_close_cleanup): Moved to cleanup-utils.c.
	(make_cleanup_close): Likewise.

gdb/gdbserver/ChangeLog:

	* Makefile.in (SFILES): Add common/cleanup-utils.c.
	(OBS): Add cleanup-utils.o.
	(cleanup-utils.o): New rule.
---
 gdb/ChangeLog              |   13 +++++++++++++
 gdb/Makefile.in            |   12 +++++++++---
 gdb/common/cleanup-utils.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 gdb/common/cleanup-utils.h |   31 +++++++++++++++++++++++++++++++
 gdb/common/common-utils.h  |    2 ++
 gdb/gdbserver/ChangeLog    |    6 ++++++
 gdb/gdbserver/Makefile.in  |    6 +++++-
 gdb/utils.c                |   17 -----------------
 gdb/utils.h                |    2 +-
 9 files changed, 109 insertions(+), 22 deletions(-)
 create mode 100644 gdb/common/cleanup-utils.c
 create mode 100644 gdb/common/cleanup-utils.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 95104ef..47b216a 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -888,7 +888,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	common/format.c common/filestuff.c btrace.c record-btrace.c ctf.c \
 	target/waitstatus.c common/print-utils.c common/rsp-low.c \
 	common/errors.c common/common-debug.c common/common-exceptions.c \
-	common/btrace-common.c common/fileio.c \
+	common/btrace-common.c common/fileio.c common/cleanup-utils.c \
 	$(SUBDIR_GCC_COMPILE_SRCS)
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -979,7 +979,8 @@ i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \
 common/common-debug.h common/cleanups.h common/gdb_setjmp.h \
 common/common-exceptions.h target/target.h common/symbol.h \
 common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
-common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h
+common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h \
+common/cleanup-utils.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1079,7 +1080,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
 	format.o registry.o btrace.o record-btrace.o waitstatus.o \
 	print-utils.o rsp-low.o errors.o common-debug.o debug.o \
-	common-exceptions.o btrace-common.o fileio.o \
+	common-exceptions.o btrace-common.o fileio.o cleanup-utils.o \
 	$(SUBDIR_GCC_COMPILE_OBS)
 
 TSOBS = inflow.o
@@ -2260,6 +2261,11 @@ btrace-common.o: ${srcdir}/common/btrace-common.c
 fileio.o: ${srcdir}/common/fileio.c
 	$(COMPILE) $(srcdir)/common/fileio.c
 	$(POSTCOMPILE)
+
+cleanup-utils.o: ${srcdir}/common/cleanup-utils.c
+	$(COMPILE) $(srcdir)/common/cleanup-utils.c
+	$(POSTCOMPILE)
+
 #
 # gdb/target/ dependencies
 #
diff --git a/gdb/common/cleanup-utils.c b/gdb/common/cleanup-utils.c
new file mode 100644
index 0000000..829d067
--- /dev/null
+++ b/gdb/common/cleanup-utils.c
@@ -0,0 +1,42 @@
+/* Cleanup utilities for GDB, the GNU debugger.
+
+   Copyright (C) 1986-2015 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 "cleanup-utils.h"
+
+/* Helper function which does the work for make_cleanup_close.  */
+
+static void
+do_close_cleanup (void *arg)
+{
+  int *fd = arg;
+
+  close (*fd);
+}
+
+/* See cleanup-utils.h.  */
+
+struct cleanup *
+make_cleanup_close (int fd)
+{
+  int *saved_fd = xmalloc (sizeof (fd));
+
+  *saved_fd = fd;
+  return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
+}
diff --git a/gdb/common/cleanup-utils.h b/gdb/common/cleanup-utils.h
new file mode 100644
index 0000000..c5a0d50
--- /dev/null
+++ b/gdb/common/cleanup-utils.h
@@ -0,0 +1,31 @@
+/* Cleanup utilities for GDB, the GNU debugger.
+
+   Copyright (C) 1986-2015 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/>.  */
+
+/* Cleanup utilities.  These are not declared in cleanups.h
+   (nor defined in cleanups.c) because, while they use the
+   cleanup API, they are not part of the cleanup API.  */
+
+#ifndef CLEANUP_UTILS_H
+#define CLEANUP_UTILS_H
+
+/* Return a new cleanup that closes FD.  */
+
+extern struct cleanup *make_cleanup_close (int fd);
+
+#endif /* CLEANUP_UTILS_H */
diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
index cd2665a..dc3ceea 100644
--- a/gdb/common/common-utils.h
+++ b/gdb/common/common-utils.h
@@ -20,6 +20,8 @@
 #ifndef COMMON_UTILS_H
 #define COMMON_UTILS_H
 
+#include "cleanup-utils.h"
+
 /* If possible, define FUNCTION_NAME, a macro containing the name of
    the function being defined.  Since this macro may not always be
    defined, all uses must be protected by appropriate macro definition
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index a981ee8..8ba88d4 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -180,7 +180,7 @@ SFILES=	$(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
 	$(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c \
 	$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c \
 	$(srcdir)/common/btrace-common.c \
-	$(srcdir)/common/fileio.c
+	$(srcdir)/common/fileio.c $(srcdir)/common/cleanup-utils.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -195,6 +195,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
       common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
       tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
       common-exceptions.o symbol.o btrace-common.o fileio.o \
+      cleanup-utils.o \
       $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
 GDBREPLAY_OBS = gdbreplay.o version.o
 GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -615,6 +616,9 @@ x86-linux.o: ../nat/x86-linux.c
 x86-linux-dregs.o: ../nat/x86-linux-dregs.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+cleanup-utils.o: ../common/cleanup-utils.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 
 aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c
diff --git a/gdb/utils.c b/gdb/utils.c
index a9350d9..46be4a5 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -191,23 +191,6 @@ make_cleanup_bfd_unref (bfd *abfd)
   return make_cleanup (do_bfd_close_cleanup, abfd);
 }
 
-static void
-do_close_cleanup (void *arg)
-{
-  int *fd = arg;
-
-  close (*fd);
-}
-
-struct cleanup *
-make_cleanup_close (int fd)
-{
-  int *saved_fd = xmalloc (sizeof (fd));
-
-  *saved_fd = fd;
-  return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
-}
-
 /* Helper function which does the work for make_cleanup_fclose.  */
 
 static void
diff --git a/gdb/utils.h b/gdb/utils.h
index b8e1aff..b8435da 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -80,7 +80,7 @@ struct section_addr_info;
 extern struct cleanup *(make_cleanup_free_section_addr_info 
                         (struct section_addr_info *));
 
-extern struct cleanup *make_cleanup_close (int fd);
+/* For make_cleanup_close see common/cleanup-utils.h.  */
 
 extern struct cleanup *make_cleanup_fclose (FILE *file);
 
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 2/7] Introduce target_fileio_set_fs
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
  2015-04-16 12:19 ` [PATCH 4/7] Remove linux_proc_pid_get_ns Gary Benson
  2015-04-16 12:20 ` [PATCH 1/7] Move make_cleanup_close to common code Gary Benson
@ 2015-04-16 12:20 ` Gary Benson
  2015-04-17  3:04   ` Doug Evans
  2015-04-16 12:27 ` [PATCH 6/7] Implement multiple-filesystem support for remote targets Gary Benson
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-16 12:20 UTC (permalink / raw)
  To: gdb-patches

This commit introduces a new target method target_fileio_set_fs
and adds calls to it in various places.  This allows support to
be added for targets where processes do not share a common
filesystem.

gdb/ChangeLog:

	* target.h (struct inferior): New forward declaration.
	(struct target_ops) <to_fileio_set_fs>: New field.
	(target_fileio_set_fs): New declaration.
	* target-delegates.c: Regenerate.
	* target.c (target_fileio_set_fs): New function.
	* exec.c (exec_file_attach): Call target_fileio_set_fs.
	* gdb_bfd.c (inferior.h): New include.
	(gdb_bfd_iovec_fileio_open): Rename argument.  Call
	target_fileio_set_fs.
	(gdb_bfd_open): Call target_fileio_set_fs.  Pass current
	inferior as argument to gdb_bfd_iovec_fileio_open.
	* linux-tdep.c (linux_info_proc): Call target_fileio_set_fs.
	(linux_find_memory_regions_full): Likewise.
	(linux_fill_prpsinfo): Likewise.
	* solib.c (solib_find_1): Likewise.
---
 gdb/ChangeLog          |   18 ++++++++++++++++++
 gdb/exec.c             |    2 ++
 gdb/gdb_bfd.c          |   10 ++++++++--
 gdb/linux-tdep.c       |    9 +++++++++
 gdb/solib.c            |    9 +++++++--
 gdb/target-delegates.c |   28 ++++++++++++++++++++++++++++
 gdb/target.c           |   23 +++++++++++++++++++++++
 gdb/target.h           |   23 +++++++++++++++++++++++
 8 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/gdb/exec.c b/gdb/exec.c
index 872b86c..e97793a 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -231,6 +231,8 @@ exec_file_attach (const char *filename, int from_tty)
 
       if (is_target_filename (filename))
 	{
+	  target_fileio_set_fs (current_inferior ());
+
 	  if (target_filesystem_is_local ())
 	    filename += strlen (TARGET_SYSROOT_PREFIX);
 	  else
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 3d5d23f..bdcf985 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -32,6 +32,7 @@
 #endif
 #include "target.h"
 #include "gdb/fileio.h"
+#include "inferior.h"
 
 typedef bfd *bfdp;
 DEF_VEC_P (bfdp);
@@ -213,7 +214,7 @@ fileio_errno_to_host (int errnum)
    OPEN_CLOSURE is unused.  */
 
 static void *
-gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)
+gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *inferior)
 {
   const char *filename = bfd_get_filename (abfd);
   int fd, target_errno;
@@ -221,6 +222,8 @@ gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)
 
   gdb_assert (is_target_filename (filename));
 
+  target_fileio_set_fs ((struct inferior *) inferior);
+
   fd = target_fileio_open (filename + strlen (TARGET_SYSROOT_PREFIX),
 			   FILEIO_O_RDONLY, 0,
 			   &target_errno);
@@ -322,12 +325,15 @@ gdb_bfd_open (const char *name, const char *target, int fd)
 
   if (is_target_filename (name))
     {
+      target_fileio_set_fs (current_inferior ());
+
       if (!target_filesystem_is_local ())
 	{
 	  gdb_assert (fd == -1);
 
 	  abfd = gdb_bfd_openr_iovec (name, target,
-				      gdb_bfd_iovec_fileio_open, NULL,
+				      gdb_bfd_iovec_fileio_open,
+				      current_inferior (),
 				      gdb_bfd_iovec_fileio_pread,
 				      gdb_bfd_iovec_fileio_close,
 				      gdb_bfd_iovec_fileio_fstat);
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 9d75b66..44b2970 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -715,6 +715,9 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
   if (args && args[0])
     error (_("Too many parameters: %s"), args);
 
+  /* Access /proc/ from our filesystem.  */
+  target_fileio_set_fs (NULL);
+
   printf_filtered (_("process %ld\n"), pid);
   if (cmdline_f)
     {
@@ -1130,6 +1133,9 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
 
   pid = current_inferior ()->pid;
 
+  /* Access /proc/ from our filesystem.  */
+  target_fileio_set_fs (NULL);
+
   if (use_coredump_filter)
     {
       xsnprintf (coredumpfilter_name, sizeof (coredumpfilter_name),
@@ -1752,6 +1758,9 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
 
   gdb_assert (p != NULL);
 
+  /* Access /proc/ from our filesystem.  */
+  target_fileio_set_fs (NULL);
+
   /* Obtaining PID and filename.  */
   pid = ptid_get_pid (inferior_ptid);
   xsnprintf (filename, sizeof (filename), "/proc/%d/cmdline", (int) pid);
diff --git a/gdb/solib.c b/gdb/solib.c
index 2466235..f1e694f 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -167,8 +167,13 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
 	 ensures that the same search algorithm is used for
 	 all local files regardless of whether a "target:"
 	 prefix was used.  */
-      if (is_target_filename (sysroot) && target_filesystem_is_local ())
-	sysroot += strlen (TARGET_SYSROOT_PREFIX);
+      if (is_target_filename (sysroot))
+	{
+	  target_fileio_set_fs (current_inferior ());
+
+	  if (target_filesystem_is_local ())
+	    sysroot += strlen (TARGET_SYSROOT_PREFIX);
+	}
 
       if (*sysroot == '\0')
 	sysroot = NULL;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 36eacbf..0c16f9e 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -2343,6 +2343,30 @@ debug_thread_address_space (struct target_ops *self, ptid_t arg1)
   return result;
 }
 
+static void
+delegate_fileio_set_fs (struct target_ops *self, int arg1)
+{
+  self = self->beneath;
+  self->to_fileio_set_fs (self, arg1);
+}
+
+static void
+tdefault_fileio_set_fs (struct target_ops *self, int arg1)
+{
+}
+
+static void
+debug_fileio_set_fs (struct target_ops *self, int arg1)
+{
+  fprintf_unfiltered (gdb_stdlog, "-> %s->to_fileio_set_fs (...)\n", debug_target.to_shortname);
+  debug_target.to_fileio_set_fs (&debug_target, arg1);
+  fprintf_unfiltered (gdb_stdlog, "<- %s->to_fileio_set_fs (", debug_target.to_shortname);
+  target_debug_print_struct_target_ops_p (&debug_target);
+  fputs_unfiltered (", ", gdb_stdlog);
+  target_debug_print_int (arg1);
+  fputs_unfiltered (")\n", gdb_stdlog);
+}
+
 static int
 delegate_filesystem_is_local (struct target_ops *self)
 {
@@ -4049,6 +4073,8 @@ install_delegators (struct target_ops *ops)
     ops->to_thread_architecture = delegate_thread_architecture;
   if (ops->to_thread_address_space == NULL)
     ops->to_thread_address_space = delegate_thread_address_space;
+  if (ops->to_fileio_set_fs == NULL)
+    ops->to_fileio_set_fs = delegate_fileio_set_fs;
   if (ops->to_filesystem_is_local == NULL)
     ops->to_filesystem_is_local = delegate_filesystem_is_local;
   if (ops->to_trace_init == NULL)
@@ -4254,6 +4280,7 @@ install_dummy_methods (struct target_ops *ops)
   ops->to_can_run_breakpoint_commands = tdefault_can_run_breakpoint_commands;
   ops->to_thread_architecture = default_thread_architecture;
   ops->to_thread_address_space = default_thread_address_space;
+  ops->to_fileio_set_fs = tdefault_fileio_set_fs;
   ops->to_filesystem_is_local = tdefault_filesystem_is_local;
   ops->to_trace_init = tdefault_trace_init;
   ops->to_download_tracepoint = tdefault_download_tracepoint;
@@ -4402,6 +4429,7 @@ init_debug_target (struct target_ops *ops)
   ops->to_can_run_breakpoint_commands = debug_can_run_breakpoint_commands;
   ops->to_thread_architecture = debug_thread_architecture;
   ops->to_thread_address_space = debug_thread_address_space;
+  ops->to_fileio_set_fs = debug_fileio_set_fs;
   ops->to_filesystem_is_local = debug_filesystem_is_local;
   ops->to_trace_init = debug_trace_init;
   ops->to_download_tracepoint = debug_download_tracepoint;
diff --git a/gdb/target.c b/gdb/target.c
index 306c21d..0b78512 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2684,6 +2684,29 @@ default_fileio_target (void)
     return find_default_run_target ("file I/O");
 }
 
+/* See target.h.  */
+
+void
+target_fileio_set_fs (struct inferior *inf)
+{
+  struct target_ops *t;
+  int pid = (inf == NULL || inf->fake_pid_p) ? 0 : inf->pid;
+
+  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+    {
+      if (t->to_fileio_set_fs != NULL)
+	{
+	  t->to_fileio_set_fs (t, pid);
+
+	  if (targetdebug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"target_fileio_set_fs (%d)\n", pid);
+
+	  break;
+	}
+    }
+}
+
 /* File handle for target file operations.  */
 
 typedef struct
diff --git a/gdb/target.h b/gdb/target.h
index 66bf91e..0472237 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -38,6 +38,7 @@ struct static_tracepoint_marker;
 struct traceframe_info;
 struct expression;
 struct dcache_struct;
+struct inferior;
 
 #include "infrun.h" /* For enum exec_direction_kind.  */
 
@@ -830,6 +831,15 @@ struct target_ops
 
     /* Target file operations.  */
 
+    /* Set the filesystem accessed by target_filesystem_is_local and
+       target_fileio_* methods that take FILENAME arguments to the
+       filesystem as seen by process PID on the target system.  If
+       PID is zero, set the filesystem to that seen by the GDB, or,
+       for remote targets, the remote stub.  See the comment on
+       target_fileio_set_fs for more details.  */
+    void (*to_fileio_set_fs) (struct target_ops *, int pid)
+      TARGET_DEFAULT_IGNORE ();
+
     /* Return nonzero if the filesystem accessed by the
        target_fileio_* methods is the local filesystem,
        zero otherwise.  */
@@ -1932,6 +1942,19 @@ extern int target_search_memory (CORE_ADDR start_addr,
 
 /* Target file operations.  */
 
+/* Set the filesystem accessed by target_filesystem_is_local and
+   target_fileio_* methods that take FILENAME arguments to the
+   filesystem as seen by INF iff INF is non-NULL and refers to
+   a running process with a non-faked PID.  Set the filesystem
+   to that seen by the debugger (GDB or the remote stub) in all
+   other cases.  All callers of target_filesystem_is_local and
+   target_fileio_* methods with FILENAME arguments should call
+   target_fileio_set_fs to ensure the correct filesystem is used.
+   File descriptors returned by target_fileio_open should continue
+   to reference the filesystem in which they were opened across
+   calls to target_fileio_set_fs.  */
+extern void target_fileio_set_fs (struct inferior *inf);
+
 /* Return nonzero if the filesystem accessed by the target_fileio_*
    methods is the local filesystem, zero otherwise.  */
 #define target_filesystem_is_local() \
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (2 preceding siblings ...)
  2015-04-16 12:20 ` [PATCH 2/7] Introduce target_fileio_set_fs Gary Benson
@ 2015-04-16 12:27 ` Gary Benson
  2015-04-16 15:12   ` Eli Zaretskii
                     ` (2 more replies)
  2015-04-16 12:34 ` [PATCH 3/7] Introduce nat/linux-namespaces.[ch] Gary Benson
                   ` (14 subsequent siblings)
  18 siblings, 3 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-16 12:27 UTC (permalink / raw)
  To: gdb-patches

This commit allows GDB to access executables and shared libraries
on remote targets where the inferior and the remote stub do not
share a common filesystem.  A new packet "vFile:setfs" is added
to the remote protocol and the three remote hostio functions with
filename arguments are modified to send "vFile:setfs" packets as
necessary.

gdb/ChangeLog:

	* remote.c (struct remote_state) <fs_pid>: New field.
	(new_remote_state): Initialize the above.
	(PACKET_vFile_setfs): New enum value.
	(remote_fs_pid): New static variable.
	(remote_hostio_set_fs_deferred): New function.
	(remote_hostio_set_filesystem): Likewise.
	(remote_hostio_open): Call the above.
	(remote_hostio_unlink): Likewise.
	(remote_hostio_readlink): Likewise.
	(init_remote_ops): Initialize to_fileio_set_fs.
	(_initialize_remote): Register new "set/show remote
	hostio-setfs-packet" command.
	* NEWS: Mention that GDB and gdbserver support attaching to
	processes in different mount namespaces on GNU/Linux systems.
	Announce new vFile:setfs packet.

gdb/doc/ChangeLog:

	* gdb.texinfo (Remote Configuration): Document the
	"set/show remote hostio-setfs-packet" command.
	(Host I/O Packets): Document the vFile:setfs packet.
---
 gdb/ChangeLog       |   18 +++++++++++++++
 gdb/NEWS            |    8 +++++++
 gdb/doc/ChangeLog   |    6 +++++
 gdb/doc/gdb.texinfo |   11 +++++++++
 gdb/remote.c        |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 62cbdcb..a9f05e4 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -42,6 +42,10 @@
   (no "set sysroot" or "file" commands are required).  See "New remote
   packets" below.
 
+* GDB and gdbserver now support attaching to processes running in
+  different mount namespaces from the debugger on GNU/Linux systems.
+  See "New remote packets" below.
+
 * Python Scripting
 
   ** gdb.Objfile objects have a new attribute "username",
@@ -116,6 +120,10 @@ qXfer:exec-file:read
   Return the full absolute name of the file that was executed to
   create a process running on the remote system.
 
+vFile:setfs:
+  Set the filesystem accessed by vFile: packets with filename
+  arguments.
+
 * The info record command now shows the recording format and the
   branch tracing configuration for the current thread when using
   the btrace record target.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e7872dd..fc0f4b1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19889,6 +19889,10 @@ are:
 @tab @code{vFile:fstat}
 @tab Host I/O
 
+@item @code{hostio-setfs-packet}
+@tab @code{vFile:setfs}
+@tab Host I/O
+
 @item @code{noack-packet}
 @tab @code{QStartNoAckMode}
 @tab Packet acknowledgment
@@ -37533,6 +37537,13 @@ An empty response indicates that this operation is not recognized.
 These are the supported Host I/O operations:
 
 @table @samp
+@item vFile:setfs: @var{pid}
+Set the filesystem accessed by @code{vFile} packets with
+@var{filename} arguments to the filesystem as seen by process
+@var{pid}.  If @var{pid} is zero, set the filesystem to that
+seen by the remote stub.  Return 0 on success, or -1 if an
+error occurs.
+
 @item vFile:open: @var{filename}, @var{flags}, @var{mode}
 Open a file at @var{filename} and return a file descriptor for it, or
 return -1 if an error occurs.  The @var{filename} is a string,
diff --git a/gdb/remote.c b/gdb/remote.c
index 3b2325f..3202871 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -367,6 +367,12 @@ struct remote_state
 
   /* The branch trace configuration.  */
   struct btrace_config btrace_config;
+
+  /* The argument to the last "vFile:setfs:" packet we sent, used
+     to avoid sending repeated unnecessary "vFile:setfs:" packets.
+     Initialized to -1 to indicate that no "vFile:setfs:" packet
+     has yet been sent.  */
+  int fs_pid;
 };
 
 /* Private data that we'll store in (struct thread_info)->private.  */
@@ -409,6 +415,7 @@ new_remote_state (void)
   result->buf = xmalloc (result->buf_size);
   result->remote_traceframe_number = -1;
   result->last_sent_signal = GDB_SIGNAL_0;
+  result->fs_pid = -1;
 
   return result;
 }
@@ -1243,6 +1250,7 @@ enum {
   PACKET_Z2,
   PACKET_Z3,
   PACKET_Z4,
+  PACKET_vFile_setfs,
   PACKET_vFile_open,
   PACKET_vFile_pread,
   PACKET_vFile_pwrite,
@@ -9879,6 +9887,46 @@ remote_hostio_send_command (int command_bytes, int which_packet,
   return ret;
 }
 
+/* Process ID of inferior whose filesystem remote_hostio functions
+   that take FILENAME arguments will use.  Zero means to use the
+   remote stub's filesystem.  */
+
+static int remote_fs_pid = 0;
+
+/* Implementation of to_fileio_set_fs.  */
+
+static void
+remote_hostio_set_fs_deferred (struct target_ops *self, int pid)
+{
+  remote_fs_pid = pid;
+}
+
+/* Set the filesystem remote_hostio functions that take FILENAME
+   arguments will use.  */
+
+static void
+remote_hostio_set_filesystem (void)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  if (rs->fs_pid == -1 || remote_fs_pid != rs->fs_pid)
+    {
+      char *p = rs->buf;
+      int left = get_remote_packet_size () - 1;
+      int remote_errno;
+      char arg[9];
+
+      remote_buffer_add_string (&p, &left, "vFile:setfs:");
+
+      xsnprintf (arg, sizeof (arg), "%x", remote_fs_pid);
+      remote_buffer_add_string (&p, &left, arg);
+
+      if (remote_hostio_send_command (p - rs->buf, PACKET_vFile_setfs,
+				      &remote_errno, NULL, NULL) == 0)
+	rs->fs_pid = remote_fs_pid;
+    }
+}
+
 /* Return nonzero if the filesystem accessed by the target_fileio_*
    methods is the local filesystem, zero otherwise.  */
 
@@ -9901,6 +9949,8 @@ remote_hostio_open (struct target_ops *self,
   char *p = rs->buf;
   int left = get_remote_packet_size () - 1;
 
+  remote_hostio_set_filesystem ();
+
   remote_buffer_add_string (&p, &left, "vFile:open:");
 
   remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
@@ -10015,6 +10065,8 @@ remote_hostio_unlink (struct target_ops *self,
   char *p = rs->buf;
   int left = get_remote_packet_size () - 1;
 
+  remote_hostio_set_filesystem ();
+
   remote_buffer_add_string (&p, &left, "vFile:unlink:");
 
   remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
@@ -10040,6 +10092,8 @@ remote_hostio_readlink (struct target_ops *self,
   int read_len;
   char *ret;
 
+  remote_hostio_set_filesystem ();
+
   remote_buffer_add_string (&p, &left, "vFile:readlink:");
 
   remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
@@ -11756,6 +11810,7 @@ Specify the serial device it is connected to\n\
   remote_ops.to_supports_multi_process = remote_supports_multi_process;
   remote_ops.to_supports_disable_randomization
     = remote_supports_disable_randomization;
+  remote_ops.to_fileio_set_fs = remote_hostio_set_fs_deferred;
   remote_ops.to_filesystem_is_local = remote_filesystem_is_local;
   remote_ops.to_fileio_open = remote_hostio_open;
   remote_ops.to_fileio_pwrite = remote_hostio_pwrite;
@@ -12322,6 +12377,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qTStatus],
 			 "qTStatus", "trace-status", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_setfs],
+			 "vFile:setfs", "hostio-setfs", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_open],
 			 "vFile:open", "hostio-open", 0);
 
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 3/7] Introduce nat/linux-namespaces.[ch]
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (3 preceding siblings ...)
  2015-04-16 12:27 ` [PATCH 6/7] Implement multiple-filesystem support for remote targets Gary Benson
@ 2015-04-16 12:34 ` Gary Benson
  2015-04-17  4:26   ` Doug Evans
  2015-04-17 14:52   ` Pedro Alves
  2015-04-16 12:54 ` [PATCH 7/7] Implement vFile:setfs in gdbserver Gary Benson
                   ` (13 subsequent siblings)
  18 siblings, 2 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-16 12:34 UTC (permalink / raw)
  To: gdb-patches

This commit introduces new shared files nat/linux-namespaces.[ch]
containing code to support Linux namespaces that will be used by
both GDB and gdbserver.

gdb/ChangeLog:

	* configure.ac (AC_CHECK_FUNCS): Add setns.
	* config.in: Regenerate.
	* configure: Likewise.
	* nat/linux-namespaces.h: New file.
	* nat/linux-namespaces.c: Likewise.
	* Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-namespaces.h.
	(linux-namespaces.o): New rule.
	* config/aarch64/linux.mh (NATDEPFILES): Add linux-namespaces.o.
	* config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
	* config/arm/linux.mh (NATDEPFILES): Likewise.
	* config/i386/linux.mh (NATDEPFILES): Likewise.
	* config/i386/linux64.mh (NATDEPFILES): Likewise.
	* config/ia64/linux.mh (NATDEPFILES): Likewise.
	* config/m32r/linux.mh (NATDEPFILES): Likewise.
	* config/m68k/linux.mh (NATDEPFILES): Likewise.
	* config/mips/linux.mh (NATDEPFILES): Likewise.
	* config/pa/linux.mh (NATDEPFILES): Likewise.
	* config/powerpc/linux.mh (NATDEPFILES): Likewise.
	* config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
	* config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
	* config/s390/linux.mh (NATDEPFILES): Likewise.
	* config/sparc/linux.mh (NATDEPFILES): Likewise.
	* config/sparc/linux64.mh (NATDEPFILES): Likewise.
	* config/tilegx/linux.mh (NATDEPFILES): Likewise.
	* config/xtensa/linux.mh (NATDEPFILES): Likewise.

gdb/gdbserver/ChangeLog:

	* configure.ac (AC_CHECK_FUNCS): Add setns.
	* config.in: Regenerate.
	* configure: Likewise.
	* Makefile.in (SFILES): Add nat/linux-namespaces.c.
	(linux-namespaces.o): New rule.
	* configure.srv (srv_linux_obj): Add linux-namespaces.o.
---
 gdb/ChangeLog                     |   28 +++++
 gdb/Makefile.in                   |    6 +-
 gdb/config.in                     |    3 +
 gdb/config/aarch64/linux.mh       |    2 +-
 gdb/config/alpha/alpha-linux.mh   |    2 +-
 gdb/config/arm/linux.mh           |    2 +-
 gdb/config/i386/linux.mh          |    2 +-
 gdb/config/i386/linux64.mh        |    2 +-
 gdb/config/ia64/linux.mh          |    3 +-
 gdb/config/m32r/linux.mh          |    2 +-
 gdb/config/m68k/linux.mh          |    2 +-
 gdb/config/mips/linux.mh          |    2 +-
 gdb/config/pa/linux.mh            |    2 +-
 gdb/config/powerpc/linux.mh       |    2 +-
 gdb/config/powerpc/ppc64-linux.mh |    3 +-
 gdb/config/powerpc/spu-linux.mh   |    4 +-
 gdb/config/s390/linux.mh          |    2 +-
 gdb/config/sparc/linux.mh         |    2 +-
 gdb/config/sparc/linux64.mh       |    2 +-
 gdb/config/tilegx/linux.mh        |    2 +-
 gdb/config/xtensa/linux.mh        |    2 +-
 gdb/configure                     |    2 +-
 gdb/configure.ac                  |    2 +-
 gdb/gdbserver/ChangeLog           |    9 ++
 gdb/gdbserver/Makefile.in         |    6 +-
 gdb/gdbserver/config.in           |    3 +
 gdb/gdbserver/configure           |    2 +-
 gdb/gdbserver/configure.ac        |    2 +-
 gdb/gdbserver/configure.srv       |    2 +-
 gdb/nat/linux-namespaces.c        |  231 +++++++++++++++++++++++++++++++++++++
 gdb/nat/linux-namespaces.h        |   61 ++++++++++
 31 files changed, 371 insertions(+), 26 deletions(-)
 create mode 100644 gdb/nat/linux-namespaces.c
 create mode 100644 gdb/nat/linux-namespaces.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 47b216a..9921dcb 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -980,7 +980,7 @@ common/common-debug.h common/cleanups.h common/gdb_setjmp.h \
 common/common-exceptions.h target/target.h common/symbol.h \
 common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
 common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h \
-common/cleanup-utils.h
+common/cleanup-utils.h nat/linux-namespaces.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -2325,6 +2325,10 @@ x86-linux-dregs.o: ${srcdir}/nat/x86-linux-dregs.c
 	$(COMPILE) $(srcdir)/nat/x86-linux-dregs.c
 	$(POSTCOMPILE)
 
+linux-namespaces.o: ${srcdir}/nat/linux-namespaces.c
+	$(COMPILE) $(srcdir)/nat/linux-namespaces.c
+	$(POSTCOMPILE)
+
 #
 # gdb/tui/ dependencies
 #
diff --git a/gdb/config.in b/gdb/config.in
index d41e6cf..5b6dbbb 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -390,6 +390,9 @@
 /* Define to 1 if you have the `setlocale' function. */
 #undef HAVE_SETLOCALE
 
+/* Define to 1 if you have the `setns' function. */
+#undef HAVE_SETNS
+
 /* Define to 1 if you have the `setpgid' function. */
 #undef HAVE_SETPGID
 
diff --git a/gdb/config/aarch64/linux.mh b/gdb/config/aarch64/linux.mh
index 7f96e4d..6a8aa7d 100644
--- a/gdb/config/aarch64/linux.mh
+++ b/gdb/config/aarch64/linux.mh
@@ -22,7 +22,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o aarch64-linux-nat.o \
 	proc-service.o linux-thread-db.o linux-nat.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-osdata.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
diff --git a/gdb/config/alpha/alpha-linux.mh b/gdb/config/alpha/alpha-linux.mh
index 2ea02a1..4991dd2 100644
--- a/gdb/config/alpha/alpha-linux.mh
+++ b/gdb/config/alpha/alpha-linux.mh
@@ -3,7 +3,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o alpha-linux-nat.o \
 	fork-child.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/arm/linux.mh b/gdb/config/arm/linux.mh
index 549bf42..f0c5967 100644
--- a/gdb/config/arm/linux.mh
+++ b/gdb/config/arm/linux.mh
@@ -4,7 +4,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o arm-linux-nat.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh
index 9be2c5f..421c56f 100644
--- a/gdb/config/i386/linux.mh
+++ b/gdb/config/i386/linux.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
 	linux-btrace.o linux-waitpid.o linux-personality.o x86-linux.o \
-	x86-linux-dregs.o
+	x86-linux-dregs.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh
index 224a2a9..04cbb95 100644
--- a/gdb/config/i386/linux64.mh
+++ b/gdb/config/i386/linux64.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-btrace.o \
 	linux-waitpid.o linux-personality.o x86-linux.o \
-	x86-linux-dregs.o
+	x86-linux-dregs.o linux-namespaces.o
 NAT_FILE= config/nm-linux.h
 NAT_CDEPS = $(srcdir)/proc-service.list
 
diff --git a/gdb/config/ia64/linux.mh b/gdb/config/ia64/linux.mh
index 9dce22b..b05f834 100644
--- a/gdb/config/ia64/linux.mh
+++ b/gdb/config/ia64/linux.mh
@@ -6,7 +6,8 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-personality.o \
-	linux-procfs.o linux-ptrace.o linux-waitpid.o
+	linux-procfs.o linux-ptrace.o linux-waitpid.o \
+	linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/m32r/linux.mh b/gdb/config/m32r/linux.mh
index 6b810e6..277d8bd 100644
--- a/gdb/config/m32r/linux.mh
+++ b/gdb/config/m32r/linux.mh
@@ -4,7 +4,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o				\
 	m32r-linux-nat.o proc-service.o linux-thread-db.o	\
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
diff --git a/gdb/config/m68k/linux.mh b/gdb/config/m68k/linux.mh
index f3b3baa..60d5ce4 100644
--- a/gdb/config/m68k/linux.mh
+++ b/gdb/config/m68k/linux.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
 	linux-personality.o \
-	linux-waitpid.o
+	linux-waitpid.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/mips/linux.mh b/gdb/config/mips/linux.mh
index d6a802f..11ff903 100644
--- a/gdb/config/mips/linux.mh
+++ b/gdb/config/mips/linux.mh
@@ -5,7 +5,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o mips-linux-nat.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
 	linux-personality.o \
-	mips-linux-watch.o
+	mips-linux-watch.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/pa/linux.mh b/gdb/config/pa/linux.mh
index 9539b64..1b73ecd 100644
--- a/gdb/config/pa/linux.mh
+++ b/gdb/config/pa/linux.mh
@@ -4,7 +4,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	hppa-linux-nat.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/powerpc/linux.mh b/gdb/config/powerpc/linux.mh
index 76e62c0..f4a52c3 100644
--- a/gdb/config/powerpc/linux.mh
+++ b/gdb/config/powerpc/linux.mh
@@ -6,7 +6,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
 	ppc-linux-nat.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/powerpc/ppc64-linux.mh b/gdb/config/powerpc/ppc64-linux.mh
index 7eb6507..580eb1f 100644
--- a/gdb/config/powerpc/ppc64-linux.mh
+++ b/gdb/config/powerpc/ppc64-linux.mh
@@ -6,7 +6,8 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
 	ppc-linux-nat.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o ppc-linux.o linux-personality.o
+	linux-waitpid.o ppc-linux.o linux-personality.o \
+	linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The PowerPC has severe limitations on TOC size, and uses them even
diff --git a/gdb/config/powerpc/spu-linux.mh b/gdb/config/powerpc/spu-linux.mh
index d44aeeb..9205b62 100644
--- a/gdb/config/powerpc/spu-linux.mh
+++ b/gdb/config/powerpc/spu-linux.mh
@@ -4,5 +4,5 @@
 # PPU side of the Cell BE and debugging the SPU side.
 
 NATDEPFILES = spu-linux-nat.o fork-child.o inf-ptrace.o \
-	      linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o
-
+	      linux-procfs.o linux-ptrace.o linux-waitpid.o \
+	      linux-personality.o linux-namespaces.o
diff --git a/gdb/config/s390/linux.mh b/gdb/config/s390/linux.mh
index e1ad899..4a137cd 100644
--- a/gdb/config/s390/linux.mh
+++ b/gdb/config/s390/linux.mh
@@ -4,6 +4,6 @@ NATDEPFILES= inf-ptrace.o fork-child.o s390-linux-nat.o \
 	linux-thread-db.o proc-service.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
 	linux-personality.o \
-	linux-waitpid.o
+	linux-waitpid.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/sparc/linux.mh b/gdb/config/sparc/linux.mh
index bd7fc86..385f640 100644
--- a/gdb/config/sparc/linux.mh
+++ b/gdb/config/sparc/linux.mh
@@ -5,7 +5,7 @@ NATDEPFILES= sparc-nat.o sparc-linux-nat.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/sparc/linux64.mh b/gdb/config/sparc/linux64.mh
index 86f984f..8df0de1 100644
--- a/gdb/config/sparc/linux64.mh
+++ b/gdb/config/sparc/linux64.mh
@@ -5,7 +5,7 @@ NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-linux-nat.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/tilegx/linux.mh b/gdb/config/tilegx/linux.mh
index b5edcd4..ec648d3 100644
--- a/gdb/config/tilegx/linux.mh
+++ b/gdb/config/tilegx/linux.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
 # gdb executable.
diff --git a/gdb/config/xtensa/linux.mh b/gdb/config/xtensa/linux.mh
index b4e59b3..d5b8f91 100644
--- a/gdb/config/xtensa/linux.mh
+++ b/gdb/config/xtensa/linux.mh
@@ -5,7 +5,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o xtensa-linux-nat.o \
 	linux-thread-db.o proc-service.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/configure b/gdb/configure
index 2baf6dd..5100921 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10957,7 +10957,7 @@ for ac_func in getauxval getrusage getuid getgid \
 		sigaction sigprocmask sigsetmask socketpair \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid \
-		ptrace64 sigaltstack mkdtemp
+		ptrace64 sigaltstack mkdtemp setns
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/configure.ac b/gdb/configure.ac
index c703e35..2035a37 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1331,7 +1331,7 @@ AC_CHECK_FUNCS([getauxval getrusage getuid getgid \
 		sigaction sigprocmask sigsetmask socketpair \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid \
-		ptrace64 sigaltstack mkdtemp])
+		ptrace64 sigaltstack mkdtemp setns])
 AM_LANGINFO_CODESET
 GDB_AC_COMMON
 
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 8ba88d4..4179cd6 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -180,7 +180,8 @@ SFILES=	$(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
 	$(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c \
 	$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c \
 	$(srcdir)/common/btrace-common.c \
-	$(srcdir)/common/fileio.c $(srcdir)/common/cleanup-utils.c
+	$(srcdir)/common/fileio.c $(srcdir)/common/cleanup-utils.c \
+	$(srcdir)/nat/linux-namespaces.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -619,6 +620,9 @@ x86-linux-dregs.o: ../nat/x86-linux-dregs.c
 cleanup-utils.o: ../common/cleanup-utils.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+linux-namespaces.o: ../nat/linux-namespaces.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 
 aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index 3c3bfca..893aaab 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -183,6 +183,9 @@
 /* Define to 1 if you have the `pwrite' function. */
 #undef HAVE_PWRITE
 
+/* Define to 1 if you have the `setns' function. */
+#undef HAVE_SETNS
+
 /* Define to 1 if you have the <sgtty.h> header file. */
 #undef HAVE_SGTTY_H
 
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 75860dd..bcb3f2e 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -5310,7 +5310,7 @@ fi
 
 done
 
-for ac_func in getauxval pread pwrite pread64
+for ac_func in getauxval pread pwrite pread64 setns
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index 34af269..2aef2b4 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -94,7 +94,7 @@ AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl
 		 fcntl.h signal.h sys/file.h dnl
 		 sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
 		 netinet/tcp.h arpa/inet.h)
-AC_CHECK_FUNCS(getauxval pread pwrite pread64)
+AC_CHECK_FUNCS(getauxval pread pwrite pread64 setns)
 
 GDB_AC_COMMON
 
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 81dd235..7f89f2f 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -42,7 +42,7 @@ srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/amd
 
 # Linux object files.  This is so we don't have to repeat
 # these files over and over again.
-srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o"
+srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o linux-namespaces.o"
 
 # Input is taken from the "${target}" variable.
 
diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
new file mode 100644
index 0000000..f6fe863
--- /dev/null
+++ b/gdb/nat/linux-namespaces.c
@@ -0,0 +1,231 @@
+/* Linux namespaces(7) support.
+
+   Copyright (C) 2015 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 "nat/linux-namespaces.h"
+#include "filestuff.h"
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+
+/* Handle systems with __NR_setns but no setns.  */
+#if defined(__NR_setns) && !defined(HAVE_SETNS)
+static int
+setns (int fd, int nstype)
+{
+  return syscall (__NR_setns, fd, nstype);
+}
+#define HAVE_SETNS 1
+#endif /* defined(__NR_setns) && !defined(HAVE_SETNS) */
+
+#ifdef HAVE_SETNS
+
+/* Return the path of the TYPE namespace entry for process PID.
+   The returned value persists until this function is next called.  */
+
+static const char *
+linux_ns_path_for (int pid, const char *type)
+{
+  static char path[PATH_MAX];
+
+  xsnprintf (path, sizeof (path), "/proc/%d/ns/%s", pid, type);
+
+  return path;
+}
+
+/* See nat/linux-namespaces.h.  */
+
+int
+linux_ns_same (int pid1, int pid2, const char *type)
+{
+  const char *path;
+  struct stat sb;
+  ino_t pid1_id;
+
+  if (pid1 == pid2)
+    return 1;
+
+  /* Lack of kernel support for TYPE namespaces is detected by
+     attempting to open our own.  Try to make PID1 be our own
+     PID so we don't have to do extra checking if the the first
+     stat fails.  */
+  if (pid2 == getpid ())
+    {
+      int swap = pid1;
+
+      pid1 = pid2;
+      pid2 = swap;
+    }
+
+  path = linux_ns_path_for (pid1, type);
+  if (stat (path, &sb) != 0)
+    {
+      int saved_errno;
+
+      if (pid1 == getpid ())
+	{
+	  /* Assume the kernel does not support TYPE namespaces.  */
+	  return 1;
+	}
+
+      saved_errno = errno;
+      path = linux_ns_path_for (getpid (), type);
+      if (stat (path, &sb) != 0)
+	{
+	  /* Assume the kernel does not support TYPE namespaces.  */
+	  return 1;
+	}
+
+      /* We can open our own TYPE namespace but not that for process
+	 PID.  The process might have died, or we might not have the
+	 right permissions (though we should be attached by this time
+	 so this seems unlikely).  In any event, we cannot make any
+	 decisions and must throw.  */
+      errno = saved_errno;
+      perror_with_name (linux_ns_path_for (pid1, type));
+    }
+  pid1_id = sb.st_ino;
+
+  /* The kernel definitely supports TYPE namespaces so we cannot
+     make any decisions if this stat fails.  */
+  path = linux_ns_path_for (pid2, type);
+  if (stat (path, &sb) != 0)
+    perror_with_name (path);
+
+  return sb.st_ino == pid1_id;
+}
+
+/* Helper function which does the work for make_cleanup_setns.  */
+
+static void
+do_setns_cleanup (void *arg)
+{
+  int *fd = arg;
+
+  if (setns (*fd, 0) != 0)
+    internal_error (__FILE__, __LINE__,
+		    _("unable to restore namespace: %s"),
+		    safe_strerror (errno));
+}
+
+/* Return a new cleanup that calls setns on FD.  */
+
+static struct cleanup *
+make_cleanup_setns (int fd)
+{
+  int *saved_fd = xmalloc (sizeof (fd));
+
+  *saved_fd = fd;
+  return make_cleanup_dtor (do_setns_cleanup, saved_fd, xfree);
+}
+
+
+/* See nat/linux-namespaces.h.  */
+
+int
+linux_ns_enter (int pid, const char *type,
+		void (*func) (void *), void *arg)
+{
+  struct cleanup *old_chain, *close_pidfd;
+  int our_fd, pid_fd;
+  struct stat sb;
+  ino_t our_id;
+
+  /* Open our TYPE namespace.  On failure, assume the kernel does
+     not support TYPE namespaces (so every process is in the same
+     TYPE namespace) and just call FUNC with ARG and return.  */
+  our_fd = gdb_open_cloexec (linux_ns_path_for (getpid(), type),
+			     O_RDONLY, 0);
+  if (our_fd < 0)
+    {
+      func (arg);
+      return 1;
+    }
+  old_chain = make_cleanup_close (our_fd);
+
+  /* We've successfully opened our own TYPE namespace.  The kernel
+     obviously supports TYPE namespaces and any subsequent errors
+     cannot be continued over.  */
+
+  if (fstat (our_fd, &sb) != 0)
+    {
+      do_cleanups (old_chain);
+      return 0;
+    }
+  our_id = sb.st_ino;
+
+  pid_fd = gdb_open_cloexec (linux_ns_path_for (pid, type),
+			     O_RDONLY, 0);
+  if (pid_fd < 0)
+    {
+      do_cleanups (old_chain);
+      return 0;
+    }
+  close_pidfd = make_cleanup_close (pid_fd);
+
+  if (fstat (pid_fd, &sb) != 0)
+    {
+      do_cleanups (old_chain);
+      return 0;
+    }
+
+  if (sb.st_ino == our_id)
+    {
+      /* The other process has the same TYPE namespace as us.  */
+      do_cleanups (old_chain);
+      func (arg);
+      return 1;
+    }
+
+  if (setns (pid_fd, 0) != 0)
+    {
+      do_cleanups (old_chain);
+      return 0;
+    }
+  do_cleanups (close_pidfd);
+  make_cleanup_setns (our_fd);
+
+  func (arg);
+
+  do_cleanups (old_chain);
+  return 1;
+}
+
+#else /* HAVE_SETNS */
+
+/* See nat/linux-namespaces.h.  */
+
+int
+linux_ns_same (int pid1, int pid2, const char *type)
+{
+  return 1;
+}
+
+/* See nat/linux-namespaces.h.  */
+
+int
+linux_ns_enter (int pid, const char *type,
+		void (*func) (void *), void *arg)
+{
+  func (arg);
+
+  return 1;
+}
+
+#endif  /* HAVE_SETNS */
diff --git a/gdb/nat/linux-namespaces.h b/gdb/nat/linux-namespaces.h
new file mode 100644
index 0000000..0e94c07
--- /dev/null
+++ b/gdb/nat/linux-namespaces.h
@@ -0,0 +1,61 @@
+/* Linux namespaces(7) support.
+
+   Copyright (C) 2015 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 LINUX_NAMESPACES_H
+#define LINUX_NAMESPACES_H
+
+/* Filenames of Linux namespaces in /proc/PID/ns.  */
+
+/* IPC namespace: System V IPC, POSIX message queues.  */
+#define LINUX_NS_IPC "ipc"
+
+/* Mount namespace: mount points.  */
+#define LINUX_NS_MNT "mnt"
+
+/* Network namespace: network devices, stacks, ports, etc.  */
+#define LINUX_NS_NET "net"
+
+/* PID namespace: process IDs.  */
+#define LINUX_NS_PID "pid"
+
+/* User namespace: user and group IDs.  */
+#define LINUX_NS_USER "user"
+
+/* UTS namespace: hostname and NIS domain name.  */
+#define LINUX_NS_UTS "uts"
+
+
+/* Return nonzero if processes PID1 and PID2 have the same TYPE
+   namespace, or if the kernel does not support TYPE namespaces
+   (in which case there is only one TYPE namespace).  Return zero
+   if the kernel supports TYPE namespaces and the two processes
+   have different TYPE namespaces.  */
+
+extern int linux_ns_same (int pid1, int pid2, const char *type);
+
+/* Enter the TYPE namespace of process PID and call FUNC with the
+   argument ARG, returning to the original TYPE namespace afterwards.
+   If process PID has the same TYPE namespace as the current process,
+   or if TYPE namespaces are not supported, just call FUNC with ARG.
+   Return nonzero if FUNC was called, zero otherwise (and set ERRNO). */
+
+extern int linux_ns_enter (int pid, const char *type,
+			   void (*func) (void *), void *arg);
+
+#endif /* LINUX_NAMESPACES_H */
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 7/7] Implement vFile:setfs in gdbserver
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (4 preceding siblings ...)
  2015-04-16 12:34 ` [PATCH 3/7] Introduce nat/linux-namespaces.[ch] Gary Benson
@ 2015-04-16 12:54 ` Gary Benson
  2015-04-17 15:30   ` Pedro Alves
  2015-04-16 13:06 ` [PATCH 5/7] Implement multiple-filesystem support for Linux targets Gary Benson
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-16 12:54 UTC (permalink / raw)
  To: gdb-patches

gdb/gdbserver/ChangeLog:

	* target.h (struct target_ops) <call_with_fs_of>: New field.
	* linux-low.c (nat/linux-namespaces.h): New include.
	(linux_low_call_with_fs_of): New function.
	* linux-low.c (linux_target_ops): Initialize call_with_fs_of.
	* hostio.c (hostio_fs_pid): New static variable.
	(handle_setfs): New function.
	(enter_filesystem): Likewise.
	(open_closure): New structure.
	(handle_open_1): New function.
	(handle_open): Update to use enter_filesystem.
	(unlink_closure): New structure.
	(handle_unlink_1): New function.
	(handle_unlink): Update to use enter_filesystem.
	(readlink_closure): New structure.
	(handle_readlink_1): New function.
	(handle_readlink): Update to use enter_filesystem.
	(handle_vFile): Handle vFile:setfs packets.
---
 gdb/gdbserver/ChangeLog   |   20 ++++++
 gdb/gdbserver/hostio.c    |  152 ++++++++++++++++++++++++++++++++++++++++----
 gdb/gdbserver/linux-low.c |   10 +++
 gdb/gdbserver/target.h    |    6 ++
 4 files changed, 174 insertions(+), 14 deletions(-)

diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
index b03b5ad..9a1e443 100644
--- a/gdb/gdbserver/hostio.c
+++ b/gdb/gdbserver/hostio.c
@@ -243,6 +243,51 @@ hostio_reply_with_data (char *own_buf, char *buffer, int len,
   return input_index;
 }
 
+/* Process ID of inferior whose filesystem hostio functions
+   that take FILENAME arguments will use.  Zero means to use
+   our own filesystem.  */
+
+static int hostio_fs_pid = 0;
+
+/* Handle a "vFile:setfs:" packet.  */
+
+static void
+handle_setfs (char *own_buf)
+{
+  char *p;
+  int pid;
+
+  p = own_buf + strlen ("vFile:setfs:");
+
+  if (require_int (&p, &pid)
+      || pid < 0
+      || require_end (p))
+    {
+      hostio_packet_error (own_buf);
+      return;
+    }
+
+  hostio_fs_pid = pid;
+
+  hostio_reply (own_buf, 0);
+}
+
+/* Cause the filesystem to appear as it does to the process specified
+   by the most recent valid "vFile:setfs:" packet and call FUNC with
+   argument ARG, restoring the filesystem to its original state
+   afterwards.  Return nonzero if FUNC was called, zero otherwise (and
+   set ERRNO). */
+
+static int
+enter_filesystem (void (*func) (void *), void *arg)
+{
+  if (hostio_fs_pid != 0 && the_target->call_with_fs_of != NULL)
+    return the_target->call_with_fs_of (hostio_fs_pid, func, arg);
+
+  func (arg);
+  return 1;
+}
+
 static int
 fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
 {
@@ -275,23 +320,45 @@ fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
   return 0;
 }
 
+/* Arguments and return value of open(2).  */
+
+struct open_closure
+{
+  char filename[HOSTIO_PATH_MAX];
+  int flags;
+  int mode;
+  int return_value;
+};
+
+/* Helper for handle_open.  */
+
+static void
+handle_open_1 (void *arg)
+{
+  struct open_closure *clo = (struct open_closure *) arg;
+
+  clo->return_value = open (clo->filename, clo->flags, clo->mode);
+}
+
+/* Handle a "vFile:open:" packet.  */
+
 static void
 handle_open (char *own_buf)
 {
-  char filename[HOSTIO_PATH_MAX];
   char *p;
-  int fileio_flags, mode, flags, fd;
+  int fileio_flags, fd;
   struct fd_list *new_fd;
+  struct open_closure clo;
 
   p = own_buf + strlen ("vFile:open:");
 
-  if (require_filename (&p, filename)
+  if (require_filename (&p, clo.filename)
       || require_comma (&p)
       || require_int (&p, &fileio_flags)
       || require_comma (&p)
-      || require_int (&p, &mode)
+      || require_int (&p, &clo.mode)
       || require_end (p)
-      || fileio_open_flags_to_host (fileio_flags, &flags))
+      || fileio_open_flags_to_host (fileio_flags, &clo.flags))
     {
       hostio_packet_error (own_buf);
       return;
@@ -299,7 +366,11 @@ handle_open (char *own_buf)
 
   /* We do not need to convert MODE, since the fileio protocol
      uses the standard values.  */
-  fd = open (filename, flags, mode);
+
+  if (enter_filesystem (handle_open_1, &clo))
+    fd = clo.return_value;
+  else
+    fd = -1;
 
   if (fd == -1)
     {
@@ -487,23 +558,46 @@ handle_close (char *own_buf)
   hostio_reply (own_buf, ret);
 }
 
+/* Arguments and return value of unlink(2).  */
+
+struct unlink_closure
+{
+  char filename[HOSTIO_PATH_MAX];
+  int return_value;
+};
+
+/* Helper for handle_unlink.  */
+
+static void
+handle_unlink_1 (void *arg)
+{
+  struct unlink_closure *clo = (struct unlink_closure *) arg;
+
+  clo->return_value = unlink (clo->filename);
+}
+
+/* Handle a "vFile:unlink:" packet.  */
+
 static void
 handle_unlink (char *own_buf)
 {
-  char filename[HOSTIO_PATH_MAX];
+  struct unlink_closure clo;
   char *p;
   int ret;
 
   p = own_buf + strlen ("vFile:unlink:");
 
-  if (require_filename (&p, filename)
+  if (require_filename (&p, clo.filename)
       || require_end (p))
     {
       hostio_packet_error (own_buf);
       return;
     }
 
-  ret = unlink (filename);
+  if (enter_filesystem (handle_unlink_1, &clo))
+    ret = clo.return_value;
+  else
+    ret = -1;
 
   if (ret == -1)
     {
@@ -514,30 +608,57 @@ handle_unlink (char *own_buf)
   hostio_reply (own_buf, ret);
 }
 
+/* Arguments and return value of readlink(2).  */
+
+struct readlink_closure
+{
+  char filename[HOSTIO_PATH_MAX];
+  char linkname[HOSTIO_PATH_MAX];
+  int return_value;
+};
+
+/* Helper for handle_readlink.  */
+
+static void
+handle_readlink_1 (void *arg)
+{
+  struct readlink_closure *clo = (struct readlink_closure *) arg;
+
+  clo->return_value = readlink (clo->filename, clo->linkname,
+				sizeof (clo->linkname) - 1);
+}
+
+/* Handle a "vFile:readlink:" packet.  */
+
 static void
 handle_readlink (char *own_buf, int *new_packet_len)
 {
-  char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX];
+  struct readlink_closure clo;
   char *p;
   int ret, bytes_sent;
 
   p = own_buf + strlen ("vFile:readlink:");
 
-  if (require_filename (&p, filename)
+  if (require_filename (&p, clo.filename)
       || require_end (p))
     {
       hostio_packet_error (own_buf);
       return;
     }
 
-  ret = readlink (filename, linkname, sizeof (linkname) - 1);
+  if (enter_filesystem (handle_readlink_1, &clo))
+    ret = clo.return_value;
+  else
+    ret = -1;
+
   if (ret == -1)
     {
       hostio_error (own_buf);
       return;
     }
 
-  bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len);
+  bytes_sent = hostio_reply_with_data (own_buf, clo.linkname,
+				       ret, new_packet_len);
 
   /* If the response does not fit into a single packet, do not attempt
      to return a partial response, but simply fail.  */
@@ -550,7 +671,10 @@ handle_readlink (char *own_buf, int *new_packet_len)
 int
 handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
 {
-  if (startswith (own_buf, "vFile:open:"))
+  if (the_target->call_with_fs_of != NULL
+      && startswith (own_buf, "vFile:setfs:"))
+    handle_setfs (own_buf);
+  else if (startswith (own_buf, "vFile:open:"))
     handle_open (own_buf);
   else if (startswith (own_buf, "vFile:pread:"))
     handle_pread (own_buf, new_packet_len);
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 74f754d..4f01dbd 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -51,6 +51,7 @@
    definition of elf_fpregset_t.  */
 #include <elf.h>
 #endif
+#include "nat/linux-namespaces.h"
 
 #ifndef SPUFS_MAGIC
 #define SPUFS_MAGIC 0x23c9b64e
@@ -6349,6 +6350,14 @@ current_lwp_ptid (void)
   return ptid_of (current_thread);
 }
 
+/* Implementation of target_ops->call_with_fs_of.  */
+
+static int
+linux_low_call_with_fs_of (int pid, void (*func) (void *), void *arg)
+{
+  return linux_ns_enter (pid, LINUX_NS_MNT, func, arg);
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
@@ -6434,6 +6443,7 @@ static struct target_ops linux_target_ops = {
 #endif
   linux_supports_range_stepping,
   linux_proc_pid_to_exec_file,
+  linux_low_call_with_fs_of,
 };
 
 static void
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index 6280c26..c766a2c 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -402,6 +402,12 @@ struct target_ops
      string should be copied into a buffer by the client if the string
      will not be immediately used, or if it must persist.  */
   char *(*pid_to_exec_file) (int pid);
+
+  /* Cause the filesystem to appear as it does to process PID and
+     call FUNC with argument ARG, restoring the filesystem to its
+     original state afterwards.  Return nonzero if FUNC was called,
+     zero otherwise (and set ERRNO). */
+  int (*call_with_fs_of) (int pid, void (*func) (void *), void *arg);
 };
 
 extern struct target_ops *the_target;
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 5/7] Implement multiple-filesystem support for Linux targets
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (5 preceding siblings ...)
  2015-04-16 12:54 ` [PATCH 7/7] Implement vFile:setfs in gdbserver Gary Benson
@ 2015-04-16 13:06 ` Gary Benson
  2015-04-17 15:35 ` [PATCH 0/7] GNU/Linux mount namespace support Pedro Alves
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-16 13:06 UTC (permalink / raw)
  To: gdb-patches

This commit allows GDB to access executables and shared libraries
on native Linux targets where GDB and the inferior have different
filesystem namespaces.

gdb/ChangeLog:

	* linux-nat.c (fileio.h): New include.
	(nat/linux-namespaces.h): Likewise.
	(super_fileio_open): New static variable.
	(super_fileio_unlink): Likewise.
	(super_fileio_readlink): Likewise.
	(fs_ns_pid): Likewise.
	(linux_nat_fileio_set_fs): New function.
	(linux_nat_filesystem_is_local): Likewise.
	(linux_nat_enter_fs): Likewise.
	(open_closure): New structure.
	(linux_nat_fileio_open_1): New function.
	(linux_nat_fileio_open): Likewise.
	(unlink_closure): New structure.
	(linux_nat_fileio_unlink_1): New function.
	(linux_nat_fileio_unlink): Likewise.
	(linux_nat_add_target): Install new target methods.
	(readlink_closure): New structure.
	(linux_nat_fileio_readlink_1): New function.
	(linux_nat_fileio_readlink): Likewise.
---
 gdb/ChangeLog   |   22 ++++++
 gdb/linux-nat.c |  193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 215 insertions(+), 0 deletions(-)

diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index b04aa68..a54c704 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -66,6 +66,8 @@
 #include "target-descriptions.h"
 #include "filestuff.h"
 #include "objfiles.h"
+#include "fileio.h"
+#include "nat/linux-namespaces.h"
 
 #ifndef SPUFS_MAGIC
 #define SPUFS_MAGIC 0x23c9b64e
@@ -196,6 +198,24 @@ static target_xfer_partial_ftype *super_xfer_partial;
    Called by our to_close.  */
 static void (*super_close) (struct target_ops *);
 
+/* The saved to_fileio_open method, inherited from inf-child.c.
+   Called by our to_fileio_open.  */
+
+static int (*super_fileio_open) (struct target_ops *,
+				 const char *, int, int, int *);
+
+/* The saved to_fileio_unlink method, inherited from inf-child.c.
+   Called by our to_fileio_unlink.  */
+
+static int (*super_fileio_unlink) (struct target_ops *,
+				   const char *, int *);
+
+/* The saved to_fileio_readlink method, inherited from inf-child.c.
+   Called by our to_fileio_readlink.  */
+
+static char *(*super_fileio_readlink) (struct target_ops *,
+				       const char *, int *);
+
 static unsigned int debug_linux_nat;
 static void
 show_debug_linux_nat (struct ui_file *file, int from_tty,
@@ -4842,6 +4862,169 @@ linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid)
   return -1;
 }
 
+/* Process ID of inferior whose filesystem namespace the various
+   target_fileio functions will use.  Zero means to use our own.  */
+
+static int fs_ns_pid = 0;
+
+/* Implementation of to_fileio_set_fs.  */
+
+static void
+linux_nat_fileio_set_fs (struct target_ops *ops, int pid)
+{
+  fs_ns_pid = pid;
+}
+
+/* Implementation of to_filesystem_is_local.  */
+
+static int
+linux_nat_filesystem_is_local (struct target_ops *ops)
+{
+  return fs_ns_pid == 0
+    || linux_ns_same (getpid (), fs_ns_pid, LINUX_NS_MNT);
+}
+
+/* Enter the filesystem namespace of the process specified by
+   target_fileio_set_fs and call FUNC with the argument ARG,
+   restoring the original filesystem namespace afterwards.
+   Set TARGET_ERRNO if FUNC is not called.  */
+
+static void
+linux_nat_enter_fs (void (*func) (void *), void *arg, int *target_errno)
+{
+  if (fs_ns_pid == 0)
+    func (arg);
+  else if (!linux_ns_enter (fs_ns_pid, LINUX_NS_MNT, func, arg))
+    *target_errno = host_to_fileio_error (errno);
+}
+
+/* Arguments and return value of to_fileio_open.  */
+
+struct open_closure
+{
+  struct target_ops *ops;
+  const char *filename;
+  int flags;
+  int mode;
+  int *target_errno;
+  int return_value;
+};
+
+/* Helper for linux_nat_fileio_open.  */
+
+static void
+linux_nat_fileio_open_1 (void *arg)
+{
+  struct open_closure *clo = (struct open_closure *) arg;
+
+  clo->return_value = super_fileio_open (clo->ops, clo->filename,
+					 clo->flags, clo->mode,
+					 clo->target_errno);
+}
+
+/* Implementation of to_fileio_open.  */
+
+static int
+linux_nat_fileio_open (struct target_ops *ops,
+		       const char *filename, int flags, int mode,
+		       int *target_errno)
+{
+  struct open_closure clo =
+    {
+      /* Arguments.  */
+      ops, filename, flags, mode, target_errno,
+
+      /* Failure return value.  */
+      -1
+    };
+
+  linux_nat_enter_fs (linux_nat_fileio_open_1, &clo, target_errno);
+
+  return clo.return_value;
+}
+
+/* Arguments and return value of to_fileio_unlink.  */
+
+struct unlink_closure
+{
+  struct target_ops *ops;
+  const char *filename;
+  int *target_errno;
+  int return_value;
+};
+
+/* Helper for linux_nat_fileio_unlink.  */
+
+static void
+linux_nat_fileio_unlink_1 (void *arg)
+{
+  struct unlink_closure *clo = (struct unlink_closure *) arg;
+
+  clo->return_value = super_fileio_unlink (clo->ops, clo->filename,
+					   clo->target_errno);
+}
+
+/* Implementation of to_fileio_unlink.  */
+
+static int
+linux_nat_fileio_unlink (struct target_ops *ops,
+			   const char *filename, int *target_errno)
+{
+  struct unlink_closure clo =
+    {
+      /* Arguments.  */
+      ops, filename, target_errno,
+
+      /* Failure return value.  */
+      -1
+    };
+
+  linux_nat_enter_fs (linux_nat_fileio_unlink_1, &clo, target_errno);
+
+  return clo.return_value;
+}
+
+/* Arguments and return value of to_fileio_readlink.  */
+
+struct readlink_closure
+{
+  struct target_ops *ops;
+  const char *filename;
+  int *target_errno;
+  char *return_value;
+};
+
+/* Helper for linux_nat_fileio_readlink.  */
+
+static void
+linux_nat_fileio_readlink_1 (void *arg)
+{
+  struct readlink_closure *clo = (struct readlink_closure *) arg;
+
+  clo->return_value = super_fileio_readlink (clo->ops, clo->filename,
+					     clo->target_errno);
+}
+
+/* Implementation of to_fileio_readlink.  */
+
+static char *
+linux_nat_fileio_readlink (struct target_ops *ops,
+			   const char *filename, int *target_errno)
+{
+  struct readlink_closure clo =
+    {
+      /* Arguments.  */
+      ops, filename, target_errno,
+
+      /* Failure return value.  */
+      NULL
+    };
+
+  linux_nat_enter_fs (linux_nat_fileio_readlink_1, &clo, target_errno);
+
+  return clo.return_value;
+}
+
 void
 linux_nat_add_target (struct target_ops *t)
 {
@@ -4895,6 +5078,16 @@ linux_nat_add_target (struct target_ops *t)
 
   t->to_core_of_thread = linux_nat_core_of_thread;
 
+  /* Target File-I/O functions.  */
+  t->to_fileio_set_fs = linux_nat_fileio_set_fs;
+  t->to_filesystem_is_local = linux_nat_filesystem_is_local;
+  super_fileio_open = t->to_fileio_open;
+  t->to_fileio_open = linux_nat_fileio_open;
+  super_fileio_unlink = t->to_fileio_unlink;
+  t->to_fileio_unlink = linux_nat_fileio_unlink;
+  super_fileio_readlink = t->to_fileio_readlink;
+  t->to_fileio_readlink = linux_nat_fileio_readlink;
+
   /* We don't change the stratum; this target will sit at
      process_stratum and thread_db will set at thread_stratum.  This
      is a little strange, since this is a multi-threaded-capable
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-16 12:27 ` [PATCH 6/7] Implement multiple-filesystem support for remote targets Gary Benson
@ 2015-04-16 15:12   ` Eli Zaretskii
  2015-04-17 15:06   ` Pedro Alves
  2015-04-17 15:31   ` Pedro Alves
  2 siblings, 0 replies; 84+ messages in thread
From: Eli Zaretskii @ 2015-04-16 15:12 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches

> From: Gary Benson <gbenson@redhat.com>
> Date: Thu, 16 Apr 2015 13:19:50 +0100
> 
> gdb/doc/ChangeLog:
> 
> 	* gdb.texinfo (Remote Configuration): Document the
> 	"set/show remote hostio-setfs-packet" command.
> 	(Host I/O Packets): Document the vFile:setfs packet.
> ---
>  gdb/ChangeLog       |   18 +++++++++++++++
>  gdb/NEWS            |    8 +++++++
>  gdb/doc/ChangeLog   |    6 +++++
>  gdb/doc/gdb.texinfo |   11 +++++++++

I think the patch for the docs leaves too much unsaid to be useful.
E.g., after reading it, I was left as clueless as before regarding
what this feature is about.  What is a "mount namespace", for
starters?  What does it mean to "set a filesystem"?

Please consider explaining a bit of background about this in the
manual.

Thanks.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 1/7] Move make_cleanup_close to common code
  2015-04-16 12:20 ` [PATCH 1/7] Move make_cleanup_close to common code Gary Benson
@ 2015-04-17  2:47   ` Doug Evans
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Evans @ 2015-04-17  2:47 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches

On Thu, Apr 16, 2015 at 5:19 AM, Gary Benson <gbenson@redhat.com> wrote:
> This commit moves the function make_cleanup_close from gdb/utils.[ch]
> to gdb/common/cleanup-utils.[ch] to make it usable from common code.
> A new file was created over putting the function in common-utils.[ch]
> to avoid having to build cleanups.c into the in-process agent.
>
> gdb/ChangeLog:
>
>         * common/cleanup-utils.h: New file.
>         * common/cleanup-utils.c: Likewise.
>         * Makefile.in (SFILES): Add common/cleanup-utils.c.
>         (HFILES_NO_SRCDIR): Add common/cleanup-utils.h.
>         (COMMON_OBS): Add cleanup-utils.o.
>         (cleanup-utils.o): New rule.
>         * common/common-utils.h (cleanup-utils.h): New include.
>         * utils.h (make_cleanup_close): Moved to cleanup-utils.h.
>         * utils.c (do_close_cleanup): Moved to cleanup-utils.c.
>         (make_cleanup_close): Likewise.
>
> gdb/gdbserver/ChangeLog:
>
>         * Makefile.in (SFILES): Add common/cleanup-utils.c.
>         (OBS): Add cleanup-utils.o.
>         (cleanup-utils.o): New rule.

Hi.

I haven't reviewed the entire patch set (often I want to read the
whole thing first before sending reviews, but in the interests of
saving time ...).

LGTM.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/7] Introduce target_fileio_set_fs
  2015-04-16 12:20 ` [PATCH 2/7] Introduce target_fileio_set_fs Gary Benson
@ 2015-04-17  3:04   ` Doug Evans
  2015-04-17 13:36     ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Doug Evans @ 2015-04-17  3:04 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches

On Thu, Apr 16, 2015 at 5:19 AM, Gary Benson <gbenson@redhat.com> wrote:
> This commit introduces a new target method target_fileio_set_fs
> and adds calls to it in various places.  This allows support to
> be added for targets where processes do not share a common
> filesystem.
>
> gdb/ChangeLog:
>
>         * target.h (struct inferior): New forward declaration.
>         (struct target_ops) <to_fileio_set_fs>: New field.
>         (target_fileio_set_fs): New declaration.
>         * target-delegates.c: Regenerate.
>         * target.c (target_fileio_set_fs): New function.
>         * exec.c (exec_file_attach): Call target_fileio_set_fs.
>         * gdb_bfd.c (inferior.h): New include.
>         (gdb_bfd_iovec_fileio_open): Rename argument.  Call
>         target_fileio_set_fs.
>         (gdb_bfd_open): Call target_fileio_set_fs.  Pass current
>         inferior as argument to gdb_bfd_iovec_fileio_open.
>         * linux-tdep.c (linux_info_proc): Call target_fileio_set_fs.
>         (linux_find_memory_regions_full): Likewise.
>         (linux_fill_prpsinfo): Likewise.
>         * solib.c (solib_find_1): Likewise.
> ...
> diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
> index 9d75b66..44b2970 100644
> --- a/gdb/linux-tdep.c
> +++ b/gdb/linux-tdep.c
> @@ -715,6 +715,9 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
>    if (args && args[0])
>      error (_("Too many parameters: %s"), args);
>
> +  /* Access /proc/ from our filesystem.  */
> +  target_fileio_set_fs (NULL);
> +
>    printf_filtered (_("process %ld\n"), pid);
>    if (cmdline_f)
>      {

[here and elsewhere, but here's a good example]
It seems odd to have to continually set global state (the target fs)
like this before being able to access the fs.
Intuitively, I'd expect it to either be set once during some
initialization phase, and/or have something passed as a parameter on
down.

Perhaps things will become clearer later in the patch set, but if you
have reasons for doing it this way (that aren't mentioned elsewhere)
it'd be good to hear them.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 3/7] Introduce nat/linux-namespaces.[ch]
  2015-04-16 12:34 ` [PATCH 3/7] Introduce nat/linux-namespaces.[ch] Gary Benson
@ 2015-04-17  4:26   ` Doug Evans
  2015-04-17 13:41     ` Gary Benson
  2015-04-17 14:52   ` Pedro Alves
  1 sibling, 1 reply; 84+ messages in thread
From: Doug Evans @ 2015-04-17  4:26 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches

On Thu, Apr 16, 2015 at 5:19 AM, Gary Benson <gbenson@redhat.com> wrote:
> This commit introduces new shared files nat/linux-namespaces.[ch]
> containing code to support Linux namespaces that will be used by
> both GDB and gdbserver.
>
> gdb/ChangeLog:
>
>         * configure.ac (AC_CHECK_FUNCS): Add setns.
>         * config.in: Regenerate.
>         * configure: Likewise.
>         * nat/linux-namespaces.h: New file.
>         * nat/linux-namespaces.c: Likewise.
>         * Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-namespaces.h.
>         (linux-namespaces.o): New rule.
>         * config/aarch64/linux.mh (NATDEPFILES): Add linux-namespaces.o.
>         * config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
>         * config/arm/linux.mh (NATDEPFILES): Likewise.
>         * config/i386/linux.mh (NATDEPFILES): Likewise.
>         * config/i386/linux64.mh (NATDEPFILES): Likewise.
>         * config/ia64/linux.mh (NATDEPFILES): Likewise.
>         * config/m32r/linux.mh (NATDEPFILES): Likewise.
>         * config/m68k/linux.mh (NATDEPFILES): Likewise.
>         * config/mips/linux.mh (NATDEPFILES): Likewise.
>         * config/pa/linux.mh (NATDEPFILES): Likewise.
>         * config/powerpc/linux.mh (NATDEPFILES): Likewise.
>         * config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
>         * config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
>         * config/s390/linux.mh (NATDEPFILES): Likewise.
>         * config/sparc/linux.mh (NATDEPFILES): Likewise.
>         * config/sparc/linux64.mh (NATDEPFILES): Likewise.
>         * config/tilegx/linux.mh (NATDEPFILES): Likewise.
>         * config/xtensa/linux.mh (NATDEPFILES): Likewise.
>
> gdb/gdbserver/ChangeLog:
>
>         * configure.ac (AC_CHECK_FUNCS): Add setns.
>         * config.in: Regenerate.
>         * configure: Likewise.
>         * Makefile.in (SFILES): Add nat/linux-namespaces.c.
>         (linux-namespaces.o): New rule.
>         * configure.srv (srv_linux_obj): Add linux-namespaces.o.
> ...
> diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
> new file mode 100644
> index 0000000..f6fe863
> --- /dev/null
> +++ b/gdb/nat/linux-namespaces.c
> @@ -0,0 +1,231 @@
> +/* Linux namespaces(7) support.
> +
> +   Copyright (C) 2015 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 "nat/linux-namespaces.h"
> +#include "filestuff.h"
> +#include <fcntl.h>
> +#include <sys/syscall.h>
> +#include <sys/stat.h>
> +
> +/* Handle systems with __NR_setns but no setns.  */
> +#if defined(__NR_setns) && !defined(HAVE_SETNS)
> +static int
> +setns (int fd, int nstype)
> +{
> +  return syscall (__NR_setns, fd, nstype);
> +}
> +#define HAVE_SETNS 1
> +#endif /* defined(__NR_setns) && !defined(HAVE_SETNS) */

Nit:
I understand the goal here, but I think it would be better to do this
slightly differently.
The value of HAVE_SETNS is potentially different in this file than for
the rest of gdb,
and I generally think of config.h as being consistent across the app.
I don't have a strong preference on how to change this, other than I
think values
defined in config.h should be left alone.
E.g., one could just just define another macro locally here.

#if defined(__NR_setns) || defined(HAVE_SETNS)
#define REALLY_HAVE_SETNS 1
#endif

#ifdef REALLY_HAVE_SETNS
... the rest of the file ...

or some such.

> +
> +#ifdef HAVE_SETNS
> +
> +/* Return the path of the TYPE namespace entry for process PID.
> +   The returned value persists until this function is next called.  */
> +
> +static const char *
> +linux_ns_path_for (int pid, const char *type)
> +{
> +  static char path[PATH_MAX];
> +
> +  xsnprintf (path, sizeof (path), "/proc/%d/ns/%s", pid, type);
> +
> +  return path;
> +}
> +
> +/* See nat/linux-namespaces.h.  */
> +
> +int
> +linux_ns_same (int pid1, int pid2, const char *type)
> +{
> +  const char *path;
> +  struct stat sb;
> +  ino_t pid1_id;
> +
> +  if (pid1 == pid2)
> +    return 1;
> +
> +  /* Lack of kernel support for TYPE namespaces is detected by
> +     attempting to open our own.  Try to make PID1 be our own
> +     PID so we don't have to do extra checking if the the first
> +     stat fails.  */
> +  if (pid2 == getpid ())
> +    {
> +      int swap = pid1;
> +
> +      pid1 = pid2;
> +      pid2 = swap;
> +    }
> +
> +  path = linux_ns_path_for (pid1, type);
> +  if (stat (path, &sb) != 0)
> +    {
> +      int saved_errno;
> +
> +      if (pid1 == getpid ())
> +       {
> +         /* Assume the kernel does not support TYPE namespaces.  */
> +         return 1;
> +       }
> +
> +      saved_errno = errno;
> +      path = linux_ns_path_for (getpid (), type);
> +      if (stat (path, &sb) != 0)
> +       {
> +         /* Assume the kernel does not support TYPE namespaces.  */
> +         return 1;
> +       }
> +
> +      /* We can open our own TYPE namespace but not that for process
> +        PID.  The process might have died, or we might not have the
> +        right permissions (though we should be attached by this time
> +        so this seems unlikely).  In any event, we cannot make any
> +        decisions and must throw.  */
> +      errno = saved_errno;
> +      perror_with_name (linux_ns_path_for (pid1, type));
> +    }
> +  pid1_id = sb.st_ino;
> +
> +  /* The kernel definitely supports TYPE namespaces so we cannot
> +     make any decisions if this stat fails.  */
> +  path = linux_ns_path_for (pid2, type);
> +  if (stat (path, &sb) != 0)
> +    perror_with_name (path);
> +
> +  return sb.st_ino == pid1_id;
> +}
> +
> +/* Helper function which does the work for make_cleanup_setns.  */
> +
> +static void
> +do_setns_cleanup (void *arg)
> +{
> +  int *fd = arg;
> +
> +  if (setns (*fd, 0) != 0)
> +    internal_error (__FILE__, __LINE__,
> +                   _("unable to restore namespace: %s"),
> +                   safe_strerror (errno));
> +}
> +
> +/* Return a new cleanup that calls setns on FD.  */
> +
> +static struct cleanup *
> +make_cleanup_setns (int fd)
> +{
> +  int *saved_fd = xmalloc (sizeof (fd));
> +
> +  *saved_fd = fd;
> +  return make_cleanup_dtor (do_setns_cleanup, saved_fd, xfree);
> +}
> +
> +
> +/* See nat/linux-namespaces.h.  */
> +
> +int
> +linux_ns_enter (int pid, const char *type,
> +               void (*func) (void *), void *arg)
> +{
> +  struct cleanup *old_chain, *close_pidfd;
> +  int our_fd, pid_fd;
> +  struct stat sb;
> +  ino_t our_id;
> +
> +  /* Open our TYPE namespace.  On failure, assume the kernel does
> +     not support TYPE namespaces (so every process is in the same
> +     TYPE namespace) and just call FUNC with ARG and return.  */
> +  our_fd = gdb_open_cloexec (linux_ns_path_for (getpid(), type),
> +                            O_RDONLY, 0);
> +  if (our_fd < 0)
> +    {
> +      func (arg);
> +      return 1;
> +    }
> +  old_chain = make_cleanup_close (our_fd);
> +
> +  /* We've successfully opened our own TYPE namespace.  The kernel
> +     obviously supports TYPE namespaces and any subsequent errors
> +     cannot be continued over.  */
> +
> +  if (fstat (our_fd, &sb) != 0)
> +    {
> +      do_cleanups (old_chain);
> +      return 0;
> +    }
> +  our_id = sb.st_ino;
> +
> +  pid_fd = gdb_open_cloexec (linux_ns_path_for (pid, type),
> +                            O_RDONLY, 0);
> +  if (pid_fd < 0)
> +    {
> +      do_cleanups (old_chain);
> +      return 0;
> +    }
> +  close_pidfd = make_cleanup_close (pid_fd);
> +
> +  if (fstat (pid_fd, &sb) != 0)
> +    {
> +      do_cleanups (old_chain);
> +      return 0;
> +    }
> +
> +  if (sb.st_ino == our_id)
> +    {
> +      /* The other process has the same TYPE namespace as us.  */
> +      do_cleanups (old_chain);
> +      func (arg);
> +      return 1;
> +    }
> +
> +  if (setns (pid_fd, 0) != 0)
> +    {
> +      do_cleanups (old_chain);
> +      return 0;
> +    }
> +  do_cleanups (close_pidfd);
> +  make_cleanup_setns (our_fd);
> +
> +  func (arg);
> +
> +  do_cleanups (old_chain);
> +  return 1;
> +}
> +
> +#else /* HAVE_SETNS */

GNU coding convention says to write this as /*  not HAVE_SETNS */
though I think /* !HAVE_SETNS */ is ok too.
http://www.gnu.org/prep/standards/standards.html#Comments
[I like this convention.]

> +
> +/* See nat/linux-namespaces.h.  */
> +
> +int
> +linux_ns_same (int pid1, int pid2, const char *type)
> +{
> +  return 1;
> +}
> +
> +/* See nat/linux-namespaces.h.  */
> +
> +int
> +linux_ns_enter (int pid, const char *type,
> +               void (*func) (void *), void *arg)
> +{
> +  func (arg);
> +
> +  return 1;
> +}
> +
> +#endif  /* HAVE_SETNS */

/* !HAVE_SETNS */ or /* not HAVE_SETNS */

> diff --git a/gdb/nat/linux-namespaces.h b/gdb/nat/linux-namespaces.h
> new file mode 100644
> index 0000000..0e94c07
> --- /dev/null
> +++ b/gdb/nat/linux-namespaces.h
> @@ -0,0 +1,61 @@
> +/* Linux namespaces(7) support.
> +
> +   Copyright (C) 2015 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 LINUX_NAMESPACES_H
> +#define LINUX_NAMESPACES_H
> +
> +/* Filenames of Linux namespaces in /proc/PID/ns.  */
> +
> +/* IPC namespace: System V IPC, POSIX message queues.  */
> +#define LINUX_NS_IPC "ipc"
> +
> +/* Mount namespace: mount points.  */
> +#define LINUX_NS_MNT "mnt"
> +
> +/* Network namespace: network devices, stacks, ports, etc.  */
> +#define LINUX_NS_NET "net"
> +
> +/* PID namespace: process IDs.  */
> +#define LINUX_NS_PID "pid"
> +
> +/* User namespace: user and group IDs.  */
> +#define LINUX_NS_USER "user"
> +
> +/* UTS namespace: hostname and NIS domain name.  */
> +#define LINUX_NS_UTS "uts"
> +

extra blank line

> +
> +/* Return nonzero if processes PID1 and PID2 have the same TYPE
> +   namespace, or if the kernel does not support TYPE namespaces
> +   (in which case there is only one TYPE namespace).  Return zero
> +   if the kernel supports TYPE namespaces and the two processes
> +   have different TYPE namespaces.  */
> +
> +extern int linux_ns_same (int pid1, int pid2, const char *type);
> +
> +/* Enter the TYPE namespace of process PID and call FUNC with the
> +   argument ARG, returning to the original TYPE namespace afterwards.
> +   If process PID has the same TYPE namespace as the current process,
> +   or if TYPE namespaces are not supported, just call FUNC with ARG.
> +   Return nonzero if FUNC was called, zero otherwise (and set ERRNO). */
> +
> +extern int linux_ns_enter (int pid, const char *type,
> +                          void (*func) (void *), void *arg);
> +
> +#endif /* LINUX_NAMESPACES_H */

Otherwise LGTM.
[still reading patches in order though]

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 4/7] Remove linux_proc_pid_get_ns
  2015-04-16 12:19 ` [PATCH 4/7] Remove linux_proc_pid_get_ns Gary Benson
@ 2015-04-17  4:36   ` Doug Evans
  2015-04-17 13:44     ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Doug Evans @ 2015-04-17  4:36 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches

On Thu, Apr 16, 2015 at 5:19 AM, Gary Benson <gbenson@redhat.com> wrote:
> This commit removes linux_proc_pid_get_ns, and updates its only
> use to use linux_ns_same instead.
>
> gdb/ChangeLog:
>
>         * linux-thread-db.c (nat/linux-namespaces.h): New include.
>         (check_pid_namespace_match): Use linux_ns_same rather than
>         linux_proc_pid_get_ns to spot PID namespace mismatches.
>         * nat/linux-procfs.h (linux_proc_pid_get_ns): Remove.
>         * nat/linux-procfs.c (linux_proc_pid_get_ns): Likewise.

LGTM.
one nit below

> diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c
> index 44364c5..24bcb01 100644
> --- a/gdb/nat/linux-procfs.c
> +++ b/gdb/nat/linux-procfs.c
> @@ -185,25 +185,6 @@ linux_proc_pid_is_zombie (pid_t pid)
>    return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
>  }
>
> -/* See linux-procfs.h declaration.  */
> -
> -char *
> -linux_proc_pid_get_ns (pid_t pid, const char *ns)
> -{
> -  char buf[100];
> -  char nsval[64];
> -  int ret;
> -  xsnprintf (buf, sizeof (buf), "/proc/%d/ns/%s", (int) pid, ns);
> -  ret = readlink (buf, nsval, sizeof (nsval));
> -  if (0 < ret && ret < sizeof (nsval))
> -    {
> -      nsval[ret] = '\0';
> -      return xstrdup (nsval);
> -    }
> -
> -  return NULL;
> -}

I see we're using pid_t here.
I think we talked before about a type for pids.
Since this is all linux specific code maybe use pid_t more in this patch set?

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/7] Introduce target_fileio_set_fs
  2015-04-17  3:04   ` Doug Evans
@ 2015-04-17 13:36     ` Gary Benson
  2015-04-17 14:21       ` Pedro Alves
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-17 13:36 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

Doug Evans wrote:
> On Thu, Apr 16, 2015 at 5:19 AM, Gary Benson <gbenson@redhat.com> wrote:
> > This commit introduces a new target method target_fileio_set_fs
> > and adds calls to it in various places.  This allows support to
> > be added for targets where processes do not share a common
> > filesystem.
> > 
[snip]
> > 
> > diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
> > index 9d75b66..44b2970 100644
> > --- a/gdb/linux-tdep.c
> > +++ b/gdb/linux-tdep.c
> > @@ -715,6 +715,9 @@ linux_info_proc
> >    if (args && args[0])
> >      error (_("Too many parameters: %s"), args);
> >
> > +  /* Access /proc/ from our filesystem.  */
> > +  target_fileio_set_fs (NULL);
> > +
> >    printf_filtered (_("process %ld\n"), pid);
> >    if (cmdline_f)
> >      {
> 
> [here and elsewhere, but here's a good example]
> It seems odd to have to continually set global state (the target fs)
> like this before being able to access the fs.
> Intuitively, I'd expect it to either be set once during some
> initialization phase, and/or have something passed as a parameter
> on down.
> 
> Perhaps things will become clearer later in the patch set, but if
> you have reasons for doing it this way (that aren't mentioned
> elsewhere) it'd be good to hear them.

It was basically because the alternative was to add a parameter to
target_filesystem_is_local and target_fileio_{open,readlink,unlink}
(and all their target vector implementations) to pass around whatever
inferior you were talking about.  You'd also have to make a lot more
changes to the remote protocol: either vFile:{open,unlink,readlink}
would need an extra argument (indicated with qSupported) or you'd need
new "fs" versions of each packet.  Both Pedro and I thought that was
ugly.

Thanks,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 3/7] Introduce nat/linux-namespaces.[ch]
  2015-04-17  4:26   ` Doug Evans
@ 2015-04-17 13:41     ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-17 13:41 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

Doug Evans wrote:
> On Thu, Apr 16, 2015 at 5:19 AM, Gary Benson <gbenson@redhat.com> wrote:
> > diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
> > new file mode 100644
> > index 0000000..f6fe863
> > --- /dev/null
> > +++ b/gdb/nat/linux-namespaces.c
> > @@ -0,0 +1,231 @@
[snip]
> > +#include "common-defs.h"
> > +#include "nat/linux-namespaces.h"
> > +#include "filestuff.h"
> > +#include <fcntl.h>
> > +#include <sys/syscall.h>
> > +#include <sys/stat.h>
> > +
> > +/* Handle systems with __NR_setns but no setns.  */
> > +#if defined(__NR_setns) && !defined(HAVE_SETNS)
> > +static int
> > +setns (int fd, int nstype)
> > +{
> > +  return syscall (__NR_setns, fd, nstype);
> > +}
> > +#define HAVE_SETNS 1
> > +#endif /* defined(__NR_setns) && !defined(HAVE_SETNS) */
> 
> Nit:
> I understand the goal here, but I think it would be better to do
> this slightly differently.
> The value of HAVE_SETNS is potentially different in this file than
> for the rest of gdb,
> and I generally think of config.h as being consistent across the app.
> I don't have a strong preference on how to change this, other than I
> think values defined in config.h should be left alone.

The value of HAVE_SETNS is potentially different in this file than for
the rest of gdb, but so is the existence of a setns function.  That's
why I did it that way.  I certainly didn't want to make our own setns
available to any other file, as really anything accessing namespaces
should go through this file.

> E.g., one could just just define another macro locally here.
> 
> #if defined(__NR_setns) || defined(HAVE_SETNS)
> #define REALLY_HAVE_SETNS 1
> #endif
> 
> #ifdef REALLY_HAVE_SETNS
> ... the rest of the file ...
> 
> or some such.

I could do that (I'd probably call it HAVE_LINUX_NAMESPACES).
I prefer the way I did it but I won't fight this.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 4/7] Remove linux_proc_pid_get_ns
  2015-04-17  4:36   ` Doug Evans
@ 2015-04-17 13:44     ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-17 13:44 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

Doug Evans wrote:
> On Thu, Apr 16, 2015 at 5:19 AM, Gary Benson <gbenson@redhat.com> wrote:
> > This commit removes linux_proc_pid_get_ns, and updates its only
> > use to use linux_ns_same instead.
> >
> > gdb/ChangeLog:
> >
> >         * linux-thread-db.c (nat/linux-namespaces.h): New include.
> >         (check_pid_namespace_match): Use linux_ns_same rather than
> >         linux_proc_pid_get_ns to spot PID namespace mismatches.
> >         * nat/linux-procfs.h (linux_proc_pid_get_ns): Remove.
> >         * nat/linux-procfs.c (linux_proc_pid_get_ns): Likewise.
> 
> LGTM.
> one nit below
[snip]
> I see we're using pid_t here.
> I think we talked before about a type for pids.
> Since this is all linux specific code maybe use pid_t more in this
> patch set?

I could do that.  It would likely only be in linux-namespaces.[ch]
and maybe one or two places in linux-nat.c, all the other stuff is
in the target vectors.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/7] Introduce target_fileio_set_fs
  2015-04-17 13:36     ` Gary Benson
@ 2015-04-17 14:21       ` Pedro Alves
  2015-04-17 17:28         ` Doug Evans
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 14:21 UTC (permalink / raw)
  To: Gary Benson, Doug Evans; +Cc: gdb-patches

On 04/17/2015 02:36 PM, Gary Benson wrote:

> It was basically because the alternative was to add a parameter to
> target_filesystem_is_local and target_fileio_{open,readlink,unlink}
> (and all their target vector implementations) to pass around whatever
> inferior you were talking about.  You'd also have to make a lot more
> changes to the remote protocol: either vFile:{open,unlink,readlink}
> would need an extra argument (indicated with qSupported) or you'd need
> new "fs" versions of each packet.  Both Pedro and I thought that was
> ugly.

Right, this way mirrors what's done at the posix/system call level too,
and if some other systems needs something different for selecting
a "filesystem namespace", there's a single method/packet to change.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 3/7] Introduce nat/linux-namespaces.[ch]
  2015-04-16 12:34 ` [PATCH 3/7] Introduce nat/linux-namespaces.[ch] Gary Benson
  2015-04-17  4:26   ` Doug Evans
@ 2015-04-17 14:52   ` Pedro Alves
  2015-04-17 17:32     ` Doug Evans
  1 sibling, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 14:52 UTC (permalink / raw)
  To: Gary Benson, gdb-patches

On 04/16/2015 01:19 PM, Gary Benson wrote:

> +  path = linux_ns_path_for (pid1, type);
> +  if (stat (path, &sb) != 0)
> +    {
> +      int saved_errno;
> +
> +      if (pid1 == getpid ())
> +	{
> +	  /* Assume the kernel does not support TYPE namespaces.  */
> +	  return 1;
> +	}
> +
> +      saved_errno = errno;

Don't assume any function preserves errno.  Save this right after
stat.

> +      path = linux_ns_path_for (getpid (), type);
> +      if (stat (path, &sb) != 0)
> +	{
> +	  /* Assume the kernel does not support TYPE namespaces.  */
> +	  return 1;
> +	}
> +
> +      /* We can open our own TYPE namespace but not that for process
> +	 PID.  The process might have died, or we might not have the
> +	 right permissions (though we should be attached by this time
> +	 so this seems unlikely).  In any event, we cannot make any
> +	 decisions and must throw.  */
> +      errno = saved_errno;
> +      perror_with_name (linux_ns_path_for (pid1, type));
> +    }
> +  pid1_id = sb.st_ino;
> +
> +  /* The kernel definitely supports TYPE namespaces so we cannot
> +     make any decisions if this stat fails.  */
> +  path = linux_ns_path_for (pid2, type);
> +  if (stat (path, &sb) != 0)
> +    perror_with_name (path);
> +
> +  return sb.st_ino == pid1_id;
> +}
> +
> +/* Helper function which does the work for make_cleanup_setns.  */
> +
> +static void
> +do_setns_cleanup (void *arg)
> +{
> +  int *fd = arg;
> +
> +  if (setns (*fd, 0) != 0)
> +    internal_error (__FILE__, __LINE__,
> +		    _("unable to restore namespace: %s"),
> +		    safe_strerror (errno));

And here

  if (setns (*fd, 0) != 0)
    {
       int saved_errno = errno;

       internal_error (__FILE__, __LINE__,
	   	    _("unable to restore namespace: %s"),
		    safe_strerror (saved_errno));
    }

because _() is a function call, and you can't rely on
whether safe_strerror is called before or after.


> +/* Enter the TYPE namespace of process PID and call FUNC with the
> +   argument ARG, returning to the original TYPE namespace afterwards.
> +   If process PID has the same TYPE namespace as the current process,
> +   or if TYPE namespaces are not supported, just call FUNC with ARG.
> +   Return nonzero if FUNC was called, zero otherwise (and set ERRNO). */
> +
> +extern int linux_ns_enter (int pid, const char *type,
> +			   void (*func) (void *), void *arg);


So the function:

 #1 - enters the namespace
 #2 - calls func
 #3 - exits the namespace.

IMO, "linux_ns_ENTER" isn't a good name for that.  I'd expect that a function
called "enter" do just #1 above.  Something like "linux_ns_do",
"linux_do_in_ns", "linux_in_ns", etc., would be clearer, IMO.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-16 12:27 ` [PATCH 6/7] Implement multiple-filesystem support for remote targets Gary Benson
  2015-04-16 15:12   ` Eli Zaretskii
@ 2015-04-17 15:06   ` Pedro Alves
  2015-04-17 16:00     ` Gary Benson
  2015-04-17 15:31   ` Pedro Alves
  2 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 15:06 UTC (permalink / raw)
  To: Gary Benson, gdb-patches

On 04/16/2015 01:19 PM, Gary Benson wrote:
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -367,6 +367,12 @@ struct remote_state
>  
>    /* The branch trace configuration.  */
>    struct btrace_config btrace_config;
> +
> +  /* The argument to the last "vFile:setfs:" packet we sent, used
> +     to avoid sending repeated unnecessary "vFile:setfs:" packets.
> +     Initialized to -1 to indicate that no "vFile:setfs:" packet
> +     has yet been sent.  */
> +  int fs_pid;
>  };
>  

> +/* Process ID of inferior whose filesystem remote_hostio functions
> +   that take FILENAME arguments will use.  Zero means to use the
> +   remote stub's filesystem.  */
> +
> +static int remote_fs_pid = 0;

What's the rationale for not putting this one in "struct remote_state" ?

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 7/7] Implement vFile:setfs in gdbserver
  2015-04-16 12:54 ` [PATCH 7/7] Implement vFile:setfs in gdbserver Gary Benson
@ 2015-04-17 15:30   ` Pedro Alves
  2015-04-17 16:47     ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 15:30 UTC (permalink / raw)
  To: Gary Benson, gdb-patches

On 04/16/2015 01:19 PM, Gary Benson wrote:
> +/* Handle a "vFile:setfs:" packet.  */
> +
> +static void
> +handle_setfs (char *own_buf)
> +{
> +  char *p;
> +  int pid;
> +
> +  p = own_buf + strlen ("vFile:setfs:");
> +
> +  if (require_int (&p, &pid)
> +      || pid < 0
> +      || require_end (p))
> +    {
> +      hostio_packet_error (own_buf);
> +      return;
> +    }
> +
> +  hostio_fs_pid = pid;
> +
> +  hostio_reply (own_buf, 0);
> +}

This should probably return empty if
the_target->call_with_fs_of is NULL, to disable the packet
in GDB?

>  int
>  handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
>  {
> -  if (startswith (own_buf, "vFile:open:"))
> +  if (the_target->call_with_fs_of != NULL
> +      && startswith (own_buf, "vFile:setfs:"))
> +    handle_setfs (own_buf);
> +  else if (startswith (own_buf, "vFile:open:"))

Ah, I see now that it's handled here.  I'd prefer moving that check
inside the handle_setfs function instead so that the "setfs"
specifics handling is all localized.

> +struct open_closure
> +{
> +  char filename[HOSTIO_PATH_MAX];
> +  int flags;
> +  int mode;

mode_t mode.

(please check for the the same issue on the native side.)

> +  int return_value;
> +};

> +/* Implementation of target_ops->call_with_fs_of.  */
> +
> +static int
> +linux_low_call_with_fs_of (int pid, void (*func) (void *), void *arg)
> +{
> +  return linux_ns_enter (pid, LINUX_NS_MNT, func, arg);
> +}
> +

So back on linux_ns_enter's naming ---

I find the abstraction here a bit odd.  It seems to be me that
a function that does:

 #1 - select filesystem/namespace
 #2 - call foo
 #3 - restore filesystem/namespace

should be a function in common code, and that the only
target-specific part is selecting a filesystem/namespace.
That is, simplifying, something like:

/* Cause the filesystem to appear as it does to process PID and
   call FUNC with argument ARG, restoring the filesystem to its
   original state afterwards.  Return nonzero if FUNC was called,
   zero otherwise (and set ERRNO). */

int
call_with_fs_of (int pid, void (*func) (void *), void *arg)
{
  int ret;

  target->select_fs (pid);
  ret = func ();
  target->select_fs (0);
  return ret;
}

Was there a reason this wasn't done that way?

(maybe make target->select_fs() return the previous
namespace, instead of passing 0 on the second
call.)

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-16 12:27 ` [PATCH 6/7] Implement multiple-filesystem support for remote targets Gary Benson
  2015-04-16 15:12   ` Eli Zaretskii
  2015-04-17 15:06   ` Pedro Alves
@ 2015-04-17 15:31   ` Pedro Alves
  2015-04-17 16:01     ` Gary Benson
  2 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 15:31 UTC (permalink / raw)
  To: Gary Benson, gdb-patches

On 04/16/2015 01:19 PM, Gary Benson wrote:

> diff --git a/gdb/NEWS b/gdb/NEWS
> index 62cbdcb..a9f05e4 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -42,6 +42,10 @@
>    (no "set sysroot" or "file" commands are required).  See "New remote
>    packets" below.
>  
> +* GDB and gdbserver now support attaching to processes running in
> +  different mount namespaces from the debugger on GNU/Linux systems.
> +  See "New remote packets" below.

Reading this, I'm left wondering what this really means, because I
think we could already attach before.  What the user needed to do before
was point the "set sysroot" somewhere, while now, if the sysroot
is left to "target:", that's no longer necessary.  Is that right?

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 0/7] GNU/Linux mount namespace support
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (6 preceding siblings ...)
  2015-04-16 13:06 ` [PATCH 5/7] Implement multiple-filesystem support for Linux targets Gary Benson
@ 2015-04-17 15:35 ` Pedro Alves
  2015-04-20 16:49 ` Iago López Galeiras
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 15:35 UTC (permalink / raw)
  To: Gary Benson, gdb-patches

On 04/16/2015 01:19 PM, Gary Benson wrote:

> Ok to commit?

It looks good to me, apart from some details.  I'll be
happy when the issues raised (by me, Doug and everyone
else, of course) in the particular patches are addressed.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-17 15:06   ` Pedro Alves
@ 2015-04-17 16:00     ` Gary Benson
  2015-04-17 16:07       ` Pedro Alves
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-17 16:00 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves wrote:
> On 04/16/2015 01:19 PM, Gary Benson wrote:
> > --- a/gdb/remote.c
> > +++ b/gdb/remote.c
> > @@ -367,6 +367,12 @@ struct remote_state
> >  
> >    /* The branch trace configuration.  */
> >    struct btrace_config btrace_config;
> > +
> > +  /* The argument to the last "vFile:setfs:" packet we sent, used
> > +     to avoid sending repeated unnecessary "vFile:setfs:" packets.
> > +     Initialized to -1 to indicate that no "vFile:setfs:" packet
> > +     has yet been sent.  */
> > +  int fs_pid;
> >  };
> >  
> 
> > +/* Process ID of inferior whose filesystem remote_hostio functions
> > +   that take FILENAME arguments will use.  Zero means to use the
> > +   remote stub's filesystem.  */
> > +
> > +static int remote_fs_pid = 0;
> 
> What's the rationale for not putting this one in "struct
> remote_state" ?

I don't have one :)  Would you prefer it there?

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-17 15:31   ` Pedro Alves
@ 2015-04-17 16:01     ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-17 16:01 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves wrote:
> On 04/16/2015 01:19 PM, Gary Benson wrote:
> > diff --git a/gdb/NEWS b/gdb/NEWS
> > index 62cbdcb..a9f05e4 100644
> > --- a/gdb/NEWS
> > +++ b/gdb/NEWS
> > @@ -42,6 +42,10 @@
> >    (no "set sysroot" or "file" commands are required).  See "New remote
> >    packets" below.
> >  
> > +* GDB and gdbserver now support attaching to processes running in
> > +  different mount namespaces from the debugger on GNU/Linux systems.
> > +  See "New remote packets" below.
> 
> Reading this, I'm left wondering what this really means, because I
> think we could already attach before.  What the user needed to do
> before was point the "set sysroot" somewhere, while now, if the
> sysroot is left to "target:", that's no longer necessary.  Is that
> right?

Yeah, it's more about accessing files than attaching per se.
I think I need to spend some time rewriting the docs for this
series...

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-17 16:00     ` Gary Benson
@ 2015-04-17 16:07       ` Pedro Alves
  2015-04-17 16:20         ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 16:07 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches

On 04/17/2015 04:59 PM, Gary Benson wrote:
> Pedro Alves wrote:
>> On 04/16/2015 01:19 PM, Gary Benson wrote:
>>> --- a/gdb/remote.c
>>> +++ b/gdb/remote.c
>>> @@ -367,6 +367,12 @@ struct remote_state
>>>  
>>>    /* The branch trace configuration.  */
>>>    struct btrace_config btrace_config;
>>> +
>>> +  /* The argument to the last "vFile:setfs:" packet we sent, used
>>> +     to avoid sending repeated unnecessary "vFile:setfs:" packets.
>>> +     Initialized to -1 to indicate that no "vFile:setfs:" packet
>>> +     has yet been sent.  */
>>> +  int fs_pid;
>>>  };
>>>  
>>
>>> +/* Process ID of inferior whose filesystem remote_hostio functions
>>> +   that take FILENAME arguments will use.  Zero means to use the
>>> +   remote stub's filesystem.  */
>>> +
>>> +static int remote_fs_pid = 0;
>>
>> What's the rationale for not putting this one in "struct
>> remote_state" ?
> 
> I don't have one :)  Would you prefer it there?

It's not really about personal preference: if on a
multi-remote-connections world the flag would be remote connection
specific, it should be in remote_state.  It seemed that way
to me, but if it isn't, then it should be left a global.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/7] Implement multiple-filesystem support for remote targets
  2015-04-17 16:07       ` Pedro Alves
@ 2015-04-17 16:20         ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-17 16:20 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves wrote:
> On 04/17/2015 04:59 PM, Gary Benson wrote:
> > Pedro Alves wrote:
> >> On 04/16/2015 01:19 PM, Gary Benson wrote:
> > > > --- a/gdb/remote.c
> > > > +++ b/gdb/remote.c
> > > > @@ -367,6 +367,12 @@ struct remote_state
> > > >  
> > > >    /* The branch trace configuration.  */
> > > >    struct btrace_config btrace_config;
> > > > +
> > > > +  /* The argument to the last "vFile:setfs:" packet we sent, used
> > > > +     to avoid sending repeated unnecessary "vFile:setfs:" packets.
> > > > +     Initialized to -1 to indicate that no "vFile:setfs:" packet
> > > > +     has yet been sent.  */
> > > > +  int fs_pid;
> > > >  };
> > > >  
> > >
> > > > +/* Process ID of inferior whose filesystem remote_hostio functions
> > > > +   that take FILENAME arguments will use.  Zero means to use the
> > > > +   remote stub's filesystem.  */
> > > > +
> > > > +static int remote_fs_pid = 0;
> > >
> > > What's the rationale for not putting this one in "struct
> > > remote_state" ?
> > 
> > I don't have one :)  Would you prefer it there?
> 
> It's not really about personal preference: if on a
> multi-remote-connections world the flag would be remote connection
> specific, it should be in remote_state.  It seemed that way to me,
> but if it isn't, then it should be left a global.

Ah, it is probably connection-specific, I'll move it.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 7/7] Implement vFile:setfs in gdbserver
  2015-04-17 16:47     ` Gary Benson
@ 2015-04-17 16:29       ` Gary Benson
  2015-04-17 17:09         ` Pedro Alves
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-17 16:29 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Gary Benson wrote:
> Pedro Alves wrote:
> > So back on linux_ns_enter's naming ---
> > 
> > I find the abstraction here a bit odd.  It seems to be me that
> > a function that does:
> > 
> >  #1 - select filesystem/namespace
> >  #2 - call foo
> >  #3 - restore filesystem/namespace
> > 
> > should be a function in common code, and that the only
> > target-specific part is selecting a filesystem/namespace.
> > That is, simplifying, something like:
> > 
> > /* Cause the filesystem to appear as it does to process PID and
> >    call FUNC with argument ARG, restoring the filesystem to its
> >    original state afterwards.  Return nonzero if FUNC was called,
> >    zero otherwise (and set ERRNO). */
> > 
> > int
> > call_with_fs_of (int pid, void (*func) (void *), void *arg)
> > {
> >   int ret;
> > 
> >   target->select_fs (pid);
> >   ret = func ();
> >   target->select_fs (0);
> >   return ret;
> > }
> > 
> > Was there a reason this wasn't done that way?
> > 
> > (maybe make target->select_fs() return the previous
> > namespace, instead of passing 0 on the second
> > call.)
> 
> I'll have a go at doing it that way.

It is kind of uglier doing it that way.  It would need to look
something more like this:

  struct cleanup **old_chain;

  if (target->select_fs (pid, &old_chain) != 0)
     return failure_return_value;
  ret = func ();
  do_cleanups (old_chain);
  return ret;

linux_ns_enter has to open file descriptors for its own namespace
and the one it wants to enter.  Its own namespace file descriptor
is what it needs to return, and it has to be held open: you can't
flip namespace and then open your own descriptor to flip back.
So the thing target->select_fs would have to return would be an
open file descriptor (to then pass to target->restore_fs, which
would take a file descriptor argument rather than an PID) but
that would be putting a Linuxism into the target vector.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 7/7] Implement vFile:setfs in gdbserver
  2015-04-17 15:30   ` Pedro Alves
@ 2015-04-17 16:47     ` Gary Benson
  2015-04-17 16:29       ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-17 16:47 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves wrote:
> On 04/16/2015 01:19 PM, Gary Benson wrote:
> > +/* Handle a "vFile:setfs:" packet.  */
> > +
> > +static void
> > +handle_setfs (char *own_buf)
> > +{
[snip]
> > +}
> 
> This should probably return empty if the_target->call_with_fs_of is
> NULL, to disable the packet in GDB?
> 
> >  int
> >  handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
> >  {
> > -  if (startswith (own_buf, "vFile:open:"))
> > +  if (the_target->call_with_fs_of != NULL
> > +      && startswith (own_buf, "vFile:setfs:"))
> > +    handle_setfs (own_buf);
> > +  else if (startswith (own_buf, "vFile:open:"))
> 
> Ah, I see now that it's handled here.  I'd prefer moving that
> check inside the handle_setfs function instead so that the "setfs"
> specifics handling is all localized.

Ok.

> > +struct open_closure
> > +{
> > +  char filename[HOSTIO_PATH_MAX];
> > +  int flags;
> > +  int mode;
> 
> mode_t mode.
> 
> (please check for the the same issue on the native side.)

It's there in both places.  Is mode_t ok to use in gdbserver?
I don't see it anywhere...

> > +  int return_value;
> > +};
> 
> > +/* Implementation of target_ops->call_with_fs_of.  */
> > +
> > +static int
> > +linux_low_call_with_fs_of (int pid, void (*func) (void *), void *arg)
> > +{
> > +  return linux_ns_enter (pid, LINUX_NS_MNT, func, arg);
> > +}
> > +
> 
> So back on linux_ns_enter's naming ---
> 
> I find the abstraction here a bit odd.  It seems to be me that
> a function that does:
> 
>  #1 - select filesystem/namespace
>  #2 - call foo
>  #3 - restore filesystem/namespace
> 
> should be a function in common code, and that the only
> target-specific part is selecting a filesystem/namespace.
> That is, simplifying, something like:
> 
> /* Cause the filesystem to appear as it does to process PID and
>    call FUNC with argument ARG, restoring the filesystem to its
>    original state afterwards.  Return nonzero if FUNC was called,
>    zero otherwise (and set ERRNO). */
> 
> int
> call_with_fs_of (int pid, void (*func) (void *), void *arg)
> {
>   int ret;
> 
>   target->select_fs (pid);
>   ret = func ();
>   target->select_fs (0);
>   return ret;
> }
> 
> Was there a reason this wasn't done that way?
> 
> (maybe make target->select_fs() return the previous
> namespace, instead of passing 0 on the second
> call.)

I'll have a go at doing it that way.

Thanks,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 7/7] Implement vFile:setfs in gdbserver
  2015-04-17 16:29       ` Gary Benson
@ 2015-04-17 17:09         ` Pedro Alves
  0 siblings, 0 replies; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 17:09 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches

On 04/17/2015 05:29 PM, Gary Benson wrote:
> Gary Benson wrote:
>> Pedro Alves wrote:
>>> So back on linux_ns_enter's naming ---
>>>
>>> I find the abstraction here a bit odd.  It seems to be me that
>>> a function that does:
>>>
>>>  #1 - select filesystem/namespace
>>>  #2 - call foo
>>>  #3 - restore filesystem/namespace
>>>
>>> should be a function in common code, and that the only
>>> target-specific part is selecting a filesystem/namespace.
>>> That is, simplifying, something like:
>>>
>>> /* Cause the filesystem to appear as it does to process PID and
>>>    call FUNC with argument ARG, restoring the filesystem to its
>>>    original state afterwards.  Return nonzero if FUNC was called,
>>>    zero otherwise (and set ERRNO). */
>>>
>>> int
>>> call_with_fs_of (int pid, void (*func) (void *), void *arg)
>>> {
>>>   int ret;
>>>
>>>   target->select_fs (pid);
>>>   ret = func ();
>>>   target->select_fs (0);
>>>   return ret;
>>> }
>>>
>>> Was there a reason this wasn't done that way?
>>>
>>> (maybe make target->select_fs() return the previous
>>> namespace, instead of passing 0 on the second
>>> call.)
>>
>> I'll have a go at doing it that way.
> 
> It is kind of uglier doing it that way.  It would need to look
> something more like this:
> 
>   struct cleanup **old_chain;
> 
>   if (target->select_fs (pid, &old_chain) != 0)
>      return failure_return_value;
>   ret = func ();
>   do_cleanups (old_chain);
>   return ret;
> 
> linux_ns_enter has to open file descriptors for its own namespace
> and the one it wants to enter.  Its own namespace file descriptor
> is what it needs to return, and it has to be held open: you can't
> flip namespace and then open your own descriptor to flip back.
> So the thing target->select_fs would have to return would be an
> open file descriptor (to then pass to target->restore_fs, which
> would take a file descriptor argument rather than an PID) but
> that would be putting a Linuxism into the target vector.

Seems to me we can fix that by returning an opaque closure
instead then.  I don't think that's ugly at all.  E.g.,:

int
call_with_fs_of (int pid, void (*func) (void *), void *arg)
{
  int ret = failure_return_value;

   restore_token = target->select_fs (pid);
   if (restore_token == NULL)
     return failure_return_value;
   TRY
     {
       ret = func ();
     }
   CATCH (ex, RETURN_MASK_ALL)
     {
       target->restore_fs (restore_token);
       throw_exception (ex);
     }
   END_CATCH
   return ret;
}

The reason I think this target interface is better is that
it also allows open coding the select_fs/restore_fs calls.
Which in turn would allow getting rid of all those closures in
the other patch.  For example, like this:

/* On exception, restore the filesystem, and rethrow.  */
#define CATCH_RESTORE_FS(restore_token) \
   CATCH (ex, RETURN_MASK_ALL) \
     { \
       linux_restore_namespace (restore_token); \
       throw_exception (ex); \
     } \
   END_CATCH

static int
linux_nat_fileio_unlink (struct target_ops *ops,
		         const char *filename, int *target_errno)
{
  void *restore_token;
  int ret = -1;

  restore_token = linux_nat_enter_fs ();

  TRY
    {
      ret = super_fileio_unlink (ops, filename, target_errno);
    }
  CATCH_RESTORE_FS(restore_token)

  return ret;
}

static char *
linux_nat_fileio_readlink (struct target_ops *ops,
			   const char *filename, int *target_errno)
{
  void *restore_token;
  char *ret = NULL;

  restore_token = linux_nat_enter_fs ();

  TRY
    {
      ret = super_fileio_readlink (ops, filename, target_errno);
    }
  CATCH_RESTORE_FS(restore_token)

  return ret;
}


etc., which I find _much_ more readable than:


+/* Arguments and return value of to_fileio_unlink.  */
+
+struct unlink_closure
+{
+  struct target_ops *ops;
+  const char *filename;
+  int *target_errno;
+  int return_value;
+};
+
+/* Helper for linux_nat_fileio_unlink.  */
+
+static void
+linux_nat_fileio_unlink_1 (void *arg)
+{
+  struct unlink_closure *clo = (struct unlink_closure *) arg;
+
+  clo->return_value = super_fileio_unlink (clo->ops, clo->filename,
+					   clo->target_errno);
+}
+
+/* Implementation of to_fileio_unlink.  */
+
+static int
+linux_nat_fileio_unlink (struct target_ops *ops,
+			   const char *filename, int *target_errno)
+{
+  struct unlink_closure clo =
+    {
+      /* Arguments.  */
+      ops, filename, target_errno,
+
+      /* Failure return value.  */
+      -1
+    };
+
+  linux_nat_enter_fs (linux_nat_fileio_unlink_1, &clo, target_errno);
+
+  return clo.return_value;
+}
+
+/* Arguments and return value of to_fileio_readlink.  */
+
+struct readlink_closure
+{
+  struct target_ops *ops;
+  const char *filename;
+  int *target_errno;
+  char *return_value;
+};
+
+/* Helper for linux_nat_fileio_readlink.  */
+
+static void
+linux_nat_fileio_readlink_1 (void *arg)
+{
+  struct readlink_closure *clo = (struct readlink_closure *) arg;
+
+  clo->return_value = super_fileio_readlink (clo->ops, clo->filename,
+					     clo->target_errno);
+}
+
+/* Implementation of to_fileio_readlink.  */
+
+static char *
+linux_nat_fileio_readlink (struct target_ops *ops,
+			   const char *filename, int *target_errno)
+{
+  struct readlink_closure clo =
+    {
+      /* Arguments.  */
+      ops, filename, target_errno,
+
+      /* Failure return value.  */
+      NULL
+    };
+
+  linux_nat_enter_fs (linux_nat_fileio_readlink_1, &clo, target_errno);
+
+  return clo.return_value;
+}

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/7] Introduce target_fileio_set_fs
  2015-04-17 14:21       ` Pedro Alves
@ 2015-04-17 17:28         ` Doug Evans
  2015-04-17 17:46           ` Pedro Alves
  0 siblings, 1 reply; 84+ messages in thread
From: Doug Evans @ 2015-04-17 17:28 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Gary Benson, gdb-patches

On Fri, Apr 17, 2015 at 7:21 AM, Pedro Alves <palves@redhat.com> wrote:
> On 04/17/2015 02:36 PM, Gary Benson wrote:
>
>> It was basically because the alternative was to add a parameter to
>> target_filesystem_is_local and target_fileio_{open,readlink,unlink}
>> (and all their target vector implementations) to pass around whatever
>> inferior you were talking about.  You'd also have to make a lot more
>> changes to the remote protocol: either vFile:{open,unlink,readlink}
>> would need an extra argument (indicated with qSupported) or you'd need
>> new "fs" versions of each packet.  Both Pedro and I thought that was
>> ugly.
>
> Right, this way mirrors what's done at the posix/system call level too,
> and if some other systems needs something different for selecting
> a "filesystem namespace", there's a single method/packet to change.

Fair enough.
All I would ask is that this get pushed down as far as possible in the
call stack.

E.g., while I wouldn't suggest massive changes to the remote protocol
(regardless of how desperately IWBN), IWBN that layers above that
follow good programming practices (avoiding using global state
wherever possible/reasonable).

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 3/7] Introduce nat/linux-namespaces.[ch]
  2015-04-17 14:52   ` Pedro Alves
@ 2015-04-17 17:32     ` Doug Evans
  2015-04-20 11:12       ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Doug Evans @ 2015-04-17 17:32 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Gary Benson, gdb-patches

On Fri, Apr 17, 2015 at 7:52 AM, Pedro Alves <palves@redhat.com> wrote:
>> +/* Enter the TYPE namespace of process PID and call FUNC with the
>> +   argument ARG, returning to the original TYPE namespace afterwards.
>> +   If process PID has the same TYPE namespace as the current process,
>> +   or if TYPE namespaces are not supported, just call FUNC with ARG.
>> +   Return nonzero if FUNC was called, zero otherwise (and set ERRNO). */
>> +
>> +extern int linux_ns_enter (int pid, const char *type,
>> +                        void (*func) (void *), void *arg);
>
>
> So the function:
>
>  #1 - enters the namespace
>  #2 - calls func
>  #3 - exits the namespace.
>
> IMO, "linux_ns_ENTER" isn't a good name for that.  I'd expect that a function
> called "enter" do just #1 above.  Something like "linux_ns_do",
> "linux_do_in_ns", "linux_in_ns", etc., would be clearer, IMO.

with_linux_ns ?

full disclosure: borrowed from Scheme
/ducks

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/7] Introduce target_fileio_set_fs
  2015-04-17 17:28         ` Doug Evans
@ 2015-04-17 17:46           ` Pedro Alves
  2015-04-20 11:11             ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-04-17 17:46 UTC (permalink / raw)
  To: Doug Evans; +Cc: Gary Benson, gdb-patches

On 04/17/2015 06:28 PM, Doug Evans wrote:
> On Fri, Apr 17, 2015 at 7:21 AM, Pedro Alves <palves@redhat.com> wrote:
>> On 04/17/2015 02:36 PM, Gary Benson wrote:
>>
>>> It was basically because the alternative was to add a parameter to
>>> target_filesystem_is_local and target_fileio_{open,readlink,unlink}
>>> (and all their target vector implementations) to pass around whatever
>>> inferior you were talking about.  You'd also have to make a lot more
>>> changes to the remote protocol: either vFile:{open,unlink,readlink}
>>> would need an extra argument (indicated with qSupported) or you'd need
>>> new "fs" versions of each packet.  Both Pedro and I thought that was
>>> ugly.
>>
>> Right, this way mirrors what's done at the posix/system call level too,
>> and if some other systems needs something different for selecting
>> a "filesystem namespace", there's a single method/packet to change.
> 
> Fair enough.
> All I would ask is that this get pushed down as far as possible in the
> call stack.
> 
> E.g., while I wouldn't suggest massive changes to the remote protocol
> (regardless of how desperately IWBN), IWBN that layers above that
> follow good programming practices (avoiding using global state
> wherever possible/reasonable).

Fair enough as well.  I'm fine with adding explicit arguments
on the layers above, leaving the packet as is.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/7] Introduce target_fileio_set_fs
  2015-04-17 17:46           ` Pedro Alves
@ 2015-04-20 11:11             ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-20 11:11 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Doug Evans, gdb-patches

Pedro Alves wrote:
> On 04/17/2015 06:28 PM, Doug Evans wrote:
> > On Fri, Apr 17, 2015 at 7:21 AM, Pedro Alves <palves@redhat.com> wrote:
> > > On 04/17/2015 02:36 PM, Gary Benson wrote:
> > > > It was basically because the alternative was to add a parameter to
> > > > target_filesystem_is_local and target_fileio_{open,readlink,unlink}
> > > > (and all their target vector implementations) to pass around whatever
> > > > inferior you were talking about.  You'd also have to make a lot more
> > > > changes to the remote protocol: either vFile:{open,unlink,readlink}
> > > > would need an extra argument (indicated with qSupported) or you'd need
> > > > new "fs" versions of each packet.  Both Pedro and I thought that was
> > > > ugly.
> > >
> > > Right, this way mirrors what's done at the posix/system call level too,
> > > and if some other systems needs something different for selecting
> > > a "filesystem namespace", there's a single method/packet to change.
> > 
> > Fair enough.
> > All I would ask is that this get pushed down as far as possible in the
> > call stack.
> > 
> > E.g., while I wouldn't suggest massive changes to the remote protocol
> > (regardless of how desperately IWBN), IWBN that layers above that
> > follow good programming practices (avoiding using global state
> > wherever possible/reasonable).
> 
> Fair enough as well.  I'm fine with adding explicit arguments
> on the layers above, leaving the packet as is.

Ok, I'll make that change.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 3/7] Introduce nat/linux-namespaces.[ch]
  2015-04-17 17:32     ` Doug Evans
@ 2015-04-20 11:12       ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-20 11:12 UTC (permalink / raw)
  To: Doug Evans; +Cc: Pedro Alves, gdb-patches

Doug Evans wrote:
> On Fri, Apr 17, 2015 at 7:52 AM, Pedro Alves <palves@redhat.com> wrote:
> > > +/* Enter the TYPE namespace of process PID and call FUNC with the
> > > +   argument ARG, returning to the original TYPE namespace afterwards.
> > > +   If process PID has the same TYPE namespace as the current process,
> > > +   or if TYPE namespaces are not supported, just call FUNC with ARG.
> > > +   Return nonzero if FUNC was called, zero otherwise (and set ERRNO). */
> > > +
> > > +extern int linux_ns_enter (int pid, const char *type,
> > > +                        void (*func) (void *), void *arg);
> >
> >
> > So the function:
> >
> >  #1 - enters the namespace
> >  #2 - calls func
> >  #3 - exits the namespace.
> >
> > IMO, "linux_ns_ENTER" isn't a good name for that.  I'd expect that a function
> > called "enter" do just #1 above.  Something like "linux_ns_do",
> > "linux_do_in_ns", "linux_in_ns", etc., would be clearer, IMO.
> 
> with_linux_ns ?
> 
> full disclosure: borrowed from Scheme
> /ducks

Works for me.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 0/7] GNU/Linux mount namespace support
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (7 preceding siblings ...)
  2015-04-17 15:35 ` [PATCH 0/7] GNU/Linux mount namespace support Pedro Alves
@ 2015-04-20 16:49 ` Iago López Galeiras
  2015-04-21  7:56   ` Gary Benson
  2015-04-30 12:06 ` [PATCH 6/9 v2] Implement mount namespace support for native Linux targets Gary Benson
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Iago López Galeiras @ 2015-04-20 16:49 UTC (permalink / raw)
  To: gdb-patches

Thanks a lot for the patches!

I've got a small feature request. If the process inside the mount namespace is
running on a chroot I believe it won't work (I couldn't test it because the
patches don't work for me[1]).

The reason I want this feature is that rkt[2] runs several apps in a container,
each one on its own chroot and I'd like to debug programs running there.

Maybe you could detect if it's runinng on a chroot by reading /proc/$PID/root,
comparing it to / and, if they're different, use the former to get the binary.
What do you think about it?

Thanks again.
Cheers.

[1]: Context from an IRC conversation with gbenson: My gdb is multi-threaded and
multi-threaded programs can't change mount namespaces, he is already working on
a fix.

[2]: https://github.com/coreos/rkt

On 04/16/2015 02:19 PM, Gary Benson wrote:
> Hi all,
> 
> This series allows GDB and gdbserver on GNU/Linux systems to attach
> to processes in mount namespaces other than the debugger's own when
> invoked with the appropriate permissions.  This allows an application
> running in a container to be debugged by running GDB or gdbserver on
> the host, or by running GDB or gdbserver from within another container
> that shares the host's PID namespace.
> 
> This series builds on the 'Do not require "file" commands for remote
> targets' series that is currently under review:
> 
>   https://sourceware.org/ml/gdb-patches/2015-04/msg00015.html
> 
> It also requires the 'Do not manipulate "target:" filenames as local
> paths' patch to function correctly:
> 
>   https://sourceware.org/ml/gdb-patches/2015-04/msg00547.html
> 
> A tree with the latest versions of all these patches applied is
> available here:
> 
>   https://github.com/gbenson/binutils-gdb/tree/namespaces
> 
> The patches in this series are as follows:
> 
>  - Patch 1 (Move make_cleanup_close to common code) is a minor
>    refactoring required for patch 3.
> 
>  - Patch 2 (Introduce target_fileio_set_fs) adds target-layer
>    support for systems where different processes can have different
>    views of the filesystem.  The new function target_fileio_set_fs
>    sets the context in which target_filesystem_is_local and the
>    other target_fileio_* functions operate, and can be called to
>    select the filesystem of a specific inferior or the filesystem
>    of the debugger (GDB or gdbserver).  The default implementation
>    of target_fileio_set_fs does nothing, which means that targets
>    where inferiors and the debugger share the same filesystem will
>    work without modification.
> 
>  - Patch 3 (Introduce nat/linux-namespaces.[ch]) introduces some
>    shared code that GDB and gdbserver can use to query and enter
>    Linux namespaces.
> 
>  - GDB contained a small amount of namespace-aware code used to
>    display a warning.  Patch 4 (Remove linux_proc_pid_get_ns)
>    replaces the querying part of this code with a call to the
>    new code introduced by patch 3.
> 
>  - Patch 5 (Implement multiple-filesystem support for Linux targets)
>    does exactly what it says on the tin.  With this patch you can
>    attach to processes in containers using the native Linux target
>    using, e.g., "gdb -p PID".
> 
>  - Patch 6 (Implement multiple-filesystem support for remote targets)
>    adds remote protocol support for remote targets where different
>    processes can have different views of the filesystem.  A new
>    vFile:setfs packet is introduced that passes the context set using
>    target_fileio_set_fs to the remote target.  Caching is used to
>    avoid sending unnecessary vFile:setfs packets.
> 
>  - Patch 7 (Implement vFile:setfs in gdbserver) implements the
>    vFile:setfs packet in gdbserver.  Currently only GNU/Linux systems
>    support this; gdbserver on other systems will return empty
>    responses in reply to vFile:setfs packets.
> 
> Built and regtested on RHEL 6.6 x86_64.
> 
> Ok to commit?
> 
> Thanks,
> Gary
> 
> --
> http://gbenson.net/
> 

-- 

Iago López Galeiras
Software developer @ Endocode AG
iago@endocode.com

------
Endocode AG, Johannisstrasse 20, 10117 Berlin
info@endocode.com | www.endocode.com

Vorstandsvorsitzender: Mirko Boehm
Vorstände: Dr. Karl Beecher, Chris Kühl, Sebastian Sucker
Aufsichtsratsvorsitzende: Jennifer Beecher

Registergericht: Amtsgericht Charlottenburg - HRB 150748 B

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 0/7] GNU/Linux mount namespace support
  2015-04-20 16:49 ` Iago López Galeiras
@ 2015-04-21  7:56   ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-21  7:56 UTC (permalink / raw)
  To: Iago López Galeiras; +Cc: gdb-patches

Iago López Galeiras wrote:
> On 04/16/2015 02:19 PM, Gary Benson wrote:
> > This series allows GDB and gdbserver on GNU/Linux systems to
> > attach to processes in mount namespaces other than the debugger's
> > own when invoked with the appropriate permissions.  This allows an
> > application running in a container to be debugged by running GDB
> > or gdbserver on the host, or by running GDB or gdbserver from
> > within another container that shares the host's PID namespace.
> 
> Thanks a lot for the patches!
> 
> I've got a small feature request. If the process inside the mount
> namespace is running on a chroot I believe it won't work (I couldn't
> test it because the patches don't work for me[1]).

Well, let's not start implementing fixes for things that might not
even be broken.  I'll mail a v2 of this series that works with
multithreaded GDB, and then you can tell me if it didn't work :)

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 5/9 v2] Add "inferior" argument to some target_fileio functions
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (11 preceding siblings ...)
  2015-04-30 12:06 ` [PATCH 3/9 v2] Remove linux_proc_pid_get_ns Gary Benson
@ 2015-04-30 12:06 ` Gary Benson
  2015-05-21 14:57   ` Pedro Alves
  2015-04-30 12:15 ` [PATCH 4/9 v2] Comment and whitespace changes Gary Benson
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-30 12:06 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit adds a new argument to all target_fileio functions with
filename arguments to allow the desired inferior to be specified.
This allows GDB to support systems where processes do not necessarily
share a common filesystem.

gdb/ChangeLog:

	* target.h (struct inferior): New forward declaration.
	(struct target_ops) <to_filesystem_is_local>: Update comment.
	(struct target_ops) <to_fileio_open>: New argument inf.
	Update comment.  All implementations updated.
	(struct target_ops) <to_fileio_unlink>: Likewise.
	(struct target_ops) <to_fileio_readlink>: Likewise.
	(target_filesystem_is_local): Update comment.
	(target_fileio_open): New argument inf.  Update comment.
	(target_fileio_unlink): Likewise.
	(target_fileio_readlink): Likewise.
	(target_fileio_read_alloc): Likewise.
	(target_fileio_read_stralloc): Likewise.
	* target.c (target_fileio_open): New argument inf.
	Pass inf to implementation.  Update debug printing.
	(target_fileio_unlink): Likewise.
	(target_fileio_readlink): Likewise.
	(target_fileio_read_alloc_1): New argument inf. Pass inf
	to target_fileio_open.
	(target_fileio_read_alloc): New argument inf. Pass inf to
	target_fileio_read_alloc_1.
	(target_fileio_read_stralloc): Likewise.
	* gdb_bfd.c (inferior.h): New include.
	(gdb_bfd_iovec_fileio_open): Replace unused "open_closure"
	argument with new argument "inferior".  Pass inferior to
	target_fileio_open.
	(gdb_bfd_open): Supply inferior argument to
	gdb_bfd_iovec_fileio_open.
	* linux-tdep.c (linux_info_proc): Supply inf argument to
	relevant target_fileio calls.
	(linux_find_memory_regions_full): Likewise.
	(linux_fill_prpsinfo): Likewise.
	* remote.c (remote_filesystem_is_local): Supply inf
	argument to remote_hostio_open.
	(remote_file_put): Likewise.
	(remote_file_get): Likewise.
	(remote_file_delete): Supply inf argument to
	remote_hostio_unlink.
---
 gdb/ChangeLog    |   40 ++++++++++++++++++++
 gdb/gdb_bfd.c    |    9 +++--
 gdb/inf-child.c  |   10 +++--
 gdb/linux-tdep.c |   25 +++++++------
 gdb/remote.c     |   18 +++++----
 gdb/target.c     |   59 +++++++++++++++++++-----------
 gdb/target.h     |  106 ++++++++++++++++++++++++++++++++++--------------------
 7 files changed, 179 insertions(+), 88 deletions(-)

diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 2cd91ef..1781d80 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -32,6 +32,7 @@
 #endif
 #include "target.h"
 #include "gdb/fileio.h"
+#include "inferior.h"
 
 typedef bfd *bfdp;
 DEF_VEC_P (bfdp);
@@ -213,7 +214,7 @@ fileio_errno_to_host (int errnum)
    OPEN_CLOSURE is unused.  */
 
 static void *
-gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)
+gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *inferior)
 {
   const char *filename = bfd_get_filename (abfd);
   int fd, target_errno;
@@ -221,7 +222,8 @@ gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)
 
   gdb_assert (is_target_filename (filename));
 
-  fd = target_fileio_open (filename + strlen (TARGET_SYSROOT_PREFIX),
+  fd = target_fileio_open ((struct inferior *) inferior,
+			   filename + strlen (TARGET_SYSROOT_PREFIX),
 			   FILEIO_O_RDONLY, 0,
 			   &target_errno);
   if (fd == -1)
@@ -327,7 +329,8 @@ gdb_bfd_open (const char *name, const char *target, int fd)
 	  gdb_assert (fd == -1);
 
 	  return gdb_bfd_openr_iovec (name, target,
-				      gdb_bfd_iovec_fileio_open, NULL,
+				      gdb_bfd_iovec_fileio_open,
+				      current_inferior (),
 				      gdb_bfd_iovec_fileio_pread,
 				      gdb_bfd_iovec_fileio_close,
 				      gdb_bfd_iovec_fileio_fstat);
diff --git a/gdb/inf-child.c b/gdb/inf-child.c
index 181a745..896c154 100644
--- a/gdb/inf-child.c
+++ b/gdb/inf-child.c
@@ -208,8 +208,8 @@ inf_child_pid_to_exec_file (struct target_ops *self, int pid)
 
 static int
 inf_child_fileio_open (struct target_ops *self,
-		       const char *filename, int flags, int mode,
-		       int *target_errno)
+		       struct inferior *inf, const char *filename,
+		       int flags, int mode, int *target_errno)
 {
   int nat_flags;
   int fd;
@@ -318,7 +318,8 @@ inf_child_fileio_close (struct target_ops *self, int fd, int *target_errno)
 
 static int
 inf_child_fileio_unlink (struct target_ops *self,
-			 const char *filename, int *target_errno)
+			 struct inferior *inf, const char *filename,
+			 int *target_errno)
 {
   int ret;
 
@@ -333,7 +334,8 @@ inf_child_fileio_unlink (struct target_ops *self,
 
 static char *
 inf_child_fileio_readlink (struct target_ops *self,
-			   const char *filename, int *target_errno)
+			   struct inferior *inf, const char *filename,
+			   int *target_errno)
 {
   /* We support readlink only on systems that also provide a compile-time
      maximum path length (PATH_MAX), at least for now.  */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 9d75b66..52b2f0d 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -719,7 +719,7 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
   if (cmdline_f)
     {
       xsnprintf (filename, sizeof filename, "/proc/%ld/cmdline", pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (NULL, filename);
       if (data)
 	{
 	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -732,7 +732,7 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
   if (cwd_f)
     {
       xsnprintf (filename, sizeof filename, "/proc/%ld/cwd", pid);
-      data = target_fileio_readlink (filename, &target_errno);
+      data = target_fileio_readlink (NULL, filename, &target_errno);
       if (data)
 	{
 	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -745,7 +745,7 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
   if (exe_f)
     {
       xsnprintf (filename, sizeof filename, "/proc/%ld/exe", pid);
-      data = target_fileio_readlink (filename, &target_errno);
+      data = target_fileio_readlink (NULL, filename, &target_errno);
       if (data)
 	{
 	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -758,7 +758,7 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
   if (mappings_f)
     {
       xsnprintf (filename, sizeof filename, "/proc/%ld/maps", pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (NULL, filename);
       if (data)
 	{
 	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -819,7 +819,7 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
   if (status_f)
     {
       xsnprintf (filename, sizeof filename, "/proc/%ld/status", pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (NULL, filename);
       if (data)
 	{
 	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -832,7 +832,7 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
   if (stat_f)
     {
       xsnprintf (filename, sizeof filename, "/proc/%ld/stat", pid);
-      data = target_fileio_read_stralloc (filename);
+      data = target_fileio_read_stralloc (NULL, filename);
       if (data)
 	{
 	  struct cleanup *cleanup = make_cleanup (xfree, data);
@@ -1134,7 +1134,8 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
     {
       xsnprintf (coredumpfilter_name, sizeof (coredumpfilter_name),
 		 "/proc/%d/coredump_filter", pid);
-      coredumpfilterdata = target_fileio_read_stralloc (coredumpfilter_name);
+      coredumpfilterdata = target_fileio_read_stralloc (NULL,
+							coredumpfilter_name);
       if (coredumpfilterdata != NULL)
 	{
 	  sscanf (coredumpfilterdata, "%x", &filterflags);
@@ -1143,12 +1144,12 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
     }
 
   xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", pid);
-  data = target_fileio_read_stralloc (mapsfilename);
+  data = target_fileio_read_stralloc (NULL, mapsfilename);
   if (data == NULL)
     {
       /* Older Linux kernels did not support /proc/PID/smaps.  */
       xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/maps", pid);
-      data = target_fileio_read_stralloc (mapsfilename);
+      data = target_fileio_read_stralloc (NULL, mapsfilename);
     }
 
   if (data != NULL)
@@ -1755,7 +1756,7 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
   /* Obtaining PID and filename.  */
   pid = ptid_get_pid (inferior_ptid);
   xsnprintf (filename, sizeof (filename), "/proc/%d/cmdline", (int) pid);
-  fname = target_fileio_read_stralloc (filename);
+  fname = target_fileio_read_stralloc (NULL, filename);
 
   if (fname == NULL || *fname == '\0')
     {
@@ -1788,7 +1789,7 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
   p->pr_psargs[sizeof (p->pr_psargs) - 1] = '\0';
 
   xsnprintf (filename, sizeof (filename), "/proc/%d/stat", (int) pid);
-  proc_stat = target_fileio_read_stralloc (filename);
+  proc_stat = target_fileio_read_stralloc (NULL, filename);
   make_cleanup (xfree, proc_stat);
 
   if (proc_stat == NULL || *proc_stat == '\0')
@@ -1869,7 +1870,7 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
   /* Finally, obtaining the UID and GID.  For that, we read and parse the
      contents of the `/proc/PID/status' file.  */
   xsnprintf (filename, sizeof (filename), "/proc/%d/status", (int) pid);
-  proc_status = target_fileio_read_stralloc (filename);
+  proc_status = target_fileio_read_stralloc (NULL, filename);
   make_cleanup (xfree, proc_status);
 
   if (proc_status == NULL || *proc_status == '\0')
diff --git a/gdb/remote.c b/gdb/remote.c
index 6820dc8..330fbeb 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -9883,8 +9883,8 @@ remote_hostio_send_command (int command_bytes, int which_packet,
 
 static int
 remote_hostio_open (struct target_ops *self,
-		    const char *filename, int flags, int mode,
-		    int *remote_errno)
+		    struct inferior *inf, const char *filename,
+		    int flags, int mode, int *remote_errno)
 {
   struct remote_state *rs = get_remote_state ();
   char *p = rs->buf;
@@ -9992,7 +9992,8 @@ remote_hostio_close (struct target_ops *self, int fd, int *remote_errno)
 
 static int
 remote_hostio_unlink (struct target_ops *self,
-		      const char *filename, int *remote_errno)
+		      struct inferior *inf, const char *filename,
+		      int *remote_errno)
 {
   struct remote_state *rs = get_remote_state ();
   char *p = rs->buf;
@@ -10011,7 +10012,8 @@ remote_hostio_unlink (struct target_ops *self,
 
 static char *
 remote_hostio_readlink (struct target_ops *self,
-			const char *filename, int *remote_errno)
+			struct inferior *inf, const char *filename,
+			int *remote_errno)
 {
   struct remote_state *rs = get_remote_state ();
   char *p = rs->buf;
@@ -10127,7 +10129,7 @@ remote_filesystem_is_local (struct target_ops *self)
 	  /* Try opening a file to probe support.  The supplied
 	     filename is irrelevant, we only care about whether
 	     the stub recognizes the packet or not.  */
-	  fd = remote_hostio_open (self, "just probing",
+	  fd = remote_hostio_open (self, NULL, "just probing",
 				   FILEIO_O_RDONLY, 0700,
 				   &remote_errno);
 
@@ -10247,7 +10249,7 @@ remote_file_put (const char *local_file, const char *remote_file, int from_tty)
     perror_with_name (local_file);
   back_to = make_cleanup_fclose (file);
 
-  fd = remote_hostio_open (find_target_at (process_stratum),
+  fd = remote_hostio_open (find_target_at (process_stratum), NULL,
 			   remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
 					 | FILEIO_O_TRUNC),
 			   0700, &remote_errno);
@@ -10333,7 +10335,7 @@ remote_file_get (const char *remote_file, const char *local_file, int from_tty)
   if (!rs->remote_desc)
     error (_("command can only be used with remote target"));
 
-  fd = remote_hostio_open (find_target_at (process_stratum),
+  fd = remote_hostio_open (find_target_at (process_stratum), NULL,
 			   remote_file, FILEIO_O_RDONLY, 0, &remote_errno);
   if (fd == -1)
     remote_hostio_error (remote_errno);
@@ -10388,7 +10390,7 @@ remote_file_delete (const char *remote_file, int from_tty)
     error (_("command can only be used with remote target"));
 
   retcode = remote_hostio_unlink (find_target_at (process_stratum),
-				  remote_file, &remote_errno);
+				  NULL, remote_file, &remote_errno);
   if (retcode == -1)
     remote_hostio_error (remote_errno);
 
diff --git a/gdb/target.c b/gdb/target.c
index c0acaa9..5935716 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2759,8 +2759,8 @@ release_fileio_fd (int fd, fileio_fh_t *fh)
 /* See target.h.  */
 
 int
-target_fileio_open (const char *filename, int flags, int mode,
-		    int *target_errno)
+target_fileio_open (struct inferior *inf, const char *filename,
+		    int flags, int mode, int *target_errno)
 {
   struct target_ops *t;
 
@@ -2768,7 +2768,8 @@ target_fileio_open (const char *filename, int flags, int mode,
     {
       if (t->to_fileio_open != NULL)
 	{
-	  int fd = t->to_fileio_open (t, filename, flags, mode, target_errno);
+	  int fd = t->to_fileio_open (t, inf, filename, flags, mode,
+				      target_errno);
 
 	  if (fd < 0)
 	    fd = -1;
@@ -2777,7 +2778,9 @@ target_fileio_open (const char *filename, int flags, int mode,
 
 	  if (targetdebug)
 	    fprintf_unfiltered (gdb_stdlog,
-				"target_fileio_open (%s,0x%x,0%o) = %d (%d)\n",
+				"target_fileio_open (%d,%s,0x%x,0%o)"
+				" = %d (%d)\n",
+				inf == NULL ? 0 : inf->num,
 				filename, flags, mode,
 				fd, fd != -1 ? 0 : *target_errno);
 	  return fd;
@@ -2882,7 +2885,8 @@ target_fileio_close (int fd, int *target_errno)
 /* See target.h.  */
 
 int
-target_fileio_unlink (const char *filename, int *target_errno)
+target_fileio_unlink (struct inferior *inf, const char *filename,
+		      int *target_errno)
 {
   struct target_ops *t;
 
@@ -2890,12 +2894,15 @@ target_fileio_unlink (const char *filename, int *target_errno)
     {
       if (t->to_fileio_unlink != NULL)
 	{
-	  int ret = t->to_fileio_unlink (t, filename, target_errno);
+	  int ret = t->to_fileio_unlink (t, inf, filename,
+					 target_errno);
 
 	  if (targetdebug)
 	    fprintf_unfiltered (gdb_stdlog,
-				"target_fileio_unlink (%s) = %d (%d)\n",
-				filename, ret, ret != -1 ? 0 : *target_errno);
+				"target_fileio_unlink (%d,%s)"
+				" = %d (%d)\n",
+				inf == NULL ? 0 : inf->num, filename,
+				ret, ret != -1 ? 0 : *target_errno);
 	  return ret;
 	}
     }
@@ -2907,7 +2914,8 @@ target_fileio_unlink (const char *filename, int *target_errno)
 /* See target.h.  */
 
 char *
-target_fileio_readlink (const char *filename, int *target_errno)
+target_fileio_readlink (struct inferior *inf, const char *filename,
+			int *target_errno)
 {
   struct target_ops *t;
 
@@ -2915,11 +2923,14 @@ target_fileio_readlink (const char *filename, int *target_errno)
     {
       if (t->to_fileio_readlink != NULL)
 	{
-	  char *ret = t->to_fileio_readlink (t, filename, target_errno);
+	  char *ret = t->to_fileio_readlink (t, inf, filename,
+					     target_errno);
 
 	  if (targetdebug)
 	    fprintf_unfiltered (gdb_stdlog,
-				"target_fileio_readlink (%s) = %s (%d)\n",
+				"target_fileio_readlink (%d,%s)"
+				" = %s (%d)\n",
+				inf == NULL ? 0 : inf->num,
 				filename, ret? ret : "(nil)",
 				ret? 0 : *target_errno);
 	  return ret;
@@ -2939,14 +2950,16 @@ target_fileio_close_cleanup (void *opaque)
   target_fileio_close (fd, &target_errno);
 }
 
-/* Read target file FILENAME.  Store the result in *BUF_P and
-   return the size of the transferred data.  PADDING additional bytes are
-   available in *BUF_P.  This is a helper function for
-   target_fileio_read_alloc; see the declaration of that function for more
-   information.  */
+/* Read target file FILENAME, in the filesystem as seen by INF.  If
+   INF is NULL, use the filesystem seen by the debugger (GDB or, for
+   remote targets, the remote stub).  Store the result in *BUF_P and
+   return the size of the transferred data.  PADDING additional bytes
+   are available in *BUF_P.  This is a helper function for
+   target_fileio_read_alloc; see the declaration of that function for
+   more information.  */
 
 static LONGEST
-target_fileio_read_alloc_1 (const char *filename,
+target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
 			    gdb_byte **buf_p, int padding)
 {
   struct cleanup *close_cleanup;
@@ -2956,7 +2969,8 @@ target_fileio_read_alloc_1 (const char *filename,
   int fd;
   int target_errno;
 
-  fd = target_fileio_open (filename, FILEIO_O_RDONLY, 0700, &target_errno);
+  fd = target_fileio_open (inf, filename, FILEIO_O_RDONLY, 0700,
+			   &target_errno);
   if (fd == -1)
     return -1;
 
@@ -3006,21 +3020,22 @@ target_fileio_read_alloc_1 (const char *filename,
 /* See target.h.  */
 
 LONGEST
-target_fileio_read_alloc (const char *filename, gdb_byte **buf_p)
+target_fileio_read_alloc (struct inferior *inf, const char *filename,
+			  gdb_byte **buf_p)
 {
-  return target_fileio_read_alloc_1 (filename, buf_p, 0);
+  return target_fileio_read_alloc_1 (inf, filename, buf_p, 0);
 }
 
 /* See target.h.  */
 
 char *
-target_fileio_read_stralloc (const char *filename)
+target_fileio_read_stralloc (struct inferior *inf, const char *filename)
 {
   gdb_byte *buffer;
   char *bufstr;
   LONGEST i, transferred;
 
-  transferred = target_fileio_read_alloc_1 (filename, &buffer, 1);
+  transferred = target_fileio_read_alloc_1 (inf, filename, &buffer, 1);
   bufstr = (char *) buffer;
 
   if (transferred < 0)
diff --git a/gdb/target.h b/gdb/target.h
index 3a0ae7b..909cc1d 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -38,6 +38,7 @@ struct static_tracepoint_marker;
 struct traceframe_info;
 struct expression;
 struct dcache_struct;
+struct inferior;
 
 #include "infrun.h" /* For enum exec_direction_kind.  */
 
@@ -830,18 +831,19 @@ struct target_ops
 
     /* Target file operations.  */
 
-    /* Return nonzero if the filesystem accessed by the
-       target_fileio_* methods is the local filesystem,
-       zero otherwise.  */
+    /* Return nonzero if the filesystem seen by the current inferior
+       is the local filesystem, zero otherwise.  */
     int (*to_filesystem_is_local) (struct target_ops *)
       TARGET_DEFAULT_RETURN (1);
 
-    /* Open FILENAME on the target, using FLAGS and MODE.  Return a
-       target file descriptor, or -1 if an error occurs (and set
-       *TARGET_ERRNO).  */
+    /* Open FILENAME on the target, in the filesystem as seen by INF,
+       using FLAGS and MODE.  If INF is NULL, use the filesystem seen
+       by the debugger (GDB or, for remote targets, the remote stub).
+       Return a target file descriptor, or -1 if an error occurs (and
+       set *TARGET_ERRNO).  */
     int (*to_fileio_open) (struct target_ops *,
-			   const char *filename, int flags, int mode,
-			   int *target_errno);
+			   struct inferior *inf, const char *filename,
+			   int flags, int mode, int *target_errno);
 
     /* Write up to LEN bytes from WRITE_BUF to FD on the target.
        Return the number of bytes written, or -1 if an error occurs
@@ -867,16 +869,24 @@ struct target_ops
        (and set *TARGET_ERRNO).  */
     int (*to_fileio_close) (struct target_ops *, int fd, int *target_errno);
 
-    /* Unlink FILENAME on the target.  Return 0, or -1 if an error
-       occurs (and set *TARGET_ERRNO).  */
+    /* Unlink FILENAME on the target, in the filesystem as seen by
+       INF.  If INF is NULL, use the filesystem seen by the debugger
+       (GDB or, for remote targets, the remote stub).  Return 0, or
+       -1 if an error occurs (and set *TARGET_ERRNO).  */
     int (*to_fileio_unlink) (struct target_ops *,
-			     const char *filename, int *target_errno);
-
-    /* Read value of symbolic link FILENAME on the target.  Return a
-       null-terminated string allocated via xmalloc, or NULL if an error
-       occurs (and set *TARGET_ERRNO).  */
+			     struct inferior *inf,
+			     const char *filename,
+			     int *target_errno);
+
+    /* Read value of symbolic link FILENAME on the target, in the
+       filesystem as seen by INF.  If INF is NULL, use the filesystem
+       seen by the debugger (GDB or, for remote targets, the remote
+       stub).  Return a null-terminated string allocated via xmalloc,
+       or NULL if an error occurs (and set *TARGET_ERRNO).  */
     char *(*to_fileio_readlink) (struct target_ops *,
-				 const char *filename, int *target_errno);
+				 struct inferior *inf,
+				 const char *filename,
+				 int *target_errno);
 
 
     /* Implement the "info proc" command.  */
@@ -1935,16 +1945,19 @@ extern int target_search_memory (CORE_ADDR start_addr,
 
 /* Target file operations.  */
 
-/* Return nonzero if the filesystem accessed by the target_fileio_*
-   methods is the local filesystem, zero otherwise.  */
+/* Return nonzero if the filesystem seen by the current inferior
+   is the local filesystem, zero otherwise.  */
 #define target_filesystem_is_local() \
   current_target.to_filesystem_is_local (&current_target)
 
-/* Open FILENAME on the target, using FLAGS and MODE.  Return a
-   target file descriptor, or -1 if an error occurs (and set
-   *TARGET_ERRNO).  */
-extern int target_fileio_open (const char *filename, int flags, int mode,
-			       int *target_errno);
+/* Open FILENAME on the target, in the filesystem as seen by INF,
+   using FLAGS and MODE.  If INF is NULL, use the filesystem seen
+   by the debugger (GDB or, for remote targets, the remote stub).
+   Return a target file descriptor, or -1 if an error occurs (and
+   set *TARGET_ERRNO).  */
+extern int target_fileio_open (struct inferior *inf,
+			       const char *filename, int flags,
+			       int mode, int *target_errno);
 
 /* Write up to LEN bytes from WRITE_BUF to FD on the target.
    Return the number of bytes written, or -1 if an error occurs
@@ -1968,33 +1981,48 @@ extern int target_fileio_fstat (int fd, struct stat *sb,
    (and set *TARGET_ERRNO).  */
 extern int target_fileio_close (int fd, int *target_errno);
 
-/* Unlink FILENAME on the target.  Return 0, or -1 if an error
+/* Unlink FILENAME on the target, in the filesystem as seen by INF.
+   If INF is NULL, use the filesystem seen by the debugger (GDB or,
+   for remote targets, the remote stub).  Return 0, or -1 if an error
    occurs (and set *TARGET_ERRNO).  */
-extern int target_fileio_unlink (const char *filename, int *target_errno);
-
-/* Read value of symbolic link FILENAME on the target.  Return a
-   null-terminated string allocated via xmalloc, or NULL if an error
-   occurs (and set *TARGET_ERRNO).  */
-extern char *target_fileio_readlink (const char *filename, int *target_errno);
-
-/* Read target file FILENAME.  The return value will be -1 if the transfer
-   fails or is not supported; 0 if the object is empty; or the length
-   of the object otherwise.  If a positive value is returned, a
-   sufficiently large buffer will be allocated using xmalloc and
-   returned in *BUF_P containing the contents of the object.
+extern int target_fileio_unlink (struct inferior *inf,
+				 const char *filename,
+				 int *target_errno);
+
+/* Read value of symbolic link FILENAME on the target, in the
+   filesystem as seen by INF.  If INF is NULL, use the filesystem seen
+   by the debugger (GDB or, for remote targets, the remote stub).
+   Return a null-terminated string allocated via xmalloc, or NULL if
+   an error occurs (and set *TARGET_ERRNO).  */
+extern char *target_fileio_readlink (struct inferior *inf,
+				     const char *filename,
+				     int *target_errno);
+
+/* Read target file FILENAME, in the filesystem as seen by INF.  If
+   INF is NULL, use the filesystem seen by the debugger (GDB or, for
+   remote targets, the remote stub).  The return value will be -1 if
+   the transfer fails or is not supported; 0 if the object is empty;
+   or the length of the object otherwise.  If a positive value is
+   returned, a sufficiently large buffer will be allocated using
+   xmalloc and returned in *BUF_P containing the contents of the
+   object.
 
    This method should be used for objects sufficiently small to store
    in a single xmalloc'd buffer, when no fixed bound on the object's
    size is known in advance.  */
-extern LONGEST target_fileio_read_alloc (const char *filename,
+extern LONGEST target_fileio_read_alloc (struct inferior *inf,
+					 const char *filename,
 					 gdb_byte **buf_p);
 
-/* Read target file FILENAME.  The result is NUL-terminated and
+/* Read target file FILENAME, in the filesystem as seen by INF.  If
+   INF is NULL, use the filesystem seen by the debugger (GDB or, for
+   remote targets, the remote stub).  The result is NUL-terminated and
    returned as a string, allocated using xmalloc.  If an error occurs
    or the transfer is unsupported, NULL is returned.  Empty objects
    are returned as allocated but empty strings.  A warning is issued
    if the result contains any embedded NUL bytes.  */
-extern char *target_fileio_read_stralloc (const char *filename);
+extern char *target_fileio_read_stralloc (struct inferior *inf,
+					  const char *filename);
 
 
 /* Tracepoint-related operations.  */
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 3/9 v2] Remove linux_proc_pid_get_ns
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (10 preceding siblings ...)
  2015-04-30 12:06 ` [PATCH 0/9 v2] GNU/Linux mount namespace support Gary Benson
@ 2015-04-30 12:06 ` Gary Benson
  2015-05-21 14:56   ` Pedro Alves
  2015-04-30 12:06 ` [PATCH 5/9 v2] Add "inferior" argument to some target_fileio functions Gary Benson
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-30 12:06 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit removes linux_proc_pid_get_ns, and updates its only
caller to use linux_ns_same instead.

gdb/ChangeLog:

	* linux-thread-db.c (nat/linux-namespaces.h): New include.
	(check_pid_namespace_match): Use linux_ns_same rather than
	linux_proc_pid_get_ns to spot PID namespace mismatches.
	* nat/linux-procfs.h (linux_proc_pid_get_ns): Remove.
	* nat/linux-procfs.c (linux_proc_pid_get_ns): Likewise.
---
 gdb/ChangeLog          |    8 ++++++++
 gdb/linux-thread-db.c  |   12 ++----------
 gdb/nat/linux-procfs.c |   19 -------------------
 gdb/nat/linux-procfs.h |    6 ------
 4 files changed, 10 insertions(+), 35 deletions(-)

diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 886d8ac..c4ada7a 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -42,9 +42,9 @@
 #include "nat/linux-osdata.h"
 #include "auto-load.h"
 #include "cli/cli-utils.h"
-
 #include <signal.h>
 #include <ctype.h>
+#include "nat/linux-namespaces.h"
 
 /* GNU/Linux libthread_db support.
 
@@ -1211,20 +1211,12 @@ check_pid_namespace_match (void)
 	 child's thread list, we'll mistakenly think it has no threads
 	 since the thread PID fields won't match the PID we give to
 	 libthread_db.  */
-      char *our_pid_ns = linux_proc_pid_get_ns (getpid (), "pid");
-      char *inferior_pid_ns = linux_proc_pid_get_ns (
-	ptid_get_pid (inferior_ptid), "pid");
-
-      if (our_pid_ns != NULL && inferior_pid_ns != NULL
-	  && strcmp (our_pid_ns, inferior_pid_ns) != 0)
+      if (!linux_ns_same (ptid_get_pid (inferior_ptid), LINUX_NS_PID))
 	{
 	  warning (_ ("Target and debugger are in different PID "
 		      "namespaces; thread lists and other data are "
 		      "likely unreliable"));
 	}
-
-      xfree (our_pid_ns);
-      xfree (inferior_pid_ns);
     }
 }
 
diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c
index 44364c5..24bcb01 100644
--- a/gdb/nat/linux-procfs.c
+++ b/gdb/nat/linux-procfs.c
@@ -185,25 +185,6 @@ linux_proc_pid_is_zombie (pid_t pid)
   return linux_proc_pid_is_zombie_maybe_warn (pid, 1);
 }
 
-/* See linux-procfs.h declaration.  */
-
-char *
-linux_proc_pid_get_ns (pid_t pid, const char *ns)
-{
-  char buf[100];
-  char nsval[64];
-  int ret;
-  xsnprintf (buf, sizeof (buf), "/proc/%d/ns/%s", (int) pid, ns);
-  ret = readlink (buf, nsval, sizeof (nsval));
-  if (0 < ret && ret < sizeof (nsval))
-    {
-      nsval[ret] = '\0';
-      return xstrdup (nsval);
-    }
-
-  return NULL;
-}
-
 /* See linux-procfs.h.  */
 
 void
diff --git a/gdb/nat/linux-procfs.h b/gdb/nat/linux-procfs.h
index fdbf383..f9cad39 100644
--- a/gdb/nat/linux-procfs.h
+++ b/gdb/nat/linux-procfs.h
@@ -54,12 +54,6 @@ extern int linux_proc_pid_is_zombie_nowarn (pid_t pid);
 
 extern int linux_proc_pid_is_gone (pid_t pid);
 
-/* Return an opaque string identifying PID's NS namespace or NULL if
- * the information is unavailable.  The returned string must be
- * released with xfree.  */
-
-extern char *linux_proc_pid_get_ns (pid_t pid, const char *ns);
-
 /* Callback function for linux_proc_attach_tgid_threads.  If the PTID
    thread is not yet known, try to attach to it and return true,
    otherwise return false.  */
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 0/9 v2] GNU/Linux mount namespace support
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (9 preceding siblings ...)
  2015-04-30 12:06 ` [PATCH 6/9 v2] Implement mount namespace support for native Linux targets Gary Benson
@ 2015-04-30 12:06 ` Gary Benson
  2015-06-10 14:23   ` [pushed][PATCH " Gary Benson
  2015-04-30 12:06 ` [PATCH 3/9 v2] Remove linux_proc_pid_get_ns Gary Benson
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-30 12:06 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

Hi all,

This series allows GDB and gdbserver on GNU/Linux systems to access
executable and shared library files from mount namespaces other than
the debugger's own without requiring "set sysroot" commands.  This
makes attaching to processes in containers as simple as "gdb -p PID"
or "gdbserver --attach PID".

This requires the "move vgdb special case" patch I posted the other
day to fail correctly when built on a system without kernel support
for mount namespaces and then run on a system with support.  It's
kind of an edge case, but it's there :)  A tree with that patch and
this series is here:

  https://github.com/gbenson/binutils-gdb/tree/namespaces

The major change from the first version of this series is that setns
calls are made from a single-threaded helper process that is forked
the first time a setns is required.  This should fix the issue that
Iago with multithreaded GDB.  (I'd thought I was building with Guile,
but it turns out my system Guile is too old).  I used the same code
for both GDB and gdbserver, so Doug your multithreaded gdbserver
should work fine with this code.

Other changes: I removed target_fileio_set_fs and added inferior
arguments to all target fileio functions with filename arguments.
All of the closure-style programming is gone.  I used pid_t and
mode_t everywhere I could.  I've rewritten and expanded the NEWS
and docs (I'm still not sure they're great, but...)

The patches in this series are as follows:

  - Patch 1 (Move make_cleanup_close to common code) is a minor
    refactoring required for patch 2.  Unchanged from version 1.

  - Patch 2 (Introduce nat/linux-namespaces.[ch]) is the actual
    namespace entering code, and has been almost completely
    rewritten from its equivalent in version 1 of this series.

  - Patch 3 (Remove linux_proc_pid_get_ns) replaces the little
    bit of namespace-aware code already in GDB with calls to
    the new code.  Pretty much the same as patch 4 from version
    1 of this series.

  - Patch 4 (Comment and whitespace changes) is a new patch.
    Comments on the various implementations of target fileio
    functions duplicated information documented in target.h.
    The next patch changes a ton of signatures, so rather than
    update comments everywhere this patch replaces all the
    duplicated comments with pointers back to the canonical
    version.

  - Patch 5 (Add "inferior" argument to some target fileio
    functions) is a new patch that does exactly what it says.

  - Patch 6 (Implement mount namespace support for native Linux
    targets) also does exactly what it says.  This patch is
    almost completely rewritten from its equivalent in version
    1 of this series.

  - Patch 7 (Implement multiple-filesystem support for remote
    targets) implements the vFile:setfs packet in GDB.  This
    patch is somewhat rewritten from its equivalent in version
    1 of this series: the actual remote protocol is the same,
    but the implementation is different, passing the inferior
    as an argument rather than using target_fileio_set_fs to
    set global context.  I also added code to handle error
    responses from vFile:setfs packets, the lack of which in
    version 1 of this series was an oversight on my part; the
    GNU/Linux gdbserver implementation never fails, but of
    course some other implementation might!

  - Patch 8 (Implement vFile:setfs in gdbserver) is also somewhat
    rewritten from its equivalent in version 1 of this series: the
    remote protocol is the same, but the new linux-namespaces.[ch]
    has very a different interface so all that is rewritten.

  - Patch 9 (Announce new container-awareness features for GNU/Linux
    systems) is a new patch with the main NEWS file entry pulled out
    of whatever patch it was in before.

Built and regtested on RHEL 6.6 x86_64.

Ok to commit?

Thanks,
Gary

--
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 6/9 v2] Implement mount namespace support for native Linux targets
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (8 preceding siblings ...)
  2015-04-20 16:49 ` Iago López Galeiras
@ 2015-04-30 12:06 ` Gary Benson
  2015-04-30 16:24   ` Eli Zaretskii
  2015-05-21 14:59   ` Pedro Alves
  2015-04-30 12:06 ` [PATCH 0/9 v2] GNU/Linux mount namespace support Gary Benson
                   ` (8 subsequent siblings)
  18 siblings, 2 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-30 12:06 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit allows GDB to access executables and shared libraries
on native Linux targets where GDB and the inferior have different
mount namespaces.

gdb/ChangeLog:

	* linux-nat.c (nat/linux-namespaces.h): New include.
	(fileio.h): Likewise.
	(linux_nat_filesystem_is_local): New function.
	(linux_nat_fileio_pid_of): Likewise.
	(linux_nat_fileio_open): Likewise.
	(linux_nat_fileio_readlink): Likewise.
	(linux_nat_fileio_unlink): Likewise.
	(linux_nat_add_target): Initialize to_filesystem_is_local,
	to_fileio_open, to_fileio_readlink and to_fileio_unlink.
	(_initialize_linux_nat): New "set/show debug lin-ns" commands.
	* NEWS: Mention new "set/show debug lin-ns" commands.
---
 gdb/ChangeLog   |   14 +++++++
 gdb/NEWS        |    4 ++
 gdb/linux-nat.c |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index d463b52..1c0e5ea 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -89,6 +89,10 @@ set|show record btrace bts buffer-size
   The obtained size may differ from the requested size.  Use "info
   record" to see the obtained buffer size.
 
+set debug lin-ns
+show debug lin-ns
+  Control display of debugging info regarding Linux namespaces.
+
 * The command 'thread apply all' can now support new option '-ascending'
   to call its specified command for all threads in ascending order.
 
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index b04aa68..85149a2 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -66,6 +66,8 @@
 #include "target-descriptions.h"
 #include "filestuff.h"
 #include "objfiles.h"
+#include "nat/linux-namespaces.h"
+#include "fileio.h"
 
 #ifndef SPUFS_MAGIC
 #define SPUFS_MAGIC 0x23c9b64e
@@ -4842,6 +4844,104 @@ linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid)
   return -1;
 }
 
+/* Implementation of to_filesystem_is_local.  */
+
+static int
+linux_nat_filesystem_is_local (struct target_ops *ops)
+{
+  struct inferior *inf = current_inferior ();
+
+  if (inf->fake_pid_p || inf->pid == 0)
+    return 1;
+
+  return linux_ns_same (inf->pid, LINUX_NS_MNT);
+}
+
+/* Convert the INF argument passed to a to_fileio_* method
+   to a process ID suitable for passing to its corresponding
+   linux_mntns_* function.  If INF is non-NULL then the
+   caller is requesting the filesystem seen by INF.  If INF
+   is NULL then the caller is requesting the filesystem seen
+   by the GDB.  We fall back to GDB's filesystem in the case
+   that INF is non-NULL but its PID is unknown.  */
+
+static pid_t
+linux_nat_fileio_pid_of (struct inferior *inf)
+{
+  if (inf == NULL || inf->fake_pid_p || inf->pid == 0)
+    return getpid ();
+  else
+    return inf->pid;
+}
+
+/* Implementation of to_fileio_open.  */
+
+static int
+linux_nat_fileio_open (struct target_ops *self,
+		       struct inferior *inf, const char *filename,
+		       int flags, int mode, int *target_errno)
+{
+  int nat_flags;
+  int fd;
+
+  if (fileio_to_host_openflags (flags, &nat_flags) == -1)
+    {
+      *target_errno = FILEIO_EINVAL;
+      return -1;
+    }
+
+  /* We do not need to convert MODE, since the fileio protocol
+     uses the standard values.  */
+  fd = linux_mntns_open_cloexec (linux_nat_fileio_pid_of (inf),
+				 filename, nat_flags, mode);
+  if (fd == -1)
+    *target_errno = host_to_fileio_error (errno);
+
+  return fd;
+}
+
+/* Implementation of to_fileio_readlink.  */
+
+static char *
+linux_nat_fileio_readlink (struct target_ops *self,
+			   struct inferior *inf, const char *filename,
+			   int *target_errno)
+{
+  char buf[PATH_MAX];
+  int len;
+  char *ret;
+
+  len = linux_mntns_readlink (linux_nat_fileio_pid_of (inf),
+			      filename, buf, sizeof (buf));
+  if (len < 0)
+    {
+      *target_errno = host_to_fileio_error (errno);
+      return NULL;
+    }
+
+  ret = xmalloc (len + 1);
+  memcpy (ret, buf, len);
+  ret[len] = '\0';
+  return ret;
+}
+
+/* Implementation of to_fileio_unlink.  */
+
+static int
+linux_nat_fileio_unlink (struct target_ops *self,
+			 struct inferior *inf, const char *filename,
+			 int *target_errno)
+{
+  int ret;
+
+  ret = linux_mntns_unlink (linux_nat_fileio_pid_of (inf),
+			    filename);
+  if (ret == -1)
+    *target_errno = host_to_fileio_error (errno);
+
+  return ret;
+}
+
 void
 linux_nat_add_target (struct target_ops *t)
 {
@@ -4895,6 +4995,11 @@ linux_nat_add_target (struct target_ops *t)
 
   t->to_core_of_thread = linux_nat_core_of_thread;
 
+  t->to_filesystem_is_local = linux_nat_filesystem_is_local;
+  t->to_fileio_open = linux_nat_fileio_open;
+  t->to_fileio_readlink = linux_nat_fileio_readlink;
+  t->to_fileio_unlink = linux_nat_fileio_unlink;
+
   /* We don't change the stratum; this target will sit at
      process_stratum and thread_db will set at thread_stratum.  This
      is a little strange, since this is a multi-threaded-capable
@@ -5012,6 +5117,15 @@ Enables printf debugging output."),
 			     show_debug_linux_nat,
 			     &setdebuglist, &showdebuglist);
 
+  add_setshow_boolean_cmd ("lin-ns", class_maintenance,
+			   &debug_linux_namespaces, _("\
+Set debugging of GNU/Linux namespaces module."), _("\
+Show debugging of GNU/Linux namespaces module."), _("\
+Enables printf debugging output."),
+			   NULL,
+			   NULL,
+			   &setdebuglist, &showdebuglist);
+
   /* Save this mask as the default.  */
   sigprocmask (SIG_SETMASK, NULL, &normal_mask);
 
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 4/9 v2] Comment and whitespace changes
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (12 preceding siblings ...)
  2015-04-30 12:06 ` [PATCH 5/9 v2] Add "inferior" argument to some target_fileio functions Gary Benson
@ 2015-04-30 12:15 ` Gary Benson
  2015-05-21 14:57   ` Pedro Alves
  2015-04-30 12:41 ` [PATCH 8/9 v2] Implement vFile:setfs in gdbserver Gary Benson
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-30 12:15 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

Comments on the various implementations of target fileio functions
duplicate information documented in target.h.  This commit replaces
the duplicated documentation with breadcrumbs, and inserts blank
lines to separate comments from the functions they describe where
necessary.

gdb/ChangeLog:

	* inf-child.c (inf_child_fileio_open): Replace comment.
	(inf_child_fileio_pwrite): Likewise.
	(inf_child_fileio_pread): Likewise.
	(inf_child_fileio_fstat): Insert blank line before comment.
	(inf_child_fileio_close): Replace comment.
	(inf_child_fileio_unlink): Likewise.
	(inf_child_fileio_readlink): Likewise.
	* remote.c (remote_hostio_open): Likewise.
	(remote_hostio_pread): Likewise.
	(remote_hostio_pwrite): Likewise.
	(remote_hostio_close): Likewise.
	(remote_hostio_unlink): Likewise.
	(remote_hostio_readlink): Likewise.
	(remote_hostio_fstat): Likewise.
	(remote_filesystem_is_local): Likewise.
	* target.c (target_fileio_open): Likewise.
	(target_fileio_pwrite): Likewise.
	(target_fileio_pread): Likewise.
	(target_fileio_fstat): Insert blank line before comment.
	(target_fileio_close): Replace comment.
	(target_fileio_unlink): Likewise.
	(target_fileio_readlink): Likewise.
	(target_fileio_read_alloc): Likewise.
	(target_fileio_read_stralloc): Likewise.
---
 gdb/ChangeLog   |   27 +++++++++++++++++++++++++++
 gdb/inf-child.c |   29 +++++++++++++----------------
 gdb/remote.c    |   29 ++++++++---------------------
 gdb/target.c    |   39 +++++++++++++++------------------------
 4 files changed, 63 insertions(+), 61 deletions(-)

diff --git a/gdb/inf-child.c b/gdb/inf-child.c
index 084dfa1..181a745 100644
--- a/gdb/inf-child.c
+++ b/gdb/inf-child.c
@@ -204,9 +204,8 @@ inf_child_pid_to_exec_file (struct target_ops *self, int pid)
   return NULL;
 }
 
-/* Open FILENAME on the target, using FLAGS and MODE.  Return a
-   target file descriptor, or -1 if an error occurs (and set
-   *TARGET_ERRNO).  */
+/* Implementation of to_fileio_open.  */
+
 static int
 inf_child_fileio_open (struct target_ops *self,
 		       const char *filename, int flags, int mode,
@@ -230,9 +229,8 @@ inf_child_fileio_open (struct target_ops *self,
   return fd;
 }
 
-/* Write up to LEN bytes from WRITE_BUF to FD on the target.
-   Return the number of bytes written, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
+/* Implementation of to_fileio_pwrite.  */
+
 static int
 inf_child_fileio_pwrite (struct target_ops *self,
 			 int fd, const gdb_byte *write_buf, int len,
@@ -259,9 +257,8 @@ inf_child_fileio_pwrite (struct target_ops *self,
   return ret;
 }
 
-/* Read up to LEN bytes FD on the target into READ_BUF.
-   Return the number of bytes read, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
+/* Implementation of to_fileio_pread.  */
+
 static int
 inf_child_fileio_pread (struct target_ops *self,
 			int fd, gdb_byte *read_buf, int len,
@@ -289,6 +286,7 @@ inf_child_fileio_pread (struct target_ops *self,
 }
 
 /* Implementation of to_fileio_fstat.  */
+
 static int
 inf_child_fileio_fstat (struct target_ops *self, int fd,
 			struct stat *sb, int *target_errno)
@@ -302,8 +300,8 @@ inf_child_fileio_fstat (struct target_ops *self, int fd,
   return ret;
 }
 
-/* Close FD on the target.  Return 0, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
+/* Implementation of to_fileio_close.  */
+
 static int
 inf_child_fileio_close (struct target_ops *self, int fd, int *target_errno)
 {
@@ -316,8 +314,8 @@ inf_child_fileio_close (struct target_ops *self, int fd, int *target_errno)
   return ret;
 }
 
-/* Unlink FILENAME on the target.  Return 0, or -1 if an error
-   occurs (and set *TARGET_ERRNO).  */
+/* Implementation of to_fileio_unlink.  */
+
 static int
 inf_child_fileio_unlink (struct target_ops *self,
 			 const char *filename, int *target_errno)
@@ -331,9 +329,8 @@ inf_child_fileio_unlink (struct target_ops *self,
   return ret;
 }
 
-/* Read value of symbolic link FILENAME on the target.  Return a
-   null-terminated string allocated via xmalloc, or NULL if an error
-   occurs (and set *TARGET_ERRNO).  */
+/* Implementation of to_fileio_readlink.  */
+
 static char *
 inf_child_fileio_readlink (struct target_ops *self,
 			   const char *filename, int *target_errno)
diff --git a/gdb/remote.c b/gdb/remote.c
index 099ddbb..6820dc8 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -9879,9 +9879,7 @@ remote_hostio_send_command (int command_bytes, int which_packet,
   return ret;
 }
 
-/* Open FILENAME on the remote target, using FLAGS and MODE.  Return a
-   remote file descriptor, or -1 if an error occurs (and set
-   *REMOTE_ERRNO).  */
+/* Implementation of to_fileio_open.  */
 
 static int
 remote_hostio_open (struct target_ops *self,
@@ -9907,9 +9905,7 @@ remote_hostio_open (struct target_ops *self,
 				     remote_errno, NULL, NULL);
 }
 
-/* Write up to LEN bytes from WRITE_BUF to FD on the remote target.
-   Return the number of bytes written, or -1 if an error occurs (and
-   set *REMOTE_ERRNO).  */
+/* Implementation of to_fileio_pwrite.  */
 
 static int
 remote_hostio_pwrite (struct target_ops *self,
@@ -9936,9 +9932,7 @@ remote_hostio_pwrite (struct target_ops *self,
 				     remote_errno, NULL, NULL);
 }
 
-/* Read up to LEN bytes FD on the remote target into READ_BUF
-   Return the number of bytes read, or -1 if an error occurs (and
-   set *REMOTE_ERRNO).  */
+/* Implementation of to_fileio_pread.  */
 
 static int
 remote_hostio_pread (struct target_ops *self,
@@ -9977,8 +9971,7 @@ remote_hostio_pread (struct target_ops *self,
   return ret;
 }
 
-/* Close FD on the remote target.  Return 0, or -1 if an error occurs
-   (and set *REMOTE_ERRNO).  */
+/* Implementation of to_fileio_close.  */
 
 static int
 remote_hostio_close (struct target_ops *self, int fd, int *remote_errno)
@@ -9995,8 +9988,7 @@ remote_hostio_close (struct target_ops *self, int fd, int *remote_errno)
 				     remote_errno, NULL, NULL);
 }
 
-/* Unlink FILENAME on the remote target.  Return 0, or -1 if an error
-   occurs (and set *REMOTE_ERRNO).  */
+/* Implementation of to_fileio_unlink.  */
 
 static int
 remote_hostio_unlink (struct target_ops *self,
@@ -10015,9 +10007,7 @@ remote_hostio_unlink (struct target_ops *self,
 				     remote_errno, NULL, NULL);
 }
 
-/* Read value of symbolic link FILENAME on the remote target.  Return
-   a null-terminated string allocated via xmalloc, or NULL if an error
-   occurs (and set *REMOTE_ERRNO).  */
+/* Implementation of to_fileio_readlink.  */
 
 static char *
 remote_hostio_readlink (struct target_ops *self,
@@ -10054,9 +10044,7 @@ remote_hostio_readlink (struct target_ops *self,
   return ret;
 }
 
-/* Read information about the open file FD on the remote target
-   into ST.  Return 0 on success, or -1 if an error occurs (and
-   set *REMOTE_ERRNO).  */
+/* Implementation of to_fileio_fstat.  */
 
 static int
 remote_hostio_fstat (struct target_ops *self,
@@ -10116,8 +10104,7 @@ remote_hostio_fstat (struct target_ops *self,
   return 0;
 }
 
-/* Return nonzero if the filesystem accessed by the target_fileio_*
-   methods is the local filesystem, zero otherwise.  */
+/* Implementation of to_filesystem_is_local.  */
 
 static int
 remote_filesystem_is_local (struct target_ops *self)
diff --git a/gdb/target.c b/gdb/target.c
index 306c21d..c0acaa9 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2756,9 +2756,8 @@ release_fileio_fd (int fd, fileio_fh_t *fh)
 #define fileio_fd_to_fh(fd) \
   VEC_index (fileio_fh_t, fileio_fhandles, (fd))
 
-/* Open FILENAME on the target, using FLAGS and MODE.  Return a
-   target file descriptor, or -1 if an error occurs (and set
-   *TARGET_ERRNO).  */
+/* See target.h.  */
+
 int
 target_fileio_open (const char *filename, int flags, int mode,
 		    int *target_errno)
@@ -2789,9 +2788,8 @@ target_fileio_open (const char *filename, int flags, int mode,
   return -1;
 }
 
-/* Write up to LEN bytes from WRITE_BUF to FD on the target.
-   Return the number of bytes written, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
+/* See target.h.  */
+
 int
 target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
 		      ULONGEST offset, int *target_errno)
@@ -2814,9 +2812,8 @@ target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
   return ret;
 }
 
-/* Read up to LEN bytes FD on the target into READ_BUF.
-   Return the number of bytes read, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
+/* See target.h.  */
+
 int
 target_fileio_pread (int fd, gdb_byte *read_buf, int len,
 		     ULONGEST offset, int *target_errno)
@@ -2840,6 +2837,7 @@ target_fileio_pread (int fd, gdb_byte *read_buf, int len,
 }
 
 /* See target.h.  */
+
 int
 target_fileio_fstat (int fd, struct stat *sb, int *target_errno)
 {
@@ -2858,8 +2856,8 @@ target_fileio_fstat (int fd, struct stat *sb, int *target_errno)
   return ret;
 }
 
-/* Close FD on the target.  Return 0, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
+/* See target.h.  */
+
 int
 target_fileio_close (int fd, int *target_errno)
 {
@@ -2881,8 +2879,8 @@ target_fileio_close (int fd, int *target_errno)
   return ret;
 }
 
-/* Unlink FILENAME on the target.  Return 0, or -1 if an error
-   occurs (and set *TARGET_ERRNO).  */
+/* See target.h.  */
+
 int
 target_fileio_unlink (const char *filename, int *target_errno)
 {
@@ -2906,9 +2904,8 @@ target_fileio_unlink (const char *filename, int *target_errno)
   return -1;
 }
 
-/* Read value of symbolic link FILENAME on the target.  Return a
-   null-terminated string allocated via xmalloc, or NULL if an error
-   occurs (and set *TARGET_ERRNO).  */
+/* See target.h.  */
+
 char *
 target_fileio_readlink (const char *filename, int *target_errno)
 {
@@ -3006,9 +3003,7 @@ target_fileio_read_alloc_1 (const char *filename,
     }
 }
 
-/* Read target file FILENAME.  Store the result in *BUF_P and return
-   the size of the transferred data.  See the declaration in "target.h"
-   function for more information about the return value.  */
+/* See target.h.  */
 
 LONGEST
 target_fileio_read_alloc (const char *filename, gdb_byte **buf_p)
@@ -3016,11 +3011,7 @@ target_fileio_read_alloc (const char *filename, gdb_byte **buf_p)
   return target_fileio_read_alloc_1 (filename, buf_p, 0);
 }
 
-/* Read target file FILENAME.  The result is NUL-terminated and
-   returned as a string, allocated using xmalloc.  If an error occurs
-   or the transfer is unsupported, NULL is returned.  Empty objects
-   are returned as allocated but empty strings.  A warning is issued
-   if the result contains any embedded NUL bytes.  */
+/* See target.h.  */
 
 char *
 target_fileio_read_stralloc (const char *filename)
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 8/9 v2] Implement vFile:setfs in gdbserver
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (13 preceding siblings ...)
  2015-04-30 12:15 ` [PATCH 4/9 v2] Comment and whitespace changes Gary Benson
@ 2015-04-30 12:41 ` Gary Benson
  2015-05-21 15:00   ` Pedro Alves
  2015-04-30 12:45 ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Gary Benson
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-30 12:41 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit implements the "vFile:setfs" packet in gdbserver.

gdb/gdbserver/ChangeLog:

	* target.h (struct target_ops) <multifs_open>: New field.
	<multifs_unlink>: Likewise.
	<multifs_readlink>: Likewise.
	* linux-low.c (nat/linux-namespaces.h): New include.
	(linux_target_ops): Initialize the_target->multifs_open,
	the_target->multifs_unlink and the_target->multifs_readlink.
	* hostio.c (hostio_fs_pid): New static variable.
	(handle_setfs): New function.
	(handle_open): Use the_target->multifs_open as appropriate.
	(handle_unlink): Use the_target->multifs_unlink as appropriate.
	(handle_readlink): Use the_target->multifs_readlink as
	appropriate.
	(handle_vFile): Handle vFile:setfs packets.
---
 gdb/gdbserver/ChangeLog   |   16 +++++++++++
 gdb/gdbserver/hostio.c    |   62 ++++++++++++++++++++++++++++++++++++++++++--
 gdb/gdbserver/linux-low.c |    4 +++
 gdb/gdbserver/target.h    |   21 +++++++++++++++
 4 files changed, 100 insertions(+), 3 deletions(-)

diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
index 9e858d9..10cff5a 100644
--- a/gdb/gdbserver/hostio.c
+++ b/gdb/gdbserver/hostio.c
@@ -243,6 +243,47 @@ hostio_reply_with_data (char *own_buf, char *buffer, int len,
   return input_index;
 }
 
+/* Process ID of inferior whose filesystem hostio functions
+   that take FILENAME arguments will use.  Zero means to use
+   our own filesystem.  */
+
+static int hostio_fs_pid = 0;
+
+/* Handle a "vFile:setfs:" packet.  */
+
+static void
+handle_setfs (char *own_buf)
+{
+  char *p;
+  int pid;
+
+  /* If the target doesn't have any of the in-filesystem-of methods
+     then there's no point in GDB sending "vFile:setfs:" packets.  We
+     reply with an empty packet (i.e. we pretend we don't understand
+     "vFile:setfs:") and that should stop GDB sending any more.  */
+  if (the_target->multifs_open == NULL
+      && the_target->multifs_unlink == NULL
+      && the_target->multifs_readlink == NULL)
+    {
+      own_buf[0] = '\0';
+      return;
+    }
+
+  p = own_buf + strlen ("vFile:setfs:");
+
+  if (require_int (&p, &pid)
+      || pid < 0
+      || require_end (p))
+    {
+      hostio_packet_error (own_buf);
+      return;
+    }
+
+  hostio_fs_pid = pid;
+
+  hostio_reply (own_buf, 0);
+}
+
 static void
 handle_open (char *own_buf)
 {
@@ -267,7 +308,11 @@ handle_open (char *own_buf)
 
   /* We do not need to convert MODE, since the fileio protocol
      uses the standard values.  */
-  fd = open (filename, flags, mode);
+  if (hostio_fs_pid != 0 && the_target->multifs_open != NULL)
+    fd = the_target->multifs_open (hostio_fs_pid, filename,
+				   flags, mode);
+  else
+    fd = open (filename, flags, mode);
 
   if (fd == -1)
     {
@@ -471,7 +516,10 @@ handle_unlink (char *own_buf)
       return;
     }
 
-  ret = unlink (filename);
+  if (hostio_fs_pid != 0 && the_target->multifs_unlink != NULL)
+    ret = the_target->multifs_unlink (hostio_fs_pid, filename);
+  else
+    ret = unlink (filename);
 
   if (ret == -1)
     {
@@ -498,7 +546,13 @@ handle_readlink (char *own_buf, int *new_packet_len)
       return;
     }
 
-  ret = readlink (filename, linkname, sizeof (linkname) - 1);
+  if (hostio_fs_pid != 0 && the_target->multifs_readlink != NULL)
+    ret = the_target->multifs_readlink (hostio_fs_pid, filename,
+					linkname,
+					sizeof (linkname) - 1);
+  else
+    ret = readlink (filename, linkname, sizeof (linkname) - 1);
+
   if (ret == -1)
     {
       hostio_error (own_buf);
@@ -532,6 +586,8 @@ handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
     handle_unlink (own_buf);
   else if (startswith (own_buf, "vFile:readlink:"))
     handle_readlink (own_buf, new_packet_len);
+  else if (startswith (own_buf, "vFile:setfs:"))
+    handle_setfs (own_buf);
   else
     return 0;
 
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 1c4c2d7..42e8a9e 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -51,6 +51,7 @@
    definition of elf_fpregset_t.  */
 #include <elf.h>
 #endif
+#include "nat/linux-namespaces.h"
 
 #ifndef SPUFS_MAGIC
 #define SPUFS_MAGIC 0x23c9b64e
@@ -6434,6 +6435,9 @@ static struct target_ops linux_target_ops = {
 #endif
   linux_supports_range_stepping,
   linux_proc_pid_to_exec_file,
+  linux_mntns_open_cloexec,
+  linux_mntns_unlink,
+  linux_mntns_readlink,
 };
 
 static void
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index 6280c26..7f4a1de 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -402,6 +402,27 @@ struct target_ops
      string should be copied into a buffer by the client if the string
      will not be immediately used, or if it must persist.  */
   char *(*pid_to_exec_file) (int pid);
+
+  /* Multiple-filesystem-aware open.  Like open(2), but operating in
+     the filesystem as it appears to process PID.  Systems where all
+     processes share a common filesystem should set this to NULL.
+     If NULL, the caller should fall back to open(2).  */
+  int (*multifs_open) (int pid, const char *filename,
+		       int flags, mode_t mode);
+
+  /* Multiple-filesystem-aware unlink.  Like unlink(2), but operates
+     in the filesystem as it appears to process PID.  Systems where
+     all processes share a common filesystem should set this to NULL.
+     If NULL, the caller should fall back to unlink(2).  */
+  int (*multifs_unlink) (int pid, const char *filename);
+
+  /* Multiple-filesystem-aware readlink.  Like readlink(2), but
+     operating in the filesystem as it appears to process PID.
+     Systems where all processes share a common filesystem should
+     set this to NULL.  If NULL, the caller should fall back to
+     readlink(2).  */
+  ssize_t (*multifs_readlink) (int pid, const char *filename,
+			       char *buf, size_t bufsiz);
 };
 
 extern struct target_ops *the_target;
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (14 preceding siblings ...)
  2015-04-30 12:41 ` [PATCH 8/9 v2] Implement vFile:setfs in gdbserver Gary Benson
@ 2015-04-30 12:45 ` Gary Benson
       [not found]   ` <20150501000739.740.47967@domU-12-31-39-0A-A0-4F>
                     ` (3 more replies)
  2015-04-30 14:12 ` [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets Gary Benson
                   ` (2 subsequent siblings)
  18 siblings, 4 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-30 12:45 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit introduces new shared files nat/linux-namespaces.[ch]
containing code to support Linux namespaces that will be used by
both GDB and gdbserver.

gdb/ChangeLog:

	* configure.ac (AC_CHECK_FUNCS): Add setns.
	* config.in: Regenerate.
	* configure: Likewise.
	* nat/linux-namespaces.h: New file.
	* nat/linux-namespaces.c: Likewise.
	* Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-namespaces.h.
	(linux-namespaces.o): New rule.
	* config/aarch64/linux.mh (NATDEPFILES): Add linux-namespaces.o.
	* config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
	* config/arm/linux.mh (NATDEPFILES): Likewise.
	* config/i386/linux.mh (NATDEPFILES): Likewise.
	* config/i386/linux64.mh (NATDEPFILES): Likewise.
	* config/ia64/linux.mh (NATDEPFILES): Likewise.
	* config/m32r/linux.mh (NATDEPFILES): Likewise.
	* config/m68k/linux.mh (NATDEPFILES): Likewise.
	* config/mips/linux.mh (NATDEPFILES): Likewise.
	* config/pa/linux.mh (NATDEPFILES): Likewise.
	* config/powerpc/linux.mh (NATDEPFILES): Likewise.
	* config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
	* config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
	* config/s390/linux.mh (NATDEPFILES): Likewise.
	* config/sparc/linux.mh (NATDEPFILES): Likewise.
	* config/sparc/linux64.mh (NATDEPFILES): Likewise.
	* config/tilegx/linux.mh (NATDEPFILES): Likewise.
	* config/xtensa/linux.mh (NATDEPFILES): Likewise.

gdb/gdbserver/ChangeLog:

	* configure.ac (AC_CHECK_FUNCS): Add setns.
	* config.in: Regenerate.
	* configure: Likewise.
	* Makefile.in (SFILES): Add nat/linux-namespaces.c.
	(linux-namespaces.o): New rule.
	* configure.srv (srv_linux_obj): Add linux-namespaces.o.
---
 gdb/ChangeLog                     |   28 +
 gdb/Makefile.in                   |    6 +-
 gdb/config.in                     |    3 +
 gdb/config/aarch64/linux.mh       |    2 +-
 gdb/config/alpha/alpha-linux.mh   |    2 +-
 gdb/config/arm/linux.mh           |    2 +-
 gdb/config/i386/linux.mh          |    2 +-
 gdb/config/i386/linux64.mh        |    2 +-
 gdb/config/ia64/linux.mh          |    3 +-
 gdb/config/m32r/linux.mh          |    2 +-
 gdb/config/m68k/linux.mh          |    2 +-
 gdb/config/mips/linux.mh          |    2 +-
 gdb/config/pa/linux.mh            |    2 +-
 gdb/config/powerpc/linux.mh       |    2 +-
 gdb/config/powerpc/ppc64-linux.mh |    3 +-
 gdb/config/powerpc/spu-linux.mh   |    4 +-
 gdb/config/s390/linux.mh          |    2 +-
 gdb/config/sparc/linux.mh         |    2 +-
 gdb/config/sparc/linux64.mh       |    2 +-
 gdb/config/tilegx/linux.mh        |    2 +-
 gdb/config/xtensa/linux.mh        |    2 +-
 gdb/configure                     |    2 +-
 gdb/configure.ac                  |    2 +-
 gdb/gdbserver/ChangeLog           |    9 +
 gdb/gdbserver/Makefile.in         |    6 +-
 gdb/gdbserver/config.in           |    3 +
 gdb/gdbserver/configure           |    2 +-
 gdb/gdbserver/configure.ac        |    2 +-
 gdb/gdbserver/configure.srv       |    2 +-
 gdb/nat/linux-namespaces.c        | 1042 +++++++++++++++++++++++++++++++++++++
 gdb/nat/linux-namespaces.h        |   76 +++
 31 files changed, 1197 insertions(+), 26 deletions(-)
 create mode 100644 gdb/nat/linux-namespaces.c
 create mode 100644 gdb/nat/linux-namespaces.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 47b216a..9921dcb 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -980,7 +980,7 @@ common/common-debug.h common/cleanups.h common/gdb_setjmp.h \
 common/common-exceptions.h target/target.h common/symbol.h \
 common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
 common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h \
-common/cleanup-utils.h
+common/cleanup-utils.h nat/linux-namespaces.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -2325,6 +2325,10 @@ x86-linux-dregs.o: ${srcdir}/nat/x86-linux-dregs.c
 	$(COMPILE) $(srcdir)/nat/x86-linux-dregs.c
 	$(POSTCOMPILE)
 
+linux-namespaces.o: ${srcdir}/nat/linux-namespaces.c
+	$(COMPILE) $(srcdir)/nat/linux-namespaces.c
+	$(POSTCOMPILE)
+
 #
 # gdb/tui/ dependencies
 #
diff --git a/gdb/config.in b/gdb/config.in
index d41e6cf..5b6dbbb 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -390,6 +390,9 @@
 /* Define to 1 if you have the `setlocale' function. */
 #undef HAVE_SETLOCALE
 
+/* Define to 1 if you have the `setns' function. */
+#undef HAVE_SETNS
+
 /* Define to 1 if you have the `setpgid' function. */
 #undef HAVE_SETPGID
 
diff --git a/gdb/config/aarch64/linux.mh b/gdb/config/aarch64/linux.mh
index 7f96e4d..6a8aa7d 100644
--- a/gdb/config/aarch64/linux.mh
+++ b/gdb/config/aarch64/linux.mh
@@ -22,7 +22,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o aarch64-linux-nat.o \
 	proc-service.o linux-thread-db.o linux-nat.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-osdata.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
diff --git a/gdb/config/alpha/alpha-linux.mh b/gdb/config/alpha/alpha-linux.mh
index 2ea02a1..4991dd2 100644
--- a/gdb/config/alpha/alpha-linux.mh
+++ b/gdb/config/alpha/alpha-linux.mh
@@ -3,7 +3,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o alpha-linux-nat.o \
 	fork-child.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/arm/linux.mh b/gdb/config/arm/linux.mh
index 549bf42..f0c5967 100644
--- a/gdb/config/arm/linux.mh
+++ b/gdb/config/arm/linux.mh
@@ -4,7 +4,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o arm-linux-nat.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh
index 9be2c5f..421c56f 100644
--- a/gdb/config/i386/linux.mh
+++ b/gdb/config/i386/linux.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
 	linux-btrace.o linux-waitpid.o linux-personality.o x86-linux.o \
-	x86-linux-dregs.o
+	x86-linux-dregs.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh
index 224a2a9..04cbb95 100644
--- a/gdb/config/i386/linux64.mh
+++ b/gdb/config/i386/linux64.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-btrace.o \
 	linux-waitpid.o linux-personality.o x86-linux.o \
-	x86-linux-dregs.o
+	x86-linux-dregs.o linux-namespaces.o
 NAT_FILE= config/nm-linux.h
 NAT_CDEPS = $(srcdir)/proc-service.list
 
diff --git a/gdb/config/ia64/linux.mh b/gdb/config/ia64/linux.mh
index 9dce22b..b05f834 100644
--- a/gdb/config/ia64/linux.mh
+++ b/gdb/config/ia64/linux.mh
@@ -6,7 +6,8 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-personality.o \
-	linux-procfs.o linux-ptrace.o linux-waitpid.o
+	linux-procfs.o linux-ptrace.o linux-waitpid.o \
+	linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/m32r/linux.mh b/gdb/config/m32r/linux.mh
index 6b810e6..277d8bd 100644
--- a/gdb/config/m32r/linux.mh
+++ b/gdb/config/m32r/linux.mh
@@ -4,7 +4,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o				\
 	m32r-linux-nat.o proc-service.o linux-thread-db.o	\
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
diff --git a/gdb/config/m68k/linux.mh b/gdb/config/m68k/linux.mh
index f3b3baa..60d5ce4 100644
--- a/gdb/config/m68k/linux.mh
+++ b/gdb/config/m68k/linux.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
 	linux-personality.o \
-	linux-waitpid.o
+	linux-waitpid.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/mips/linux.mh b/gdb/config/mips/linux.mh
index d6a802f..11ff903 100644
--- a/gdb/config/mips/linux.mh
+++ b/gdb/config/mips/linux.mh
@@ -5,7 +5,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o mips-linux-nat.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
 	linux-personality.o \
-	mips-linux-watch.o
+	mips-linux-watch.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/pa/linux.mh b/gdb/config/pa/linux.mh
index 9539b64..1b73ecd 100644
--- a/gdb/config/pa/linux.mh
+++ b/gdb/config/pa/linux.mh
@@ -4,7 +4,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	hppa-linux-nat.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/powerpc/linux.mh b/gdb/config/powerpc/linux.mh
index 76e62c0..f4a52c3 100644
--- a/gdb/config/powerpc/linux.mh
+++ b/gdb/config/powerpc/linux.mh
@@ -6,7 +6,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
 	ppc-linux-nat.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/powerpc/ppc64-linux.mh b/gdb/config/powerpc/ppc64-linux.mh
index 7eb6507..580eb1f 100644
--- a/gdb/config/powerpc/ppc64-linux.mh
+++ b/gdb/config/powerpc/ppc64-linux.mh
@@ -6,7 +6,8 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
 	ppc-linux-nat.o proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o ppc-linux.o linux-personality.o
+	linux-waitpid.o ppc-linux.o linux-personality.o \
+	linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The PowerPC has severe limitations on TOC size, and uses them even
diff --git a/gdb/config/powerpc/spu-linux.mh b/gdb/config/powerpc/spu-linux.mh
index d44aeeb..9205b62 100644
--- a/gdb/config/powerpc/spu-linux.mh
+++ b/gdb/config/powerpc/spu-linux.mh
@@ -4,5 +4,5 @@
 # PPU side of the Cell BE and debugging the SPU side.
 
 NATDEPFILES = spu-linux-nat.o fork-child.o inf-ptrace.o \
-	      linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o
-
+	      linux-procfs.o linux-ptrace.o linux-waitpid.o \
+	      linux-personality.o linux-namespaces.o
diff --git a/gdb/config/s390/linux.mh b/gdb/config/s390/linux.mh
index e1ad899..4a137cd 100644
--- a/gdb/config/s390/linux.mh
+++ b/gdb/config/s390/linux.mh
@@ -4,6 +4,6 @@ NATDEPFILES= inf-ptrace.o fork-child.o s390-linux-nat.o \
 	linux-thread-db.o proc-service.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
 	linux-personality.o \
-	linux-waitpid.o
+	linux-waitpid.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/config/sparc/linux.mh b/gdb/config/sparc/linux.mh
index bd7fc86..385f640 100644
--- a/gdb/config/sparc/linux.mh
+++ b/gdb/config/sparc/linux.mh
@@ -5,7 +5,7 @@ NATDEPFILES= sparc-nat.o sparc-linux-nat.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/sparc/linux64.mh b/gdb/config/sparc/linux64.mh
index 86f984f..8df0de1 100644
--- a/gdb/config/sparc/linux64.mh
+++ b/gdb/config/sparc/linux64.mh
@@ -5,7 +5,7 @@ NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-linux-nat.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/tilegx/linux.mh b/gdb/config/tilegx/linux.mh
index b5edcd4..ec648d3 100644
--- a/gdb/config/tilegx/linux.mh
+++ b/gdb/config/tilegx/linux.mh
@@ -6,7 +6,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
 	proc-service.o linux-thread-db.o \
 	linux-nat.o linux-osdata.o linux-fork.o \
 	linux-procfs.o linux-ptrace.o linux-waitpid.o \
-	linux-personality.o
+	linux-personality.o linux-namespaces.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
 # gdb executable.
diff --git a/gdb/config/xtensa/linux.mh b/gdb/config/xtensa/linux.mh
index b4e59b3..d5b8f91 100644
--- a/gdb/config/xtensa/linux.mh
+++ b/gdb/config/xtensa/linux.mh
@@ -5,7 +5,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o xtensa-linux-nat.o \
 	linux-thread-db.o proc-service.o \
 	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-	linux-waitpid.o linux-personality.o
+	linux-waitpid.o linux-personality.o linux-namespaces.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/configure b/gdb/configure
index 2baf6dd..5100921 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10957,7 +10957,7 @@ for ac_func in getauxval getrusage getuid getgid \
 		sigaction sigprocmask sigsetmask socketpair \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid \
-		ptrace64 sigaltstack mkdtemp
+		ptrace64 sigaltstack mkdtemp setns
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/configure.ac b/gdb/configure.ac
index c703e35..2035a37 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1331,7 +1331,7 @@ AC_CHECK_FUNCS([getauxval getrusage getuid getgid \
 		sigaction sigprocmask sigsetmask socketpair \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid \
-		ptrace64 sigaltstack mkdtemp])
+		ptrace64 sigaltstack mkdtemp setns])
 AM_LANGINFO_CODESET
 GDB_AC_COMMON
 
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 8ba88d4..4179cd6 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -180,7 +180,8 @@ SFILES=	$(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
 	$(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c \
 	$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c \
 	$(srcdir)/common/btrace-common.c \
-	$(srcdir)/common/fileio.c $(srcdir)/common/cleanup-utils.c
+	$(srcdir)/common/fileio.c $(srcdir)/common/cleanup-utils.c \
+	$(srcdir)/nat/linux-namespaces.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -619,6 +620,9 @@ x86-linux-dregs.o: ../nat/x86-linux-dregs.c
 cleanup-utils.o: ../common/cleanup-utils.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+linux-namespaces.o: ../nat/linux-namespaces.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 
 aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index 3c3bfca..893aaab 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -183,6 +183,9 @@
 /* Define to 1 if you have the `pwrite' function. */
 #undef HAVE_PWRITE
 
+/* Define to 1 if you have the `setns' function. */
+#undef HAVE_SETNS
+
 /* Define to 1 if you have the <sgtty.h> header file. */
 #undef HAVE_SGTTY_H
 
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 75860dd..bcb3f2e 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -5310,7 +5310,7 @@ fi
 
 done
 
-for ac_func in getauxval pread pwrite pread64
+for ac_func in getauxval pread pwrite pread64 setns
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index 34af269..2aef2b4 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -94,7 +94,7 @@ AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl
 		 fcntl.h signal.h sys/file.h dnl
 		 sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
 		 netinet/tcp.h arpa/inet.h)
-AC_CHECK_FUNCS(getauxval pread pwrite pread64)
+AC_CHECK_FUNCS(getauxval pread pwrite pread64 setns)
 
 GDB_AC_COMMON
 
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 81dd235..7f89f2f 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -42,7 +42,7 @@ srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/amd
 
 # Linux object files.  This is so we don't have to repeat
 # these files over and over again.
-srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o"
+srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o linux-namespaces.o"
 
 # Input is taken from the "${target}" variable.
 
diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
new file mode 100644
index 0000000..3603733
--- /dev/null
+++ b/gdb/nat/linux-namespaces.c
@@ -0,0 +1,1042 @@
+/* Linux namespaces(7) support.
+
+   Copyright (C) 2015 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 "nat/linux-namespaces.h"
+#include "filestuff.h"
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sched.h>
+
+/* See nat/linux-namespaces.h.  */
+int debug_linux_namespaces;
+
+/* Handle systems without setns.  */
+
+#ifndef HAVE_SETNS
+static int
+setns (int fd, int nstype)
+{
+#ifdef __NR_setns
+  return syscall (__NR_setns, fd, nstype);
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}
+#endif
+
+/* A Linux namespace.  */
+
+struct linux_ns
+{
+  /* Filename of this namespace's entries in /proc/PID/ns.  */
+  const char *filename;
+
+  /* Nonzero if this object has been initialized.  */
+  int initialized;
+
+  /* Nonzero if this namespace is supported on this system.  */
+  int supported;
+
+  /* ID of the namespace the calling process is in, used to
+     see if other processes share the namespace.  The code in
+     this file assumes that the calling process never changes
+     namespace.  */
+  ino_t id;
+};
+
+/* Return the absolute filename of process PID's /proc/PID/ns
+   entry for namespace NS.  The returned value persists until
+   this function is next called.  */
+
+static const char *
+linux_ns_filename (struct linux_ns *ns, int pid)
+{
+  static char filename[PATH_MAX];
+
+  gdb_assert (pid > 0);
+  xsnprintf (filename, sizeof (filename), "/proc/%d/ns/%s", pid,
+	     ns->filename);
+
+  return filename;
+}
+
+/* Return a representation of the caller's TYPE namespace, or
+   NULL if TYPE namespaces are not supported on this system.  */
+
+static struct linux_ns *
+linux_ns_get_namespace (enum linux_ns_type type)
+{
+  static struct linux_ns namespaces[NUM_LINUX_NS_TYPES] =
+    {
+      { "ipc" },
+      { "mnt" },
+      { "net" },
+      { "pid" },
+      { "user" },
+      { "uts" },
+    };
+  struct linux_ns *ns;
+
+  gdb_assert (type >= 0 && type < NUM_LINUX_NS_TYPES);
+  ns = &namespaces[type];
+
+  if (!ns->initialized)
+    {
+      struct stat sb;
+
+      if (stat (linux_ns_filename (ns, getpid ()), &sb) == 0)
+	{
+	  ns->id = sb.st_ino;
+
+	  ns->supported = 1;
+	}
+
+      ns->initialized = 1;
+    }
+
+  return ns->supported ? ns : NULL;
+}
+
+/* See nat/linux-namespaces.h.  */
+
+int
+linux_ns_same (pid_t pid, enum linux_ns_type type)
+{
+  struct linux_ns *ns = linux_ns_get_namespace (type);
+  const char *filename;
+  struct stat sb;
+
+  /* If the kernel does not support TYPE namespaces then there's
+     effectively only one TYPE namespace that all processes on
+     the system share.  */
+  if (ns == NULL)
+    return 1;
+
+  /* Stat PID's TYPE namespace entry to get the namespace ID.  This
+     might fail if the process died, or if we don't have the right
+     permissions (though we should be attached by this time so this
+     seems unlikely).  In any event, we can't make any decisions and
+     must throw.  */
+  filename = linux_ns_filename (ns, pid);
+  if (stat (filename, &sb) != 0)
+    perror_with_name (filename);
+
+  return sb.st_ino == ns->id;
+}
+
+/* We need to use setns(2) to handle filesystem access in mount
+   namespaces other than our own, but this isn't permitted for
+   multithreaded processes.  GDB is multithreaded when compiled
+   with Guile support, and may become multithreaded if compiled
+   with Python support.  We deal with this by spawning a single-
+   threaded helper process to access mount namespaces other than
+   our own.
+
+   The helper process is started the first time a call to setns
+   is required.  The main process (GDB or gdbserver) communicates
+   with the helper via sockets, passing file descriptors where
+   necessary using SCM_RIGHTS.  Once started the helper process
+   runs until the main process terminates; when this happens the
+   helper will receive socket errors, notice that its parent died,
+   and exit accordingly (see mnsh_maybe_mourn_peer).
+
+   The protocol is that the main process sends a request in a
+   single message, and the helper replies to every message it
+   receives with a single-message response.  If the helper
+   receives a message it does not understand it will reply with
+   a MNSH_MSG_ERROR message.  The main process checks all
+   responses it receives with gdb_assert, so if the main process
+   receives something unexpected (which includes MNSH_MSG_ERROR)
+   the main process will call internal_error.
+
+   For avoidance of doubt, if the helper process receives a
+   message it doesn't handle it will reply with MNSH_MSG_ERROR.
+   If the main process receives MNSH_MSG_ERROR at any time then
+   it will call internal_error.  If internal_error causes the
+   main process to exit, the helper will notice this and also
+   exit.  The helper will not exit until the main process
+   terminates, so if the user continues through internal_error
+   the helper will still be there awaiting requests from the
+   main process.
+
+   Messages in both directions have the following payload:
+
+   - TYPE (enum mnsh_msg_type, always sent) - the message type.
+   - INT1 and
+   - INT2 (int, always sent, though not always used) - two
+           values whose meaning is message-type-dependent.
+	   See enum mnsh_msg_type documentation below.
+   - FD (int, optional, sent using SCM_RIGHTS) - an open file
+         descriptor.
+   - BUF (unstructured data, optional) - some data with message-
+          type-dependent meaning.
+
+   Note that the helper process is the child of a call to fork,
+   so all code in the helper must be async-signal-safe.  */
+
+/* Mount namespace helper message types.  */
+
+enum mnsh_msg_type
+  {
+    /* An unrecoverable communication error occurred.
+       Receipt of this message by either end will cause
+       an assertion failure in the main process.  */
+    MNSH_MSG_ERROR,
+
+    /* Requests, sent from the main process to the helper.  */
+
+    /* A request that the helper call setns.  Arguments should
+       be passed in FD and INT1.  Helper should respond with a
+       MNSH_RET_INT.  */
+    MNSH_REQ_SETNS,
+
+    /* A request that the helper call open.  Arguments should
+       be passed in BUF, INT1 and INT2.  The filename (in BUF)
+       should include a terminating NUL character.  The helper
+       should respond with a MNSH_RET_FD.  */
+    MNSH_REQ_OPEN,
+
+    /* A request that the helper call unlink.  The single
+       argument (the filename) should be passed in BUF, and
+       should include a terminating NUL character.  Helper
+       should respond with a MNSH_RET_INT.  */
+    MNSH_REQ_UNLINK,
+
+    /* A request that the helper call readlink.  The single
+       argument (the filename) should be passed in BUF, and
+       should include a terminating NUL character. The helper
+       should respond with a MNSH_RET_INTSTR.  */
+    MNSH_REQ_READLINK,
+
+    /* Responses, sent to the main process from the helper.  */
+
+    /* Return an integer in INT1 and errno in INT2.  */
+    MNSH_RET_INT,
+
+    /* Return a file descriptor in FD if one was opened or an
+       integer in INT1 otherwise.  Return errno in INT2.  */
+    MNSH_RET_FD,
+
+    /* Return an integer in INT1, errno in INT2, and optionally
+       some data in BUF.  */
+    MNSH_RET_INTSTR,
+  };
+
+/* Print a string representation of a message using debug_printf.
+   This function is not async-signal-safe so should never be
+   called from the helper.  */
+
+static void
+mnsh_debug_print_message (enum mnsh_msg_type type,
+			  int fd, int int1, int int2,
+			  const void *buf, int bufsiz)
+{
+  gdb_byte *c = (gdb_byte *) buf;
+  gdb_byte *cl = c + bufsiz;
+
+  switch (type)
+    {
+    case MNSH_MSG_ERROR:
+      debug_printf ("ERROR");
+      break;
+
+    case MNSH_REQ_SETNS:
+      debug_printf ("SETNS");
+      break;
+
+    case MNSH_REQ_OPEN:
+      debug_printf ("OPEN");
+      break;
+
+    case MNSH_REQ_UNLINK:
+      debug_printf ("UNLINK");
+      break;
+
+    case MNSH_REQ_READLINK:
+      debug_printf ("READLINK");
+      break;
+
+    case MNSH_RET_INT:
+      debug_printf ("INT");
+      break;
+
+    case MNSH_RET_FD:
+      debug_printf ("FD");
+      break;
+
+    case MNSH_RET_INTSTR:
+      debug_printf ("INTSTR");
+      break;
+
+    default:
+      debug_printf ("unknown-packet-%d", type);
+    }
+
+  debug_printf (" %d %d %d \"", fd, int1, int2);
+
+  for (; c < cl; c++)
+    debug_printf (*c >= ' ' && *c <= '~' ? "%c" : "\\%o", *c);
+
+  debug_printf ("\"");
+}
+
+/* Forward declaration.  */
+
+static void mnsh_maybe_mourn_peer (void);
+
+/* Send a message.  The argument SOCK is the file descriptor of the
+   sending socket, the other arguments are the payload to send.
+   Return the number of bytes sent on success.  Return -1 on failure
+   and set errno appropriately.  This function is called by both the
+   main process and the helper so must be async-signal-safe.  */
+
+static ssize_t
+mnsh_send_message (int sock, enum mnsh_msg_type type,
+		   int fd, int int1, int int2,
+		   const void *buf, int bufsiz)
+{
+  struct msghdr msg;
+  struct iovec iov[4];
+  char fdbuf[CMSG_SPACE (sizeof (fd))];
+  ssize_t size;
+
+  /* Build the basic TYPE, INT1, INT2 message.  */
+  memset (&msg, 0, sizeof (msg));
+  msg.msg_iov = iov;
+
+  iov[0].iov_base = &type;
+  iov[0].iov_len = sizeof (type);
+  iov[1].iov_base = &int1;
+  iov[1].iov_len = sizeof (int1);
+  iov[2].iov_base = &int2;
+  iov[2].iov_len = sizeof (int2);
+
+  msg.msg_iovlen = 3;
+
+  /* Append BUF if supplied.  */
+  if (buf != NULL && bufsiz > 0)
+    {
+      iov[3].iov_base = alloca (bufsiz);
+      memcpy (iov[3].iov_base, buf, bufsiz);
+      iov[3].iov_len = bufsiz;
+
+      msg.msg_iovlen ++;
+    }
+
+  /* Attach FD if supplied.  */
+  if (fd >= 0)
+    {
+      struct cmsghdr *cmsg;
+
+      msg.msg_control = fdbuf;
+      msg.msg_controllen = sizeof (fdbuf);
+
+      cmsg = CMSG_FIRSTHDR (&msg);
+      cmsg->cmsg_level = SOL_SOCKET;
+      cmsg->cmsg_type = SCM_RIGHTS;
+      cmsg->cmsg_len = CMSG_LEN (sizeof (int));
+
+      *((int *) CMSG_DATA (cmsg)) = fd;
+
+      msg.msg_controllen = cmsg->cmsg_len;
+    }
+
+  /* Send the message.  */
+  size = sendmsg (sock, &msg, 0);
+
+  if (size < 0)
+    mnsh_maybe_mourn_peer ();
+
+  if (debug_linux_namespaces)
+    {
+      debug_printf ("mnsh: send: ");
+      mnsh_debug_print_message (type, fd, int1, int2, buf, bufsiz);
+      debug_printf (" -> %ld\n", size);
+    }
+
+  return size;
+}
+
+/* Receive a message.  The argument SOCK is the file descriptor of
+   the receiving socket, the other arguments point to storage for
+   the received payload.  Returns the number of bytes stored into
+   BUF on success, which may be zero in the event no BUF was sent.
+   Return -1 on failure and set errno appropriately.  This function
+   is called from both the main process and the helper and must be
+   async-signal-safe.  */
+
+static ssize_t
+mnsh_recv_message (int sock, enum mnsh_msg_type *type,
+		   int *fd, int *int1, int *int2,
+		   void *buf, int bufsiz)
+{
+  struct msghdr msg;
+  struct iovec iov[4];
+  char fdbuf[CMSG_SPACE (sizeof (*fd))];
+  struct cmsghdr *cmsg;
+  ssize_t size, fixed_size;
+  int i;
+
+  /* Build the message to receive data into.  */
+  memset (&msg, 0, sizeof (msg));
+  msg.msg_iov = iov;
+
+  iov[0].iov_base = type;
+  iov[0].iov_len = sizeof (*type);
+  iov[1].iov_base = int1;
+  iov[1].iov_len = sizeof (*int1);
+  iov[2].iov_base = int2;
+  iov[2].iov_len = sizeof (*int2);
+  iov[3].iov_base = buf;
+  iov[3].iov_len = bufsiz;
+
+  msg.msg_iovlen = 4;
+
+  for (fixed_size = i = 0; i < msg.msg_iovlen - 1; i++)
+    fixed_size += iov[i].iov_len;
+
+  msg.msg_control = fdbuf;
+  msg.msg_controllen = sizeof (fdbuf);
+
+  /* Receive the message.  */
+  size = recvmsg (sock, &msg, MSG_CMSG_CLOEXEC);
+  if (size < 0)
+    {
+      if (debug_linux_namespaces)
+	debug_printf ("namespace-helper: recv failed (%ld)\n", size);
+
+      mnsh_maybe_mourn_peer ();
+
+      return size;
+    }
+
+  /* Check for truncation.  */
+  if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
+    {
+      if (debug_linux_namespaces)
+	debug_printf ("namespace-helper: recv truncated (%ld 0x%x)\n",
+		      size, msg.msg_flags);
+
+      mnsh_maybe_mourn_peer ();
+
+      errno = EBADMSG;
+      return -1;
+    }
+
+  /* Unpack the file descriptor if supplied.  */
+  cmsg = CMSG_FIRSTHDR (&msg);
+  if (cmsg != NULL
+      && cmsg->cmsg_len == CMSG_LEN (sizeof (int))
+      && cmsg->cmsg_level == SOL_SOCKET
+      && cmsg->cmsg_type == SCM_RIGHTS)
+    *fd = *((int *) CMSG_DATA (cmsg));
+  else
+    *fd = -1;
+
+  if (debug_linux_namespaces)
+    {
+      debug_printf ("mnsh: recv: ");
+      mnsh_debug_print_message (*type, *fd, *int1, *int2, buf,
+				size - fixed_size);
+      debug_printf ("\n");
+    }
+
+  /* Return the number of bytes of data in BUF.  */
+  return size - fixed_size;
+}
+
+/* Shortcuts for returning results from the helper.  */
+
+#define mnsh_return_int(sock, result, error) \
+  mnsh_send_message (sock, MNSH_RET_INT, -1, result, error, NULL, 0)
+
+#define mnsh_return_fd(sock, fd, error) \
+  mnsh_send_message (sock, MNSH_RET_FD, \
+		     (fd) < 0 ? -1 : (fd), \
+		     (fd) < 0 ? (fd) : 0, \
+		     error, NULL, 0)
+
+#define mnsh_return_intstr(sock, result, buf, bufsiz, error) \
+  mnsh_send_message (sock, MNSH_RET_INTSTR, -1, result, error, \
+		     buf, bufsiz)
+
+/* Handle a MNSH_REQ_SETNS message.  Must be async-signal-safe.  */
+
+static ssize_t
+mnsh_handle_setns (int sock, int fd, int nstype)
+{
+  int result = setns (fd, nstype);
+
+  return mnsh_return_int (sock, result, errno);
+}
+
+/* Handle a MNSH_REQ_OPEN message.  Must be async-signal-safe.  */
+
+static ssize_t
+mnsh_handle_open (int sock, const char *filename,
+		  int flags, mode_t mode)
+{
+  int fd = gdb_open_cloexec (filename, flags, mode);
+  ssize_t result = mnsh_return_fd (sock, fd, errno);
+
+  if (fd >= 0)
+    close (fd);
+
+  return result;
+}
+
+/* Handle a MNSH_REQ_UNLINK message.  Must be async-signal-safe.  */
+
+static ssize_t
+mnsh_handle_unlink (int sock, const char *filename)
+{
+  int result = unlink (filename);
+
+  return mnsh_return_int (sock, result, errno);
+}
+
+/* Handle a MNSH_REQ_READLINK message.  Must be async-signal-safe.  */
+
+static ssize_t
+mnsh_handle_readlink (int sock, const char *filename)
+{
+  char buf[PATH_MAX];
+  int len = readlink (filename, buf, sizeof (buf));
+
+  return mnsh_return_intstr (sock, len,
+			     buf, len < 0 ? 0 : len,
+			     errno);
+}
+
+/* The helper process.  Never returns.  Must be async-signal-safe.  */
+
+static void mnsh_main (int sock) ATTRIBUTE_NORETURN;
+
+static void
+mnsh_main (int sock)
+{
+  while (1)
+    {
+      enum mnsh_msg_type type;
+      int fd, int1, int2;
+      char buf[PATH_MAX];
+      ssize_t size, response = -1;
+
+      size = mnsh_recv_message (sock, &type,
+				&fd, &int1, &int2,
+				buf, sizeof (buf));
+
+      if (size >= 0 && size < sizeof (buf))
+	{
+	  switch (type)
+	    {
+	    case MNSH_REQ_SETNS:
+	      if (fd > 0)
+		response = mnsh_handle_setns (sock, fd, int1);
+	      break;
+
+	    case MNSH_REQ_OPEN:
+	      if (buf[size - 1] == '\0')
+		response = mnsh_handle_open (sock, buf, int1, int2);
+	      break;
+
+	    case MNSH_REQ_UNLINK:
+	      if (buf[size - 1] == '\0')
+		response = mnsh_handle_unlink (sock, buf);
+	      break;
+
+	    case MNSH_REQ_READLINK:
+	      if (buf[size - 1] == '\0')
+		response = mnsh_handle_readlink (sock, buf);
+	      break;
+
+	    default:
+	      break; /* Handled below.  */
+	    }
+	}
+
+      /* Close any file descriptors we were passed.  */
+      if (fd >= 0)
+	close (fd);
+
+      /* Can't handle this message, bounce it back.  */
+      if (response < 0)
+	{
+	  if (size < 0)
+	    size = 0;
+
+	  mnsh_send_message (sock, MNSH_MSG_ERROR,
+			     -1, int1, int2, buf, size);
+	}
+    }
+}
+
+/* The mount namespace helper process.  */
+
+struct linux_mnsh
+{
+  /* PID of helper.  */
+  pid_t pid;
+
+  /* Socket for communication.  */
+  int sock;
+
+  /* ID of the mount namespace the helper is currently in.  */
+  ino_t nsid;
+};
+
+/* In the helper process this is set to the PID of the process that
+   created the helper (i.e. GDB or gdbserver).  In the main process
+   this is set to zero.  Used by mnsh_maybe_mourn_peer.  */
+static int mnsh_creator_pid = 0;
+
+/* Return an object representing the mount namespace helper process.
+   If no mount namespace helper process has been started then start
+   one.  Return NULL if no mount namespace helper process could be
+   started.  */
+
+static struct linux_mnsh *
+linux_mntns_get_helper (void)
+{
+  static struct linux_mnsh *helper = NULL;
+
+  if (helper == NULL)
+    {
+      static struct linux_mnsh h;
+      struct linux_ns *ns;
+      pid_t helper_creator = getpid ();
+      int sv[2];
+
+      ns = linux_ns_get_namespace (LINUX_NS_MNT);
+      if (ns == NULL)
+	return NULL;
+
+      if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
+	return NULL;
+
+      h.pid = fork ();
+      if (h.pid < 0)
+	{
+	  int saved_errno = errno;
+
+	  close (sv[0]);
+	  close (sv[1]);
+
+	  errno = saved_errno;
+	  return NULL;
+	}
+
+      if (h.pid == 0)
+	{
+	  /* Child process.  */
+	  close (sv[0]);
+
+	  mnsh_creator_pid = helper_creator;
+
+	  /* Debug printing isn't async-signal-safe.  */
+	  debug_linux_namespaces = 0;
+
+	  mnsh_main (sv[1]);
+	}
+
+      /* Parent process.  */
+      close (sv[1]);
+
+      helper = &h;
+      helper->sock = sv[0];
+      helper->nsid = ns->id;
+
+      if (debug_linux_namespaces)
+	debug_printf ("Started mount namespace helper process %d\n",
+		      helper->pid);
+    }
+
+  return helper;
+}
+
+/* Check whether the other process died and act accordingly.  Called
+   whenever a socket error occurs, from both the main process and the
+   helper.  Must be async-signal-safe when called from the helper.  */
+
+static void
+mnsh_maybe_mourn_peer (void)
+{
+  if (mnsh_creator_pid != 0)
+    {
+      /* We're in the helper.  Check if our current parent is the
+	 process that started us.  If it isn't, then our original
+	 parent died and we've been reparented.  Exit immediately
+	 if that's the case.  */
+      if (getppid () != mnsh_creator_pid)
+	_exit (0);
+    }
+  else
+    {
+      /* We're in the main process.  */
+
+      struct linux_mnsh *helper = linux_mntns_get_helper ();
+      int status;
+      pid_t pid;
+
+      if (helper->pid < 0)
+	{
+	  /* We already mourned it.  */
+	  return;
+	}
+
+      pid = waitpid (helper->pid, &status, WNOHANG);
+      if (pid == 0)
+	{
+	  /* The helper is still alive.  */
+	  return;
+	}
+      else if (pid == -1)
+	{
+	  if (errno == ECHILD)
+	    warning (_("mount namespace helper vanished?"));
+	  else
+	    internal_warning (__FILE__, __LINE__,
+			      _("unhandled error %d"), errno);
+	}
+      else if (pid == helper->pid)
+	{
+	  if (WIFEXITED (status))
+	    warning (_("mount namespace helper exited with status %d"),
+		     WEXITSTATUS (status));
+	  else if (WIFSIGNALED (status))
+	    warning (_("mount namespace helper killed by signal %d"),
+		     WTERMSIG (status));
+	  else
+	    internal_warning (__FILE__, __LINE__,
+			      _("unhandled status %d"), status);
+	}
+      else
+	internal_warning (__FILE__, __LINE__,
+			  _("unknown pid %d"), pid);
+
+      /* Something unrecoverable happened.  */
+      helper->pid = -1;
+    }
+}
+
+/* Shortcuts for sending messages to the helper.  */
+
+#define mnsh_send_setns(helper, fd, nstype) \
+  mnsh_send_message (helper->sock, MNSH_REQ_SETNS, fd, nstype, 0, \
+		     NULL, 0)
+
+#define mnsh_send_open(helper, filename, flags, mode) \
+  mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \
+    		     filename, strlen (filename) + 1)
+
+#define mnsh_send_unlink(helper, filename) \
+  mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \
+    		     filename, strlen (filename) + 1)
+
+#define mnsh_send_readlink(helper, filename) \
+  mnsh_send_message (helper->sock, MNSH_REQ_READLINK, -1, 0, 0, \
+    		     filename, strlen (filename) + 1)
+
+/* Receive a message from the helper.  Issue an assertion failure if
+   the message isn't a correctly-formatted MNSH_RET_INT.  Set RESULT
+   and ERROR and return 0 on success.  Set errno and return -1 on
+   failure.  */
+
+static int
+mnsh_recv_int (struct linux_mnsh *helper, int *result, int *error)
+{
+  enum mnsh_msg_type type;
+  char buf[PATH_MAX];
+  ssize_t size;
+  int fd;
+
+  size = mnsh_recv_message (helper->sock, &type, &fd,
+			    result, error,
+			    buf, sizeof (buf));
+  if (size < 0)
+    return -1;
+
+  gdb_assert (type == MNSH_RET_INT);
+  gdb_assert (fd == -1);
+  gdb_assert (size == 0);
+
+  return 0;
+}
+
+/* Receive a message from the helper.  Issue an assertion failure if
+   the message isn't a correctly-formatted MNSH_RET_FD.  Set FD and
+   ERROR and return 0 on success.  Set errno and return -1 on
+   failure.  */
+
+static int
+mnsh_recv_fd (struct linux_mnsh *helper, int *fd, int *error)
+{
+  enum mnsh_msg_type type;
+  char buf[PATH_MAX];
+  ssize_t size;
+  int result;
+
+  size = mnsh_recv_message (helper->sock, &type, fd,
+			    &result, error,
+			    buf, sizeof (buf));
+  if (size < 0)
+    return -1;
+
+  gdb_assert (type == MNSH_RET_FD);
+  gdb_assert (size == 0);
+
+  if (*fd < 0)
+    {
+      gdb_assert (result < 0);
+      *fd = result;
+    }
+
+  return 0;
+}
+
+/* Receive a message from the helper.  Issue an assertion failure if
+   the message isn't a correctly-formatted MNSH_RET_INTSTR.  Set
+   RESULT and ERROR and optionally store data in BUF, then return
+   the number of bytes stored in BUF on success (this may be zero).
+   Set errno and return -1 on error.  */
+
+static ssize_t
+mnsh_recv_intstr (struct linux_mnsh *helper,
+		  int *result, int *error,
+		  void *buf, int bufsiz)
+{
+  enum mnsh_msg_type type;
+  ssize_t size;
+  int fd;
+
+  size = mnsh_recv_message (helper->sock, &type, &fd,
+			    result, error,
+			    buf, bufsiz);
+
+  if (size < 0)
+    return -1;
+
+  gdb_assert (type == MNSH_RET_INTSTR);
+  gdb_assert (fd == -1);
+
+  return size;
+}
+
+/* Return values for linux_mntns_access_fs.  */
+
+enum mnsh_fs_code
+  {
+    /* Something went wrong, errno is set.  */
+    MNSH_FS_ERROR = -1,
+
+    /* The main process is in the correct mount namespace.
+       The caller should access the filesystem directly.  */
+    MNSH_FS_DIRECT,
+
+    /* The helper is in the correct mount namespace.
+       The caller should access the filesystem via the helper.  */
+    MNSH_FS_HELPER
+  };
+
+/* Return a value indicating how the caller should access the
+   mount namespace of process PID.  */
+
+static enum mnsh_fs_code
+linux_mntns_access_fs (pid_t pid)
+{
+  struct cleanup *old_chain;
+  struct linux_ns *ns;
+  struct stat sb;
+  struct linux_mnsh *helper;
+  ssize_t size;
+  int fd, saved_errno;
+
+  if (pid == getpid ())
+    return MNSH_FS_DIRECT;
+
+  ns = linux_ns_get_namespace (LINUX_NS_MNT);
+  if (ns == NULL)
+    return MNSH_FS_DIRECT;
+
+  old_chain = make_cleanup (null_cleanup, NULL);
+
+  fd = gdb_open_cloexec (linux_ns_filename (ns, pid), O_RDONLY, 0);
+  if (fd < 0)
+    goto error;
+
+  old_chain = make_cleanup_close (fd);
+
+  if (fstat (fd, &sb) != 0)
+    goto error;
+
+  if (sb.st_ino == ns->id)
+    {
+      do_cleanups (old_chain);
+
+      return MNSH_FS_DIRECT;
+    }
+
+  helper = linux_mntns_get_helper ();
+  if (helper == NULL)
+    goto error;
+
+  if (sb.st_ino != helper->nsid)
+    {
+      int result, error;
+
+      size = mnsh_send_setns (helper, fd, 0);
+      if (size < 0)
+	goto error;
+
+      if (mnsh_recv_int (helper, &result, &error) != 0)
+	goto error;
+
+      if (result != 0)
+	{
+	  errno = error;
+	  goto error;
+	}
+
+      helper->nsid = sb.st_ino;
+    }
+
+  do_cleanups (old_chain);
+
+  return MNSH_FS_HELPER;
+
+error:
+  saved_errno = errno;
+
+  do_cleanups (old_chain);
+
+  errno = saved_errno;
+  return MNSH_FS_ERROR;
+}
+
+/* See nat/linux-namespaces.h.  */
+
+int
+linux_mntns_open_cloexec (pid_t pid, const char *filename,
+			  int flags, mode_t mode)
+{
+  enum mnsh_fs_code access = linux_mntns_access_fs (pid);
+  struct linux_mnsh *helper;
+  int fd, error;
+  ssize_t size;
+
+  if (access == MNSH_FS_ERROR)
+    return -1;
+
+  if (access == MNSH_FS_DIRECT)
+    return gdb_open_cloexec (filename, flags, mode);
+
+  gdb_assert (access == MNSH_FS_HELPER);
+
+  helper = linux_mntns_get_helper ();
+
+  size = mnsh_send_open (helper, filename, flags, mode);
+  if (size < 0)
+    return -1;
+
+  if (mnsh_recv_fd (helper, &fd, &error) != 0)
+    return -1;
+
+  if (fd < 0)
+    errno = error;
+
+  return fd;
+}
+
+/* See nat/linux-namespaces.h.  */
+
+int
+linux_mntns_unlink (pid_t pid, const char *filename)
+{
+  enum mnsh_fs_code access = linux_mntns_access_fs (pid);
+  struct linux_mnsh *helper;
+  int ret, error;
+  ssize_t size;
+
+  if (access == MNSH_FS_ERROR)
+    return -1;
+
+  if (access == MNSH_FS_DIRECT)
+    return unlink (filename);
+
+  gdb_assert (access == MNSH_FS_HELPER);
+
+  helper = linux_mntns_get_helper ();
+
+  size = mnsh_send_unlink (helper, filename);
+  if (size < 0)
+    return -1;
+
+  if (mnsh_recv_int (helper, &ret, &error) != 0)
+    return -1;
+
+  if (ret != 0)
+    errno = error;
+
+  return ret;
+}
+
+/* See nat/linux-namespaces.h.  */
+
+ssize_t
+linux_mntns_readlink (pid_t pid, const char *filename,
+		      char *buf, size_t bufsiz)
+{
+  enum mnsh_fs_code access = linux_mntns_access_fs (pid);
+  struct linux_mnsh *helper;
+  int ret, error;
+  ssize_t size;
+
+  if (access == MNSH_FS_ERROR)
+    return -1;
+
+  if (access == MNSH_FS_DIRECT)
+    return readlink (filename, buf, bufsiz);
+
+  gdb_assert (access == MNSH_FS_HELPER);
+
+  helper = linux_mntns_get_helper ();
+
+  size = mnsh_send_readlink (helper, filename);
+  if (size < 0)
+    return -1;
+
+  size = mnsh_recv_intstr (helper, &ret, &error, buf, bufsiz);
+
+  if (size < 0)
+    {
+      ret = -1;
+      errno = error;
+    }
+  else
+    gdb_assert (size == ret);
+
+  return ret;
+}
diff --git a/gdb/nat/linux-namespaces.h b/gdb/nat/linux-namespaces.h
new file mode 100644
index 0000000..f9adc07
--- /dev/null
+++ b/gdb/nat/linux-namespaces.h
@@ -0,0 +1,76 @@
+/* Linux namespaces(7) support.
+
+   Copyright (C) 2015 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 LINUX_NAMESPACES_H
+#define LINUX_NAMESPACES_H
+
+/* Set to nonzero to enable debugging of Linux namespaces code.  */
+
+extern int debug_linux_namespaces;
+
+/* Enumeration of Linux namespace types.  */
+
+enum linux_ns_type
+  {
+    /* IPC namespace: System V IPC, POSIX message queues.  */
+    LINUX_NS_IPC,
+
+    /* Mount namespace: mount points.  */
+    LINUX_NS_MNT,
+
+    /* Network namespace: network devices, stacks, ports, etc.  */
+    LINUX_NS_NET,
+
+    /* PID namespace: process IDs.  */
+    LINUX_NS_PID,
+
+    /* User namespace: user and group IDs.  */
+    LINUX_NS_USER,
+
+    /* UTS namespace: hostname and NIS domain name.  */
+    LINUX_NS_UTS,
+
+    /* Number of Linux namespaces.  */
+    NUM_LINUX_NS_TYPES
+  };
+
+/* Return nonzero if process PID has the same TYPE namespace as the
+   calling process, or if the kernel does not support TYPE namespaces
+   (in which case there is only one TYPE namespace).  Return zero if
+   the kernel supports TYPE namespaces and the two processes have
+   different TYPE namespaces.  */
+
+extern int linux_ns_same (pid_t pid, enum linux_ns_type type);
+
+/* Like gdb_open_cloexec, but in the mount namespace of process
+   PID.  */
+
+extern int linux_mntns_open_cloexec (pid_t pid, const char *filename,
+				     int flags, mode_t mode);
+
+/* Like unlink(2), but in the mount namespace of process PID.  */
+
+extern int linux_mntns_unlink (pid_t pid, const char *filename);
+
+/* Like readlink(2), but in the mount namespace of process PID.  */
+
+extern ssize_t linux_mntns_readlink (pid_t pid, const char *filename,
+				     char *buf, size_t bufsiz);
+
+#endif /* LINUX_NAMESPACES_H */
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (15 preceding siblings ...)
  2015-04-30 12:45 ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Gary Benson
@ 2015-04-30 14:12 ` Gary Benson
  2015-04-30 17:10   ` Eli Zaretskii
  2015-05-21 15:04   ` Pedro Alves
  2015-04-30 14:12 ` [PATCH 1/9 v2] Move make_cleanup_close to common code Gary Benson
  2015-04-30 14:14 ` [PATCH 9/9 v2] Announce new container-awareness features for GNU/Linux systems Gary Benson
  18 siblings, 2 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-30 14:12 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit allows GDB to access executables and shared libraries
on remote targets where the remote stub does not share a common
filesystem with the inferior(s).  A new packet "vFile:setfs" is
added to the remote protocol and the three remote hostio functions
with filename arguments are modified to send "vFile:setfs" packets
as necessary.

gdb/ChangeLog:

	* remote.c (struct remote_state) <fs_pid>: New field.
	(new_remote_state): Initialize the above.
	(PACKET_vFile_setfs): New enum value.
	(remote_hostio_set_filesystem): New function.
	(remote_hostio_open): Call the above.
	(remote_hostio_unlink): Likewise.
	(remote_hostio_readlink): Likewise.
	(_initialize_remote): Register new "set/show remote
	hostio-setfs-packet" command.
	* NEWS: Announce new vFile:setfs packet.

gdb/doc/ChangeLog:

	* gdb.texinfo (Remote Configuration): Document the
	"set/show remote hostio-setfs-packet" command.
	(Host I/O Packets): Document the vFile:setfs packet.
---
 gdb/ChangeLog       |   13 +++++++++++
 gdb/NEWS            |    6 +++++
 gdb/doc/ChangeLog   |    6 +++++
 gdb/doc/gdb.texinfo |   18 ++++++++++++++++
 gdb/remote.c        |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 1c0e5ea..b4ce282 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -126,6 +126,12 @@ qXfer:exec-file:read
   Return the full absolute name of the file that was executed to
   create a process running on the remote system.
 
+vFile:setfs:
+  Select the filesystem on which vFile: operations with filename
+  arguments will operate.  This is required for GDB to be able to
+  access files on remote targets where the remote stub does not
+  share a common filesystem with the inferior(s).
+
 * The info record command now shows the recording format and the
   branch tracing configuration for the current thread when using
   the btrace record target.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9e2787d..d684579 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19890,6 +19890,10 @@ are:
 @tab @code{vFile:fstat}
 @tab Host I/O
 
+@item @code{hostio-setfs-packet}
+@tab @code{vFile:setfs}
+@tab Host I/O
+
 @item @code{noack-packet}
 @tab @code{QStartNoAckMode}
 @tab Packet acknowledgment
@@ -37591,6 +37595,20 @@ attachment (i.e.@: a trailing semicolon).  The return value is the
 number of target bytes read; the binary attachment may be longer if
 some characters were escaped.
 
+@item vFile:setfs: @var{pid}
+Select the filesystem on which @code{vFile} operations with
+@var{filename} arguments will operate.  This is required for
+@value{GDBN} to be able to access files on remote targets where
+the remote stub does not share a common filesystem with the
+inferior(s).
+
+If @var{pid} is nonzero, select the filesystem as seen by process
+@var{pid}.  If @var{pid} is zero, select the filesystem as seen by
+the remote stub.  Return 0 on success, or -1 if an error occurs.
+If @code{vFile:setfs:} indicates success, the selected filesystem
+remains selected until the next successful @code{vFile:setfs:}
+operation.
+
 @end table
 
 @node Interrupts
diff --git a/gdb/remote.c b/gdb/remote.c
index 330fbeb..ddb6cf6 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -367,6 +367,12 @@ struct remote_state
 
   /* The branch trace configuration.  */
   struct btrace_config btrace_config;
+
+  /* The argument to the last "vFile:setfs:" packet we sent, used
+     to avoid sending repeated unnecessary "vFile:setfs:" packets.
+     Initialized to -1 to indicate that no "vFile:setfs:" packet
+     has yet been sent.  */
+  int fs_pid;
 };
 
 /* Private data that we'll store in (struct thread_info)->private.  */
@@ -409,6 +415,7 @@ new_remote_state (void)
   result->buf = xmalloc (result->buf_size);
   result->remote_traceframe_number = -1;
   result->last_sent_signal = GDB_SIGNAL_0;
+  result->fs_pid = -1;
 
   return result;
 }
@@ -1243,6 +1250,7 @@ enum {
   PACKET_Z2,
   PACKET_Z3,
   PACKET_Z4,
+  PACKET_vFile_setfs,
   PACKET_vFile_open,
   PACKET_vFile_pread,
   PACKET_vFile_pwrite,
@@ -9879,6 +9887,43 @@ remote_hostio_send_command (int command_bytes, int which_packet,
   return ret;
 }
 
+/* Set the filesystem remote_hostio functions that take FILENAME
+   arguments will use.  Return 0 on success, or -1 if an error
+   occurs (and set *REMOTE_ERRNO).  */
+
+static int
+remote_hostio_set_filesystem (struct inferior *inf, int *remote_errno)
+{
+  struct remote_state *rs = get_remote_state ();
+  int required_pid = (inf == NULL || inf->fake_pid_p) ? 0 : inf->pid;
+  char *p = rs->buf;
+  int left = get_remote_packet_size () - 1;
+  char arg[9];
+  int ret;
+
+  if (packet_support (PACKET_vFile_setfs) == PACKET_DISABLE)
+    return 0;
+
+  if (rs->fs_pid != -1 && required_pid == rs->fs_pid)
+    return 0;
+
+  remote_buffer_add_string (&p, &left, "vFile:setfs:");
+
+  xsnprintf (arg, sizeof (arg), "%x", required_pid);
+  remote_buffer_add_string (&p, &left, arg);
+
+  ret = remote_hostio_send_command (p - rs->buf, PACKET_vFile_setfs,
+				    remote_errno, NULL, NULL);
+
+  if (packet_support (PACKET_vFile_setfs) == PACKET_DISABLE)
+    return 0;
+
+  if (ret == 0)
+    rs->fs_pid = required_pid;
+
+  return ret;
+}
+
 /* Implementation of to_fileio_open.  */
 
 static int
@@ -9890,6 +9935,9 @@ remote_hostio_open (struct target_ops *self,
   char *p = rs->buf;
   int left = get_remote_packet_size () - 1;
 
+  if (remote_hostio_set_filesystem (inf, remote_errno) != 0)
+    return -1;
+
   remote_buffer_add_string (&p, &left, "vFile:open:");
 
   remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
@@ -9999,6 +10047,9 @@ remote_hostio_unlink (struct target_ops *self,
   char *p = rs->buf;
   int left = get_remote_packet_size () - 1;
 
+  if (remote_hostio_set_filesystem (inf, remote_errno) != 0)
+    return -1;
+
   remote_buffer_add_string (&p, &left, "vFile:unlink:");
 
   remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
@@ -10023,6 +10074,9 @@ remote_hostio_readlink (struct target_ops *self,
   int read_len;
   char *ret;
 
+  if (remote_hostio_set_filesystem (inf, remote_errno) != 0)
+    return NULL;
+
   remote_buffer_add_string (&p, &left, "vFile:readlink:");
 
   remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
@@ -12355,6 +12409,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qTStatus],
 			 "qTStatus", "trace-status", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_setfs],
+			 "vFile:setfs", "hostio-setfs", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_open],
 			 "vFile:open", "hostio-open", 0);
 
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 1/9 v2] Move make_cleanup_close to common code
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (16 preceding siblings ...)
  2015-04-30 14:12 ` [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets Gary Benson
@ 2015-04-30 14:12 ` Gary Benson
  2015-05-21 14:56   ` Pedro Alves
  2015-04-30 14:14 ` [PATCH 9/9 v2] Announce new container-awareness features for GNU/Linux systems Gary Benson
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-30 14:12 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit moves the function make_cleanup_close from gdb/utils.[ch]
to gdb/common/cleanup-utils.[ch] to make it usable from common code.
A new file was created over putting the function in common-utils.[ch]
to avoid having to build cleanups.c into the in-process agent.

gdb/ChangeLog:

	* common/cleanup-utils.h: New file.
	* common/cleanup-utils.c: Likewise.
	* Makefile.in (SFILES): Add common/cleanup-utils.c.
	(HFILES_NO_SRCDIR): Add common/cleanup-utils.h.
	(COMMON_OBS): Add cleanup-utils.o.
	(cleanup-utils.o): New rule.
	* common/common-utils.h (cleanup-utils.h): New include.
	* utils.h (make_cleanup_close): Moved to cleanup-utils.h.
	* utils.c (do_close_cleanup): Moved to cleanup-utils.c.
	(make_cleanup_close): Likewise.

gdb/gdbserver/ChangeLog:

	* Makefile.in (SFILES): Add common/cleanup-utils.c.
	(OBS): Add cleanup-utils.o.
	(cleanup-utils.o): New rule.
---
 gdb/ChangeLog              |   13 +++++++++++++
 gdb/Makefile.in            |   12 +++++++++---
 gdb/common/cleanup-utils.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 gdb/common/cleanup-utils.h |   31 +++++++++++++++++++++++++++++++
 gdb/common/common-utils.h  |    2 ++
 gdb/gdbserver/ChangeLog    |    6 ++++++
 gdb/gdbserver/Makefile.in  |    6 +++++-
 gdb/utils.c                |   17 -----------------
 gdb/utils.h                |    2 +-
 9 files changed, 109 insertions(+), 22 deletions(-)
 create mode 100644 gdb/common/cleanup-utils.c
 create mode 100644 gdb/common/cleanup-utils.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 95104ef..47b216a 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -888,7 +888,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	common/format.c common/filestuff.c btrace.c record-btrace.c ctf.c \
 	target/waitstatus.c common/print-utils.c common/rsp-low.c \
 	common/errors.c common/common-debug.c common/common-exceptions.c \
-	common/btrace-common.c common/fileio.c \
+	common/btrace-common.c common/fileio.c common/cleanup-utils.c \
 	$(SUBDIR_GCC_COMPILE_SRCS)
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -979,7 +979,8 @@ i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \
 common/common-debug.h common/cleanups.h common/gdb_setjmp.h \
 common/common-exceptions.h target/target.h common/symbol.h \
 common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
-common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h
+common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h \
+common/cleanup-utils.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1079,7 +1080,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
 	format.o registry.o btrace.o record-btrace.o waitstatus.o \
 	print-utils.o rsp-low.o errors.o common-debug.o debug.o \
-	common-exceptions.o btrace-common.o fileio.o \
+	common-exceptions.o btrace-common.o fileio.o cleanup-utils.o \
 	$(SUBDIR_GCC_COMPILE_OBS)
 
 TSOBS = inflow.o
@@ -2260,6 +2261,11 @@ btrace-common.o: ${srcdir}/common/btrace-common.c
 fileio.o: ${srcdir}/common/fileio.c
 	$(COMPILE) $(srcdir)/common/fileio.c
 	$(POSTCOMPILE)
+
+cleanup-utils.o: ${srcdir}/common/cleanup-utils.c
+	$(COMPILE) $(srcdir)/common/cleanup-utils.c
+	$(POSTCOMPILE)
+
 #
 # gdb/target/ dependencies
 #
diff --git a/gdb/common/cleanup-utils.c b/gdb/common/cleanup-utils.c
new file mode 100644
index 0000000..829d067
--- /dev/null
+++ b/gdb/common/cleanup-utils.c
@@ -0,0 +1,42 @@
+/* Cleanup utilities for GDB, the GNU debugger.
+
+   Copyright (C) 1986-2015 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 "cleanup-utils.h"
+
+/* Helper function which does the work for make_cleanup_close.  */
+
+static void
+do_close_cleanup (void *arg)
+{
+  int *fd = arg;
+
+  close (*fd);
+}
+
+/* See cleanup-utils.h.  */
+
+struct cleanup *
+make_cleanup_close (int fd)
+{
+  int *saved_fd = xmalloc (sizeof (fd));
+
+  *saved_fd = fd;
+  return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
+}
diff --git a/gdb/common/cleanup-utils.h b/gdb/common/cleanup-utils.h
new file mode 100644
index 0000000..c5a0d50
--- /dev/null
+++ b/gdb/common/cleanup-utils.h
@@ -0,0 +1,31 @@
+/* Cleanup utilities for GDB, the GNU debugger.
+
+   Copyright (C) 1986-2015 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/>.  */
+
+/* Cleanup utilities.  These are not declared in cleanups.h
+   (nor defined in cleanups.c) because, while they use the
+   cleanup API, they are not part of the cleanup API.  */
+
+#ifndef CLEANUP_UTILS_H
+#define CLEANUP_UTILS_H
+
+/* Return a new cleanup that closes FD.  */
+
+extern struct cleanup *make_cleanup_close (int fd);
+
+#endif /* CLEANUP_UTILS_H */
diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
index cd2665a..dc3ceea 100644
--- a/gdb/common/common-utils.h
+++ b/gdb/common/common-utils.h
@@ -20,6 +20,8 @@
 #ifndef COMMON_UTILS_H
 #define COMMON_UTILS_H
 
+#include "cleanup-utils.h"
+
 /* If possible, define FUNCTION_NAME, a macro containing the name of
    the function being defined.  Since this macro may not always be
    defined, all uses must be protected by appropriate macro definition
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index a981ee8..8ba88d4 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -180,7 +180,7 @@ SFILES=	$(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
 	$(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c \
 	$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c \
 	$(srcdir)/common/btrace-common.c \
-	$(srcdir)/common/fileio.c
+	$(srcdir)/common/fileio.c $(srcdir)/common/cleanup-utils.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -195,6 +195,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
       common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
       tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
       common-exceptions.o symbol.o btrace-common.o fileio.o \
+      cleanup-utils.o \
       $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
 GDBREPLAY_OBS = gdbreplay.o version.o
 GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -615,6 +616,9 @@ x86-linux.o: ../nat/x86-linux.c
 x86-linux-dregs.o: ../nat/x86-linux-dregs.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+cleanup-utils.o: ../common/cleanup-utils.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 
 aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c
diff --git a/gdb/utils.c b/gdb/utils.c
index aaaf9c5..1c1ced4 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -191,23 +191,6 @@ make_cleanup_bfd_unref (bfd *abfd)
   return make_cleanup (do_bfd_close_cleanup, abfd);
 }
 
-static void
-do_close_cleanup (void *arg)
-{
-  int *fd = arg;
-
-  close (*fd);
-}
-
-struct cleanup *
-make_cleanup_close (int fd)
-{
-  int *saved_fd = xmalloc (sizeof (fd));
-
-  *saved_fd = fd;
-  return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
-}
-
 /* Helper function which does the work for make_cleanup_fclose.  */
 
 static void
diff --git a/gdb/utils.h b/gdb/utils.h
index cae1ac0..423feb5 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -80,7 +80,7 @@ struct section_addr_info;
 extern struct cleanup *(make_cleanup_free_section_addr_info 
                         (struct section_addr_info *));
 
-extern struct cleanup *make_cleanup_close (int fd);
+/* For make_cleanup_close see common/cleanup-utils.h.  */
 
 extern struct cleanup *make_cleanup_fclose (FILE *file);
 
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH 9/9 v2] Announce new container-awareness features for GNU/Linux systems
  2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
                   ` (17 preceding siblings ...)
  2015-04-30 14:12 ` [PATCH 1/9 v2] Move make_cleanup_close to common code Gary Benson
@ 2015-04-30 14:14 ` Gary Benson
  2015-04-30 16:20   ` Eli Zaretskii
  18 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-04-30 14:14 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

This commit announces the newly added ability to directly access
executable and shared library files when attaching to processes
running in containers on GNU/Linux systems.

gdb/ChangeLog:

	* NEWS: Announce support for direct access of executable and
	shared library files when attaching to inferiors in containers
	on GNU/Linux systems.
---
 gdb/ChangeLog |    6 ++++++
 gdb/NEWS      |    7 +++++++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index b4ce282..ba4fcf3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -46,6 +46,13 @@
 
 * GDB now supports the vector ABI on S/390 GNU/Linux targets.
 
+* On GNU/Linux, GDB and gdbserver are now able to access executable
+  and shared library files without a "set sysroot" command when
+  attaching to processes running in different mount namespaces from
+  the debugger.  This makes it possible to attach to processes in
+  containers as simply as "gdb -p PID" or "gdbserver --attach PID".
+  See "New remote packets" below.
+
 * Python Scripting
 
   ** gdb.Objfile objects have a new attribute "username",
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 9/9 v2] Announce new container-awareness features for GNU/Linux systems
  2015-04-30 14:14 ` [PATCH 9/9 v2] Announce new container-awareness features for GNU/Linux systems Gary Benson
@ 2015-04-30 16:20   ` Eli Zaretskii
  0 siblings, 0 replies; 84+ messages in thread
From: Eli Zaretskii @ 2015-04-30 16:20 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches, palves, dje, iago

> From: Gary Benson <gbenson@redhat.com>
> Cc: Eli Zaretskii <eliz@gnu.org>, Pedro Alves <palves@redhat.com>,
>         Doug Evans <dje@google.com>,
>         Iago López Galeiras <iago@endocode.com>
> Date: Thu, 30 Apr 2015 13:05:42 +0100
> 
> This commit announces the newly added ability to directly access
> executable and shared library files when attaching to processes
> running in containers on GNU/Linux systems.
> 
> gdb/ChangeLog:
> 
> 	* NEWS: Announce support for direct access of executable and
> 	shared library files when attaching to inferiors in containers
> 	on GNU/Linux systems.
> ---
>  gdb/ChangeLog |    6 ++++++
>  gdb/NEWS      |    7 +++++++
>  2 files changed, 13 insertions(+), 0 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index b4ce282..ba4fcf3 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -46,6 +46,13 @@
>  
>  * GDB now supports the vector ABI on S/390 GNU/Linux targets.
>  
> +* On GNU/Linux, GDB and gdbserver are now able to access executable
> +  and shared library files without a "set sysroot" command when
> +  attaching to processes running in different mount namespaces from
> +  the debugger.  This makes it possible to attach to processes in
> +  containers as simply as "gdb -p PID" or "gdbserver --attach PID".
> +  See "New remote packets" below.
> +

OK.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/9 v2] Implement mount namespace support for native Linux targets
  2015-04-30 12:06 ` [PATCH 6/9 v2] Implement mount namespace support for native Linux targets Gary Benson
@ 2015-04-30 16:24   ` Eli Zaretskii
  2015-04-30 18:05     ` Gary Benson
  2015-05-21 14:59   ` Pedro Alves
  1 sibling, 1 reply; 84+ messages in thread
From: Eli Zaretskii @ 2015-04-30 16:24 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches, palves, dje, iago

> From: Gary Benson <gbenson@redhat.com>
> Cc: Eli Zaretskii <eliz@gnu.org>, Pedro Alves <palves@redhat.com>,
>         Doug Evans <dje@google.com>,
>         Iago López Galeiras <iago@endocode.com>
> Date: Thu, 30 Apr 2015 13:05:39 +0100
> 
> +set debug lin-ns
> +show debug lin-ns
> +  Control display of debugging info regarding Linux namespaces.

Would it be better to have a more mnemonic name, like
"linux-namespace", for example?  IMO, "lin-ns" goes too far in making
its name shorter.

Otherwise, the documentation parts are OK.

Thanks.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets
  2015-04-30 14:12 ` [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets Gary Benson
@ 2015-04-30 17:10   ` Eli Zaretskii
  2015-05-21 15:04   ` Pedro Alves
  1 sibling, 0 replies; 84+ messages in thread
From: Eli Zaretskii @ 2015-04-30 17:10 UTC (permalink / raw)
  To: Gary Benson; +Cc: gdb-patches, palves, dje, iago

> From: Gary Benson <gbenson@redhat.com>
> Cc: Eli Zaretskii <eliz@gnu.org>, Pedro Alves <palves@redhat.com>,
>         Doug Evans <dje@google.com>,
>         Iago López Galeiras <iago@endocode.com>
> Date: Thu, 30 Apr 2015 13:05:40 +0100
> 
> gdb/ChangeLog:
> 
> 	* remote.c (struct remote_state) <fs_pid>: New field.
> 	(new_remote_state): Initialize the above.
> 	(PACKET_vFile_setfs): New enum value.
> 	(remote_hostio_set_filesystem): New function.
> 	(remote_hostio_open): Call the above.
> 	(remote_hostio_unlink): Likewise.
> 	(remote_hostio_readlink): Likewise.
> 	(_initialize_remote): Register new "set/show remote
> 	hostio-setfs-packet" command.
> 	* NEWS: Announce new vFile:setfs packet.
> 
> gdb/doc/ChangeLog:
> 
> 	* gdb.texinfo (Remote Configuration): Document the
> 	"set/show remote hostio-setfs-packet" command.
> 	(Host I/O Packets): Document the vFile:setfs packet.

OK for the documentation parts.

Thanks.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/9 v2] Implement mount namespace support for native Linux targets
  2015-04-30 16:24   ` Eli Zaretskii
@ 2015-04-30 18:05     ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-04-30 18:05 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves, dje, iago

Eli Zaretskii wrote:
> > From: Gary Benson <gbenson@redhat.com>
> > Cc: Eli Zaretskii <eliz@gnu.org>, Pedro Alves <palves@redhat.com>,
> >         Doug Evans <dje@google.com>,
> >         Iago López Galeiras <iago@endocode.com>
> > Date: Thu, 30 Apr 2015 13:05:39 +0100
> > 
> > +set debug lin-ns
> > +show debug lin-ns
> > +  Control display of debugging info regarding Linux namespaces.
> 
> Would it be better to have a more mnemonic name, like
> "linux-namespace", for example?  IMO, "lin-ns" goes too far in
> making its name shorter.

I can change that.  (I think I modelled it after the lin-lwp option).

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
       [not found]   ` <20150501000739.740.47967@domU-12-31-39-0A-A0-4F>
@ 2015-05-01  9:28     ` Gary Benson
  2015-05-01 13:18       ` Alban Crequy
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-05-01  9:28 UTC (permalink / raw)
  To: Alban Crequy
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

Alban Crequy wrote:
> On Thu, Apr 30, 2015 at 2:05 PM, Gary Benson <gbenson@redhat.com> wrote:
> > This commit introduces new shared files nat/linux-namespaces.[ch]
> > containing code to support Linux namespaces that will be used by
> > both GDB and gdbserver.
> 
> Thanks for working on this!
> 
> > +/* We need to use setns(2) to handle filesystem access in mount
> > +   namespaces other than our own, but this isn't permitted for
> > +   multithreaded processes.  GDB is multithreaded when compiled
> > +   with Guile support, and may become multithreaded if compiled
> > +   with Python support.  We deal with this by spawning a single-
> > +   threaded helper process to access mount namespaces other than
> > +   our own.
> 
> setns() needs CAP_SYS_CHROOT and CAP_SYS_ADMIN to change the mnt
> namespace.  So users will need to run gdb as root...

As root, or with those privileges yes.  But if you're attaching to
a process in a container, it's not running as the same UID as you;
you have to have CAP_SYS_PTRACE, for example, to even get to the
point where GDB wants to access the files.

The scenario I'm targeting is that you have an application you want
to debug running in a container.  You don't want to run GDB as root
on the container host, so you start a second container with just the
privileges you need and run GDB from there.

I've been testing this with Docker, which has --cap-add and --cap-drop
options to adjust what privileges containers are granted when they are
created with "docker run".  I'm assuming other containering systems
have something similar.

> Would accessing the files directly through
> /proc/<pid_of_traced_process>/root/usr/lib/debug/... work, without
> needing the superuser? If it works, it would also remove the
> requirement for the single-threaded helper process.

No, you need to be root (or have CAP_DAC_OVERRIDE or something) to
access /proc/PID/root.  There's also issues with symlinks pointing
back to / if you access the files that way.  I investigated it back
in February and I don't think you can handle paths with symlinks in
a way that's 100% race-free.  (I've not been overly concerned with
security but I didn't want to introduce a way for a hostile app to
exploit GDB to break out of its container.)

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-05-01  9:28     ` Gary Benson
@ 2015-05-01 13:18       ` Alban Crequy
  2015-05-01 20:29         ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Alban Crequy @ 2015-05-01 13:18 UTC (permalink / raw)
  To: Gary Benson
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

On Fri, May 1, 2015 at 11:28 AM, Gary Benson <gbenson@redhat.com> wrote:
>
> Alban Crequy wrote:
> > On Thu, Apr 30, 2015 at 2:05 PM, Gary Benson <gbenson@redhat.com> wrote:
> > > This commit introduces new shared files nat/linux-namespaces.[ch]
> > > containing code to support Linux namespaces that will be used by
> > > both GDB and gdbserver.
> >
> > Thanks for working on this!
> >
> > > +/* We need to use setns(2) to handle filesystem access in mount
> > > +   namespaces other than our own, but this isn't permitted for
> > > +   multithreaded processes.  GDB is multithreaded when compiled
> > > +   with Guile support, and may become multithreaded if compiled
> > > +   with Python support.  We deal with this by spawning a single-
> > > +   threaded helper process to access mount namespaces other than
> > > +   our own.
> >
> > setns() needs CAP_SYS_CHROOT and CAP_SYS_ADMIN to change the mnt
> > namespace.  So users will need to run gdb as root...
>
> As root, or with those privileges yes.  But if you're attaching to
> a process in a container, it's not running as the same UID as you;
> you have to have CAP_SYS_PTRACE, for example, to even get to the
> point where GDB wants to access the files.

Ok, I understand the scenario.

I had tried only with a non-root process in the container and gdb on
the host with the same uid, so I didn't need CAP_SYS_PTRACE. But
that's probably not a good use case.

> The scenario I'm targeting is that you have an application you want
> to debug running in a container.  You don't want to run GDB as root
> on the container host, so you start a second container with just the
> privileges you need and run GDB from there.

How do you get the pid of the process to give as a parameter to "gdb
-p" if gdb is running in a different pid namespace than the process to
debug?

> I've been testing this with Docker, which has --cap-add and --cap-drop
> options to adjust what privileges containers are granted when they are
> created with "docker run".  I'm assuming other containering systems
> have something similar.
>
> > Would accessing the files directly through
> > /proc/<pid_of_traced_process>/root/usr/lib/debug/... work, without
> > needing the superuser? If it works, it would also remove the
> > requirement for the single-threaded helper process.
>
> No, you need to be root (or have CAP_DAC_OVERRIDE or something) to
> access /proc/PID/root.  There's also issues with symlinks pointing
> back to / if you access the files that way.  I investigated it back
> in February and I don't think you can handle paths with symlinks in
> a way that's 100% race-free.  (I've not been overly concerned with
> security but I didn't want to introduce a way for a hostile app to
> exploit GDB to break out of its container.)

Thanks for the explanation.

Cheers,
Alban

> Cheers,
> Gary
>
> --
> http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-05-01 13:18       ` Alban Crequy
@ 2015-05-01 20:29         ` Gary Benson
  2015-05-06 18:55           ` Alban Crequy
  2015-05-07 10:39           ` Gary Benson
  0 siblings, 2 replies; 84+ messages in thread
From: Gary Benson @ 2015-05-01 20:29 UTC (permalink / raw)
  To: Alban Crequy
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

Alban Crequy wrote:
> On Fri, May 1, 2015 at 11:28 AM, Gary Benson <gbenson@redhat.com> wrote:
> > Alban Crequy wrote:
> > > On Thu, Apr 30, 2015 at 2:05 PM, Gary Benson <gbenson@redhat.com> wrote:
> > > > This commit introduces new shared files nat/linux-namespaces.[ch]
> > > > containing code to support Linux namespaces that will be used by
> > > > both GDB and gdbserver.
> > >
> > > Thanks for working on this!
> > >
> > > > +/* We need to use setns(2) to handle filesystem access in mount
> > > > +   namespaces other than our own, but this isn't permitted for
> > > > +   multithreaded processes.  GDB is multithreaded when compiled
> > > > +   with Guile support, and may become multithreaded if compiled
> > > > +   with Python support.  We deal with this by spawning a single-
> > > > +   threaded helper process to access mount namespaces other than
> > > > +   our own.
> > >
> > > setns() needs CAP_SYS_CHROOT and CAP_SYS_ADMIN to change the mnt
> > > namespace.  So users will need to run gdb as root...
> >
> > As root, or with those privileges yes.  But if you're attaching to
> > a process in a container, it's not running as the same UID as you;
> > you have to have CAP_SYS_PTRACE, for example, to even get to the
> > point where GDB wants to access the files.
> 
> Ok, I understand the scenario.
> 
> I had tried only with a non-root process in the container and gdb on
> the host with the same uid, so I didn't need CAP_SYS_PTRACE. But
> that's probably not a good use case.

Interesting... how'd you get the user IDs to line up?

> > The scenario I'm targeting is that you have an application you want
> > to debug running in a container.  You don't want to run GDB as root
> > on the container host, so you start a second container with just the
> > privileges you need and run GDB from there.
> 
> How do you get the pid of the process to give as a parameter to "gdb
> -p" if gdb is running in a different pid namespace than the process
> to debug?

It's the PID on the host, I've just been finding them with ps.  I'm
not sure how well that'd work if you had hundreds or thousands of
containers running though...  It'd be nice to have a command like ps
but that was limited to one container and that listed both inner and
outer PIDs, but I don't think any exist.  I don't think the kernel
even exports any way to translates PIDs from one PID namespace to
another... there were some patches back in November but I don't think
they got in.

> > > Would accessing the files directly through
> > > /proc/<pid_of_traced_process>/root/usr/lib/debug/... work, without
> > > needing the superuser? If it works, it would also remove the
> > > requirement for the single-threaded helper process.
> >
> > No, you need to be root (or have CAP_DAC_OVERRIDE or something) to
> > access /proc/PID/root.  There's also issues with symlinks pointing
> > back to / if you access the files that way.  I investigated it back
> > in February and I don't think you can handle paths with symlinks in
> > a way that's 100% race-free.  (I've not been overly concerned with
> > security but I didn't want to introduce a way for a hostile app to
> > exploit GDB to break out of its container.)
> 
> Thanks for the explanation.

No worries.  FWIW I expect you probably can access /proc/PID/root if
you're running with the same UID like you seem to be, but the symlink
issue is still there.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-05-01 20:29         ` Gary Benson
@ 2015-05-06 18:55           ` Alban Crequy
  2015-05-07  8:42             ` Gary Benson
  2015-05-07 10:39           ` Gary Benson
  1 sibling, 1 reply; 84+ messages in thread
From: Alban Crequy @ 2015-05-06 18:55 UTC (permalink / raw)
  To: Gary Benson
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

On Fri, May 1, 2015 at 1:29 PM, Gary Benson <gbenson@redhat.com> wrote:
> Alban Crequy wrote:
>> On Fri, May 1, 2015 at 11:28 AM, Gary Benson <gbenson@redhat.com> wrote:
>> > Alban Crequy wrote:
>> > > On Thu, Apr 30, 2015 at 2:05 PM, Gary Benson <gbenson@redhat.com> wrote:
>> > > > This commit introduces new shared files nat/linux-namespaces.[ch]
>> > > > containing code to support Linux namespaces that will be used by
>> > > > both GDB and gdbserver.
>> > >
>> > > Thanks for working on this!
>> > >
>> > > > +/* We need to use setns(2) to handle filesystem access in mount
>> > > > +   namespaces other than our own, but this isn't permitted for
>> > > > +   multithreaded processes.  GDB is multithreaded when compiled
>> > > > +   with Guile support, and may become multithreaded if compiled
>> > > > +   with Python support.  We deal with this by spawning a single-
>> > > > +   threaded helper process to access mount namespaces other than
>> > > > +   our own.
>> > >
>> > > setns() needs CAP_SYS_CHROOT and CAP_SYS_ADMIN to change the mnt
>> > > namespace.  So users will need to run gdb as root...
>> >
>> > As root, or with those privileges yes.  But if you're attaching to
>> > a process in a container, it's not running as the same UID as you;
>> > you have to have CAP_SYS_PTRACE, for example, to even get to the
>> > point where GDB wants to access the files.
>>
>> Ok, I understand the scenario.
>>
>> I had tried only with a non-root process in the container and gdb on
>> the host with the same uid, so I didn't need CAP_SYS_PTRACE. But
>> that's probably not a good use case.
>
> Interesting... how'd you get the user IDs to line up?

I just tested by manually writing in /etc/passwd in the container.

>> > The scenario I'm targeting is that you have an application you want
>> > to debug running in a container.  You don't want to run GDB as root
>> > on the container host, so you start a second container with just the
>> > privileges you need and run GDB from there.
>>
>> How do you get the pid of the process to give as a parameter to "gdb
>> -p" if gdb is running in a different pid namespace than the process
>> to debug?
>
> It's the PID on the host, I've just been finding them with ps.

But if you get the pid of the process to debug on the host, that pid
is not meaningful in the container where GDB is running. How can tell
gdb to attach to the pid if that pid is not visible in gdb's
container?

> I'm
> not sure how well that'd work if you had hundreds or thousands of
> containers running though...  It'd be nice to have a command like ps
> but that was limited to one container and that listed both inner and
> outer PIDs, but I don't think any exist.  I don't think the kernel
> even exports any way to translates PIDs from one PID namespace to
> another... there were some patches back in November but I don't think
> they got in.
>
>> > > Would accessing the files directly through
>> > > /proc/<pid_of_traced_process>/root/usr/lib/debug/... work, without
>> > > needing the superuser? If it works, it would also remove the
>> > > requirement for the single-threaded helper process.
>> >
>> > No, you need to be root (or have CAP_DAC_OVERRIDE or something) to
>> > access /proc/PID/root.  There's also issues with symlinks pointing
>> > back to / if you access the files that way.  I investigated it back
>> > in February and I don't think you can handle paths with symlinks in
>> > a way that's 100% race-free.  (I've not been overly concerned with
>> > security but I didn't want to introduce a way for a hostile app to
>> > exploit GDB to break out of its container.)
>>
>> Thanks for the explanation.
>
> No worries.  FWIW I expect you probably can access /proc/PID/root if
> you're running with the same UID like you seem to be, but the symlink
> issue is still there.
>
> Cheers,
> Gary
>
> --
> http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-05-06 18:55           ` Alban Crequy
@ 2015-05-07  8:42             ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-05-07  8:42 UTC (permalink / raw)
  To: Alban Crequy
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

Alban Crequy wrote:
> On Fri, May 1, 2015 at 1:29 PM, Gary Benson <gbenson@redhat.com> wrote:
> > Alban Crequy wrote:
> > > On Fri, May 1, 2015 at 11:28 AM, Gary Benson <gbenson@redhat.com> wrote:
> > > > The scenario I'm targeting is that you have an application you
> > > > want to debug running in a container.  You don't want to run
> > > > GDB as root on the container host, so you start a second
> > > > container with just the privileges you need and run GDB from
> > > > there.
> > >
> > > How do you get the pid of the process to give as a parameter to
> > > "gdb -p" if gdb is running in a different pid namespace than the
> > > process to debug?
> >
> > It's the PID on the host, I've just been finding them with ps.
> 
> But if you get the pid of the process to debug on the host, that pid
> is not meaningful in the container where GDB is running. How can
> tell gdb to attach to the pid if that pid is not visible in gdb's
> container?

Docker has an option --pid=host that starts a container without
creating a PID namespace for it.  I'm starting the debugger container
with that option so it can see the host PID namespace.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-05-01 20:29         ` Gary Benson
  2015-05-06 18:55           ` Alban Crequy
@ 2015-05-07 10:39           ` Gary Benson
  1 sibling, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-05-07 10:39 UTC (permalink / raw)
  To: Alban Crequy
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

Gary Benson wrote:
> Alban Crequy wrote:
> > On Fri, May 1, 2015 at 11:28 AM, Gary Benson <gbenson@redhat.com> wrote:
> > > Alban Crequy wrote:
> > > > On Thu, Apr 30, 2015 at 2:05 PM, Gary Benson <gbenson@redhat.com> wrote:
> > > The scenario I'm targeting is that you have an application you
> > > want to debug running in a container.  You don't want to run GDB
> > > as root on the container host, so you start a second container
> > > with just the privileges you need and run GDB from there.
> > 
> > How do you get the pid of the process to give as a parameter to
> > "gdb -p" if gdb is running in a different pid namespace than the
> > process to debug?
> 
> It's the PID on the host, I've just been finding them with ps.  I'm
> not sure how well that'd work if you had hundreds or thousands of
> containers running though...  It'd be nice to have a command like ps
> but that was limited to one container and that listed both inner and
> outer PIDs [snip]

FWIW the command I was looking for is "docker top":

  bash-4.2# docker ps
  CONTAINER ID  IMAGE    COMMAND  CREATED         STATUS         PORTS  NAMES
  615386bf33ac  rhel7:0  "bash"   11 minutes ago  Up 11 minutes         rhel7

  bash-4.2# docker top 615386bf33ac
  UID   PID   PPID  C  STIME  TTY    TIME      CMD
  root  2209  939   0  11:18  pts/1  00:00:00  bash
  root  2595  939   0  11:23  ?      00:00:00  nsenter-exec --nspid 2209 -- gdb -p 1
  root  2596  2595  0  11:23  ?      00:00:00  gdb -p 1
  root  2653  939   0  11:24  pts/4  00:00:00  nsenter-exec --nspid 2209 --console /dev/pts/4 -- bash
  root  2654  2653  0  11:24  pts/4  00:00:00  bash
  root  2674  2654  0  11:26  pts/4  00:00:01  /usr/bin/python /usr/bin/debuginfo-install gdb-7.6.1-64.el7.x86_64
  root  2675  2674  7  11:26  pts/4  00:00:22  /usr/bin/python /usr/libexec/urlgrabber-ext-down
  root  2676  2674  1  11:26  pts/4  00:00:03  /usr/bin/python /usr/libexec/urlgrabber-ext-down

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 3/9 v2] Remove linux_proc_pid_get_ns
  2015-04-30 12:06 ` [PATCH 3/9 v2] Remove linux_proc_pid_get_ns Gary Benson
@ 2015-05-21 14:56   ` Pedro Alves
  0 siblings, 0 replies; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 14:56 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:
> This commit removes linux_proc_pid_get_ns, and updates its only
> caller to use linux_ns_same instead.
> 
> gdb/ChangeLog:
> 
> 	* linux-thread-db.c (nat/linux-namespaces.h): New include.
> 	(check_pid_namespace_match): Use linux_ns_same rather than
> 	linux_proc_pid_get_ns to spot PID namespace mismatches.
> 	* nat/linux-procfs.h (linux_proc_pid_get_ns): Remove.
> 	* nat/linux-procfs.c (linux_proc_pid_get_ns): Likewise.

OK.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 1/9 v2] Move make_cleanup_close to common code
  2015-04-30 14:12 ` [PATCH 1/9 v2] Move make_cleanup_close to common code Gary Benson
@ 2015-05-21 14:56   ` Pedro Alves
  2015-05-27  9:52     ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 14:56 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:
> This commit moves the function make_cleanup_close from gdb/utils.[ch]
> to gdb/common/cleanup-utils.[ch] to make it usable from common code.
> A new file was created over putting the function in common-utils.[ch]
> to avoid having to build cleanups.c into the in-process agent.
> 

Hmm, how about avoiding creating another kitchensync, and
putting this in common/filestuff.[ch]?

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-04-30 12:45 ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Gary Benson
       [not found]   ` <20150501000739.740.47967@domU-12-31-39-0A-A0-4F>
@ 2015-05-21 14:56   ` Pedro Alves
  2015-05-27 10:14     ` Gary Benson
  2015-06-11  8:40     ` James Greenhalgh
  2015-06-15 15:02   ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Michael Eager
  2016-01-08 10:49   ` Yao Qi
  3 siblings, 2 replies; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 14:56 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:

...

> +   For avoidance of doubt, if the helper process receives a
> +   message it doesn't handle it will reply with MNSH_MSG_ERROR.
> +   If the main process receives MNSH_MSG_ERROR at any time then
> +   it will call internal_error.  If internal_error causes the
> +   main process to exit, the helper will notice this and also
> +   exit.  The helper will not exit until the main process
> +   terminates, so if the user continues through internal_error
> +   the helper will still be there awaiting requests from the
> +   main process.

...

> +/* Mount namespace helper message types.  */
> +
> +enum mnsh_msg_type
> +  {
> +    /* An unrecoverable communication error occurred.

I think "unrecoverable" here sounds a bit confusing, as it
contradicts the comment above that explains that the helper
is still awaiting requests if the user decides to continue
after internal_error.

> +       Receipt of this message by either end will cause
> +       an assertion failure in the main process.  */
> +    MNSH_MSG_ERROR,


> +    /* A request that the helper call unlink.  The single
> +       argument (the filename) should be passed in BUF, and
> +       should include a terminating NUL character.  Helper
> +       should respond with a MNSH_RET_INT.  */
> +    MNSH_REQ_UNLINK,
> +
> +    /* A request that the helper call readlink.  The single
> +       argument (the filename) should be passed in BUF, and
> +       should include a terminating NUL character. The helper

Missing double-space.

> +static void
> +mnsh_main (int sock)
> +{
> +  while (1)
> +    {
> +      enum mnsh_msg_type type;
> +      int fd, int1, int2;
> +      char buf[PATH_MAX];
> +      ssize_t size, response = -1;
> +
> +      size = mnsh_recv_message (sock, &type,
> +				&fd, &int1, &int2,
> +				buf, sizeof (buf));
> +
> +      if (size >= 0 && size < sizeof (buf))
> +	{
> +	  switch (type)
> +	    {
> +	    case MNSH_REQ_SETNS:
> +	      if (fd > 0)
> +		response = mnsh_handle_setns (sock, fd, int1);
> +	      break;
> +
> +	    case MNSH_REQ_OPEN:
> +	      if (buf[size - 1] == '\0')

Why these  == '\0' checks?  To protect against bugs?  In
that case, I guess this should be:

	      if (size > 0 && buf[size - 1] == '\0')

> +		response = mnsh_handle_open (sock, buf, int1, int2);
> +	      break;


And that's it.  Really all looks good to me.  :-)

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 5/9 v2] Add "inferior" argument to some target_fileio functions
  2015-04-30 12:06 ` [PATCH 5/9 v2] Add "inferior" argument to some target_fileio functions Gary Benson
@ 2015-05-21 14:57   ` Pedro Alves
  0 siblings, 0 replies; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 14:57 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:
> This commit adds a new argument to all target_fileio functions with
> filename arguments to allow the desired inferior to be specified.
> This allows GDB to support systems where processes do not necessarily
> share a common filesystem.

Looks good to me.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 4/9 v2] Comment and whitespace changes
  2015-04-30 12:15 ` [PATCH 4/9 v2] Comment and whitespace changes Gary Benson
@ 2015-05-21 14:57   ` Pedro Alves
  0 siblings, 0 replies; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 14:57 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:
> Comments on the various implementations of target fileio functions
> duplicate information documented in target.h.  This commit replaces
> the duplicated documentation with breadcrumbs, and inserts blank
> lines to separate comments from the functions they describe where
> necessary.
> 
> gdb/ChangeLog:
> 
> 	* inf-child.c (inf_child_fileio_open): Replace comment.
> 	(inf_child_fileio_pwrite): Likewise.
> 	(inf_child_fileio_pread): Likewise.
> 	(inf_child_fileio_fstat): Insert blank line before comment.
> 	(inf_child_fileio_close): Replace comment.
> 	(inf_child_fileio_unlink): Likewise.
> 	(inf_child_fileio_readlink): Likewise.
> 	* remote.c (remote_hostio_open): Likewise.
> 	(remote_hostio_pread): Likewise.
> 	(remote_hostio_pwrite): Likewise.
> 	(remote_hostio_close): Likewise.
> 	(remote_hostio_unlink): Likewise.
> 	(remote_hostio_readlink): Likewise.
> 	(remote_hostio_fstat): Likewise.
> 	(remote_filesystem_is_local): Likewise.
> 	* target.c (target_fileio_open): Likewise.
> 	(target_fileio_pwrite): Likewise.
> 	(target_fileio_pread): Likewise.
> 	(target_fileio_fstat): Insert blank line before comment.
> 	(target_fileio_close): Replace comment.
> 	(target_fileio_unlink): Likewise.
> 	(target_fileio_readlink): Likewise.
> 	(target_fileio_read_alloc): Likewise.
> 	(target_fileio_read_stralloc): Likewise.

OK.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/9 v2] Implement mount namespace support for native Linux targets
  2015-04-30 12:06 ` [PATCH 6/9 v2] Implement mount namespace support for native Linux targets Gary Benson
  2015-04-30 16:24   ` Eli Zaretskii
@ 2015-05-21 14:59   ` Pedro Alves
  2015-05-27 10:16     ` Gary Benson
  1 sibling, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 14:59 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:
> This commit allows GDB to access executables and shared libraries
> on native Linux targets where GDB and the inferior have different
> mount namespaces.


> +/* Implementation of to_fileio_open.  */
> +
> +static int
> +linux_nat_fileio_open (struct target_ops *self,
> +		       struct inferior *inf, const char *filename,
> +		       int flags, int mode, int *target_errno)
> +{
> +  int nat_flags;
> +  int fd;
> +
> +  if (fileio_to_host_openflags (flags, &nat_flags) == -1)
> +    {
> +      *target_errno = FILEIO_EINVAL;
> +      return -1;
> +    }
> +
> +  /* We do not need to convert MODE, since the fileio protocol
> +     uses the standard values.  */

Hmm, I'm not seeing how the fileio constants have to necessarily
match the host's.  So I don't understand this comment.  What
are these standard values?

> +  fd = linux_mntns_open_cloexec (linux_nat_fileio_pid_of (inf),
> +				 filename, nat_flags, mode);
> +  if (fd == -1)
> +    *target_errno = host_to_fileio_error (errno);
> +
> +  return fd;
> +}
> +

Otherwise this looks good to me.  I'll leave the "set debug" flag's
name up to you.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 8/9 v2] Implement vFile:setfs in gdbserver
  2015-04-30 12:41 ` [PATCH 8/9 v2] Implement vFile:setfs in gdbserver Gary Benson
@ 2015-05-21 15:00   ` Pedro Alves
  2015-06-09 14:11     ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 15:00 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:
> This commit implements the "vFile:setfs" packet in gdbserver.
> 
> gdb/gdbserver/ChangeLog:
> 
> 	* target.h (struct target_ops) <multifs_open>: New field.
> 	<multifs_unlink>: Likewise.
> 	<multifs_readlink>: Likewise.
> 	* linux-low.c (nat/linux-namespaces.h): New include.
> 	(linux_target_ops): Initialize the_target->multifs_open,
> 	the_target->multifs_unlink and the_target->multifs_readlink.
> 	* hostio.c (hostio_fs_pid): New static variable.
> 	(handle_setfs): New function.
> 	(handle_open): Use the_target->multifs_open as appropriate.
> 	(handle_unlink): Use the_target->multifs_unlink as appropriate.
> 	(handle_readlink): Use the_target->multifs_readlink as
> 	appropriate.
> 	(handle_vFile): Handle vFile:setfs packets.
> ---
>  gdb/gdbserver/ChangeLog   |   16 +++++++++++
>  gdb/gdbserver/hostio.c    |   62 ++++++++++++++++++++++++++++++++++++++++++--
>  gdb/gdbserver/linux-low.c |    4 +++
>  gdb/gdbserver/target.h    |   21 +++++++++++++++
>  4 files changed, 100 insertions(+), 3 deletions(-)
> 
> diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
> index 9e858d9..10cff5a 100644
> --- a/gdb/gdbserver/hostio.c
> +++ b/gdb/gdbserver/hostio.c
> @@ -243,6 +243,47 @@ hostio_reply_with_data (char *own_buf, char *buffer, int len,
>    return input_index;
>  }
>  
> +/* Process ID of inferior whose filesystem hostio functions
> +   that take FILENAME arguments will use.  Zero means to use
> +   our own filesystem.  */
> +
> +static int hostio_fs_pid = 0;


This should be cleared if GDB reconnects.

> +
> +/* Handle a "vFile:setfs:" packet.  */
> +
> +static void
> +handle_setfs (char *own_buf)
> +{
> +  char *p;
> +  int pid;
> +
> +  /* If the target doesn't have any of the in-filesystem-of methods
> +     then there's no point in GDB sending "vFile:setfs:" packets.  We
> +     reply with an empty packet (i.e. we pretend we don't understand
> +     "vFile:setfs:") and that should stop GDB sending any more.  */
> +  if (the_target->multifs_open == NULL
> +      && the_target->multifs_unlink == NULL
> +      && the_target->multifs_readlink == NULL)
> +    {
> +      own_buf[0] = '\0';
> +      return;
> +    }

For the setns/ENOSYS case, how about somehow probing whether setns
actually works here (with a new method, or probing one of the existing
ones with getpid()) and return empty packet, instead of ending up with
open failing with ENOSYS later on?

Some comment for the native side, actually.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets
  2015-04-30 14:12 ` [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets Gary Benson
  2015-04-30 17:10   ` Eli Zaretskii
@ 2015-05-21 15:04   ` Pedro Alves
  1 sibling, 0 replies; 84+ messages in thread
From: Pedro Alves @ 2015-05-21 15:04 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Doug Evans, Iago López Galeiras

On 04/30/2015 01:05 PM, Gary Benson wrote:

> @@ -9890,6 +9935,9 @@ remote_hostio_open (struct target_ops *self,
>    char *p = rs->buf;
>    int left = get_remote_packet_size () - 1;
>  
> +  if (remote_hostio_set_filesystem (inf, remote_errno) != 0)
> +    return -1;

I guess this is where the ENOSYS issue (and likewise in the native
target) we were discussing before (in the vgdb patch) comes from.
I'm not yet convinced it's a good idea to have setns==ENOSYS result
in open==ENOSYS.

Other than this issue, the whole series looks good to me.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 1/9 v2] Move make_cleanup_close to common code
  2015-05-21 14:56   ` Pedro Alves
@ 2015-05-27  9:52     ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-05-27  9:52 UTC (permalink / raw)
  To: Pedro Alves
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

Pedro Alves wrote:
> On 04/30/2015 01:05 PM, Gary Benson wrote:
> > This commit moves the function make_cleanup_close from gdb/utils.[ch]
> > to gdb/common/cleanup-utils.[ch] to make it usable from common code.
> > A new file was created over putting the function in common-utils.[ch]
> > to avoid having to build cleanups.c into the in-process agent.
> 
> Hmm, how about avoiding creating another kitchensync, and putting
> this in common/filestuff.[ch]?

I can do that.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-05-21 14:56   ` Pedro Alves
@ 2015-05-27 10:14     ` Gary Benson
  2015-06-11  8:40     ` James Greenhalgh
  1 sibling, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-05-27 10:14 UTC (permalink / raw)
  To: Pedro Alves
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

Pedro Alves wrote:
> On 04/30/2015 01:05 PM, Gary Benson wrote:
> ...
> > +   For avoidance of doubt, if the helper process receives a
> > +   message it doesn't handle it will reply with MNSH_MSG_ERROR.
> > +   If the main process receives MNSH_MSG_ERROR at any time then
> > +   it will call internal_error.  If internal_error causes the
> > +   main process to exit, the helper will notice this and also
> > +   exit.  The helper will not exit until the main process
> > +   terminates, so if the user continues through internal_error
> > +   the helper will still be there awaiting requests from the
> > +   main process.
> ...
> > +/* Mount namespace helper message types.  */
> > +
> > +enum mnsh_msg_type
> > +  {
> > +    /* An unrecoverable communication error occurred.
> 
> I think "unrecoverable" here sounds a bit confusing, as it
> contradicts the comment above that explains that the helper
> is still awaiting requests if the user decides to continue
> after internal_error.

Ok, I'll remove the "unrecoverable" and leave the rest of the
message alone.

> > +    /* A request that the helper call readlink.  The single
> > +       argument (the filename) should be passed in BUF, and
> > +       should include a terminating NUL character. The helper
> 
> Missing double-space.

Ok.

> > +static void
> > +mnsh_main (int sock)
> > +{
> > +  while (1)
> > +    {
> > +      enum mnsh_msg_type type;
> > +      int fd, int1, int2;
> > +      char buf[PATH_MAX];
> > +      ssize_t size, response = -1;
> > +
> > +      size = mnsh_recv_message (sock, &type,
> > +				&fd, &int1, &int2,
> > +				buf, sizeof (buf));
> > +
> > +      if (size >= 0 && size < sizeof (buf))
> > +	{
> > +	  switch (type)
> > +	    {
> > +	    case MNSH_REQ_SETNS:
> > +	      if (fd > 0)
> > +		response = mnsh_handle_setns (sock, fd, int1);
> > +	      break;
> > +
> > +	    case MNSH_REQ_OPEN:
> > +	      if (buf[size - 1] == '\0')
> 
> Why these  == '\0' checks?  To protect against bugs?  In
> that case, I guess this should be:

> 	      if (size > 0 && buf[size - 1] == '\0')
> 
> > +		response = mnsh_handle_open (sock, buf, int1, int2);
> > +	      break;

Yeah, that's better, I'll change it.

> And that's it.  Really all looks good to me.  :-)

Sweet :)

Thanks,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 6/9 v2] Implement mount namespace support for native Linux targets
  2015-05-21 14:59   ` Pedro Alves
@ 2015-05-27 10:16     ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-05-27 10:16 UTC (permalink / raw)
  To: Pedro Alves
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

Pedro Alves wrote:
> On 04/30/2015 01:05 PM, Gary Benson wrote:
> > This commit allows GDB to access executables and shared libraries
> > on native Linux targets where GDB and the inferior have different
> > mount namespaces.
> 
> > +/* Implementation of to_fileio_open.  */
> > +
> > +static int
> > +linux_nat_fileio_open (struct target_ops *self,
> > +		       struct inferior *inf, const char *filename,
> > +		       int flags, int mode, int *target_errno)
> > +{
> > +  int nat_flags;
> > +  int fd;
> > +
> > +  if (fileio_to_host_openflags (flags, &nat_flags) == -1)
> > +    {
> > +      *target_errno = FILEIO_EINVAL;
> > +      return -1;
> > +    }
> > +
> > +  /* We do not need to convert MODE, since the fileio protocol
> > +     uses the standard values.  */
> 
> Hmm, I'm not seeing how the fileio constants have to necessarily
> match the host's.  So I don't understand this comment.  What
> are these standard values?

Hmmm, I just copied this from inf_child_fileio_open.  Maybe I should
fix that first, with some convertor function that the compiler can
essentially optimize away *if* the values really do match.

> Otherwise this looks good to me.  I'll leave the "set debug" flag's
> name up to you.

Cool, thanks.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 8/9 v2] Implement vFile:setfs in gdbserver
  2015-05-21 15:00   ` Pedro Alves
@ 2015-06-09 14:11     ` Gary Benson
  2015-06-09 14:23       ` Pedro Alves
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-06-09 14:11 UTC (permalink / raw)
  To: Pedro Alves
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

Pedro Alves wrote:
> On 04/30/2015 01:05 PM, Gary Benson wrote:
> > This commit implements the "vFile:setfs" packet in gdbserver.
> > 
> > gdb/gdbserver/ChangeLog:
> > 
> > 	* target.h (struct target_ops) <multifs_open>: New field.
> > 	<multifs_unlink>: Likewise.
> > 	<multifs_readlink>: Likewise.
> > 	* linux-low.c (nat/linux-namespaces.h): New include.
> > 	(linux_target_ops): Initialize the_target->multifs_open,
> > 	the_target->multifs_unlink and the_target->multifs_readlink.
> > 	* hostio.c (hostio_fs_pid): New static variable.
> > 	(handle_setfs): New function.
> > 	(handle_open): Use the_target->multifs_open as appropriate.
> > 	(handle_unlink): Use the_target->multifs_unlink as appropriate.
> > 	(handle_readlink): Use the_target->multifs_readlink as
> > 	appropriate.
> > 	(handle_vFile): Handle vFile:setfs packets.
> > ---
> >  gdb/gdbserver/ChangeLog   |   16 +++++++++++
> >  gdb/gdbserver/hostio.c    |   62 ++++++++++++++++++++++++++++++++++++++++++--
> >  gdb/gdbserver/linux-low.c |    4 +++
> >  gdb/gdbserver/target.h    |   21 +++++++++++++++
> >  4 files changed, 100 insertions(+), 3 deletions(-)
> > 
> > diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
> > index 9e858d9..10cff5a 100644
> > --- a/gdb/gdbserver/hostio.c
> > +++ b/gdb/gdbserver/hostio.c
> > @@ -243,6 +243,47 @@ hostio_reply_with_data (char *own_buf, char *buffer, int len,
> >    return input_index;
> >  }
> >  
> > +/* Process ID of inferior whose filesystem hostio functions
> > +   that take FILENAME arguments will use.  Zero means to use
> > +   our own filesystem.  */
> > +
> > +static int hostio_fs_pid = 0;
> 
> 
> This should be cleared if GDB reconnects.

Ok, I added a hostio_handle_new_gdb_connection function to do this
that's called just after target_handle_new_gdb_connection in server.c.

> > +/* Handle a "vFile:setfs:" packet.  */
> > +
> > +static void
> > +handle_setfs (char *own_buf)
> > +{
> > +  char *p;
> > +  int pid;
> > +
> > +  /* If the target doesn't have any of the in-filesystem-of methods
> > +     then there's no point in GDB sending "vFile:setfs:" packets.  We
> > +     reply with an empty packet (i.e. we pretend we don't understand
> > +     "vFile:setfs:") and that should stop GDB sending any more.  */
> > +  if (the_target->multifs_open == NULL
> > +      && the_target->multifs_unlink == NULL
> > +      && the_target->multifs_readlink == NULL)
> > +    {
> > +      own_buf[0] = '\0';
> > +      return;
> > +    }
> 
> For the setns/ENOSYS case, how about somehow probing whether setns
> actually works here (with a new method, or probing one of the
> existing ones with getpid()) and return empty packet, instead of
> ending up with open failing with ENOSYS later on?

Probing and then telling GDB we don't understand "vFile:setfs:" isn't
that good of an idea.  If we do that with an inferior in another mount
namespace then the end result is that gdbserver will access the wrong
filesystem.  You might get "file not found", or you might get an open
filehandle on another file (i.e. the file with the same name but in
gdbserver's filesystem).  If the inferior's filesystem is different
from gdbserver and gdbserver cannot access that filesystem then the
only correct response is to fail.

I've updated linux_mntns_access_fs to translate ENOSYS from setns
into ENOTSUP, so neither native nor gdbserver will ever get ENOSYS
from this code. From [1] ENOTSUP seems to be the perfect code for
linux_mntns_{open_cloexec,unlink,readlink} to be returning:

  A function returns this error when certain parameter values are
  valid, but the functionality they request is not available. This can
  mean that the function does not implement a particular command or
  option value or flag bit at all. ...  If the entire function is not
  available at all in the implementation, it returns ENOSYS instead.

Thanks for hassling me about this, it took me a while to understand
what you were saying.

Cheers,
Gary

--
[1] http://lkml.iu.edu/hypermail/linux/kernel/0208.0/0121.html

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 8/9 v2] Implement vFile:setfs in gdbserver
  2015-06-09 14:11     ` Gary Benson
@ 2015-06-09 14:23       ` Pedro Alves
  2015-06-10  9:01         ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-06-09 14:23 UTC (permalink / raw)
  To: Gary Benson
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

On 06/09/2015 03:11 PM, Gary Benson wrote:
> Pedro Alves wrote:

>> For the setns/ENOSYS case, how about somehow probing whether setns
>> actually works here (with a new method, or probing one of the
>> existing ones with getpid()) and return empty packet, instead of
>> ending up with open failing with ENOSYS later on?
> 
> Probing and then telling GDB we don't understand "vFile:setfs:" isn't
> that good of an idea.  If we do that with an inferior in another mount
> namespace then the end result is that gdbserver will access the wrong
> filesystem.  You might get "file not found", or you might get an open
> filehandle on another file (i.e. the file with the same name but in
> gdbserver's filesystem).  If the inferior's filesystem is different
> from gdbserver and gdbserver cannot access that filesystem then the
> only correct response is to fail.

If the running system does not support "setfs", because it fails setns
with ENOSYS, meaning, the system call isn't implemented at all, how
can one end up in the situation that an inferior on the same kernel
is running in a different filesystem namespace?

> 
> I've updated linux_mntns_access_fs to translate ENOSYS from setns
> into ENOTSUP, so neither native nor gdbserver will ever get ENOSYS
> from this code. From [1] ENOTSUP seems to be the perfect code for
> linux_mntns_{open_cloexec,unlink,readlink} to be returning:

Great, thanks.

> Thanks for hassling me about this, it took me a while to understand
> what you were saying.

Thanks for the patience and following through.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 8/9 v2] Implement vFile:setfs in gdbserver
  2015-06-09 14:23       ` Pedro Alves
@ 2015-06-10  9:01         ` Gary Benson
  2015-06-10  9:41           ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-06-10  9:01 UTC (permalink / raw)
  To: Pedro Alves
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

Pedro Alves wrote:
> On 06/09/2015 03:11 PM, Gary Benson wrote:
> > Pedro Alves wrote:
> > > For the setns/ENOSYS case, how about somehow probing whether
> > > setns actually works here (with a new method, or probing one
> > > of the existing ones with getpid()) and return empty packet,
> > > instead of ending up with open failing with ENOSYS later on?
> > 
> > Probing and then telling GDB we don't understand "vFile:setfs:"
> > isn't that good of an idea.  If we do that with an inferior in
> > another mount namespace then the end result is that gdbserver will
> > access the wrong filesystem.  You might get "file not found", or
> > you might get an open filehandle on another file (i.e. the file
> > with the same name but in gdbserver's filesystem).  If the
> > inferior's filesystem is different from gdbserver and gdbserver
> > cannot access that filesystem then the only correct response is
> > to fail.
> 
> If the running system does not support "setfs", because it fails
> setns with ENOSYS, meaning, the system call isn't implemented at
> all, how can one end up in the situation that an inferior on the
> same kernel is running in a different filesystem namespace?

If the running kernel has namespaces support but GDB and/or glibc
was built on a kernel without.  It's an edge case but it's possible.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 8/9 v2] Implement vFile:setfs in gdbserver
  2015-06-10  9:01         ` Gary Benson
@ 2015-06-10  9:41           ` Gary Benson
  2015-06-10 14:53             ` Pedro Alves
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-06-10  9:41 UTC (permalink / raw)
  To: Pedro Alves
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

Gary Benson wrote:
> Pedro Alves wrote:
> > On 06/09/2015 03:11 PM, Gary Benson wrote:
> > > Pedro Alves wrote:
> > > > For the setns/ENOSYS case, how about somehow probing whether
> > > > setns actually works here (with a new method, or probing one
> > > > of the existing ones with getpid()) and return empty packet,
> > > > instead of ending up with open failing with ENOSYS later on?
> > > 
> > > Probing and then telling GDB we don't understand "vFile:setfs:"
> > > isn't that good of an idea.  If we do that with an inferior in
> > > another mount namespace then the end result is that gdbserver will
> > > access the wrong filesystem.  You might get "file not found", or
> > > you might get an open filehandle on another file (i.e. the file
> > > with the same name but in gdbserver's filesystem).  If the
> > > inferior's filesystem is different from gdbserver and gdbserver
> > > cannot access that filesystem then the only correct response is
> > > to fail.
> > 
> > If the running system does not support "setfs", because it fails
> > setns with ENOSYS, meaning, the system call isn't implemented at
> > all, how can one end up in the situation that an inferior on the
> > same kernel is running in a different filesystem namespace?
> 
> If the running kernel has namespaces support but GDB and/or glibc
> was built on a kernel without.  It's an edge case but it's possible.

Note that GDB/gdbserver will not attempt to call setns unless the
inferior is actually in a different mount namespace.  If you're
running without namespaces support it won't even start the helper
let alone try to setns.  Same goes for if you have namespaces
support but the inferior is in GDB/gdbserver's mount namespace.
Nothing calls setns unless it is 100% necessary.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [pushed][PATCH 0/9 v2] GNU/Linux mount namespace support
  2015-04-30 12:06 ` [PATCH 0/9 v2] GNU/Linux mount namespace support Gary Benson
@ 2015-06-10 14:23   ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-06-10 14:23 UTC (permalink / raw)
  To: gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

Gary Benson wrote:
> This series allows GDB and gdbserver on GNU/Linux systems to access
> executable and shared library files from mount namespaces other than
> the debugger's own without requiring "set sysroot" commands.  This
> makes attaching to processes in containers as simple as "gdb -p PID"
> or "gdbserver --attach PID".

I've pushed this series with the various suggested changes.
Thank you everyone for the reviews and input.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 8/9 v2] Implement vFile:setfs in gdbserver
  2015-06-10  9:41           ` Gary Benson
@ 2015-06-10 14:53             ` Pedro Alves
  0 siblings, 0 replies; 84+ messages in thread
From: Pedro Alves @ 2015-06-10 14:53 UTC (permalink / raw)
  To: Gary Benson
  Cc: gdb-patches, Eli Zaretskii, Doug Evans, Iago López Galeiras

On 06/10/2015 10:40 AM, Gary Benson wrote:
> Gary Benson wrote:
>> Pedro Alves wrote:
>>> On 06/09/2015 03:11 PM, Gary Benson wrote:
>>>> Pedro Alves wrote:
>>>>> For the setns/ENOSYS case, how about somehow probing whether
>>>>> setns actually works here (with a new method, or probing one
>>>>> of the existing ones with getpid()) and return empty packet,
>>>>> instead of ending up with open failing with ENOSYS later on?
>>>>
>>>> Probing and then telling GDB we don't understand "vFile:setfs:"
>>>> isn't that good of an idea.  If we do that with an inferior in
>>>> another mount namespace then the end result is that gdbserver will
>>>> access the wrong filesystem.  You might get "file not found", or
>>>> you might get an open filehandle on another file (i.e. the file
>>>> with the same name but in gdbserver's filesystem).  If the
>>>> inferior's filesystem is different from gdbserver and gdbserver
>>>> cannot access that filesystem then the only correct response is
>>>> to fail.
>>>
>>> If the running system does not support "setfs", because it fails
>>> setns with ENOSYS, meaning, the system call isn't implemented at
>>> all, how can one end up in the situation that an inferior on the
>>> same kernel is running in a different filesystem namespace?
>>
>> If the running kernel has namespaces support but GDB and/or glibc
>> was built on a kernel without.  It's an edge case but it's possible.

I see.

> 
> Note that GDB/gdbserver will not attempt to call setns unless the
> inferior is actually in a different mount namespace.  If you're
> running without namespaces support it won't even start the helper
> let alone try to setns.  Same goes for if you have namespaces
> support but the inferior is in GDB/gdbserver's mount namespace.
> Nothing calls setns unless it is 100% necessary.

To probe for setns I was thinking would be done by on
gdb/gdbserver's pid, by gdb/gdbserver directly.

But I agree, when the kernel supports namespaces, and we can
tell the inferior is in a different namespace, but then setns
doesn't work, it's better to error out than disabling the setfs
packet.  So I'm happy with the errno translation alone.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-05-21 14:56   ` Pedro Alves
  2015-05-27 10:14     ` Gary Benson
@ 2015-06-11  8:40     ` James Greenhalgh
  2015-06-11 11:04       ` Pedro Alves
  1 sibling, 1 reply; 84+ messages in thread
From: James Greenhalgh @ 2015-06-11  8:40 UTC (permalink / raw)
  To: Pedro Alves
  Cc: Gary Benson, gdb-patches, Eli Zaretskii, Doug Evans,
	Iago López Galeiras

Hi,

This patch broke a -Werror native build on ARM for me as so:

---
.../src/binutils-gdb/gdb/gdbserver/../nat/linux-namespaces.c: In function 'mnsh_send_message':
.../src/binutils-gdb/gdb/gdbserver/../nat/linux-namespaces.c:377:28: error: format '%ld' expects argument of type 'long int', but argument 2 has type 'ssize_t {aka int}' [-Werror=format=]
       debug_printf (" -> %ld\n", size);
                            ^
.../src/binutils-gdb/gdb/gdbserver/../nat/linux-namespaces.c: In function 'mnsh_recv_message':
.../src/binutils-gdb/gdb/gdbserver/../nat/linux-namespaces.c:429:50: error: format '%ld' expects argument of type 'long int', but argument 2 has type 'ssize_t {aka int}' [-Werror=format=]
  debug_printf ("namespace-helper: recv failed (%ld)\n", size);
                                                  ^
.../src/binutils-gdb/gdb/gdbserver/../nat/linux-namespaces.c:440:53: error: format '%ld' expects argument of type 'long int', but argument 2 has type 'ssize_t {aka int}' [-Werror=format=]
  debug_printf ("namespace-helper: recv truncated (%ld 0x%x)\n",
                                                   ^
---

I would expect that to mean this is broken for any
"long int != ssize_t" target. I'm not sure which C standards GDB requires
compatability with, but I believe the portable C99 way of printing a
ssize_t would be "%zd".

Thanks,
James

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-06-11  8:40     ` James Greenhalgh
@ 2015-06-11 11:04       ` Pedro Alves
  2015-06-11 12:42         ` [OB PATCH] Use pulongest for printing ssize_t Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Pedro Alves @ 2015-06-11 11:04 UTC (permalink / raw)
  To: James Greenhalgh
  Cc: Gary Benson, gdb-patches, Eli Zaretskii, Doug Evans,
	Iago López Galeiras

On 06/11/2015 09:40 AM, James Greenhalgh wrote:

> I would expect that to mean this is broken for any
> "long int != ssize_t" target. I'm not sure which C standards GDB requires
> compatability with, but I believe the portable C99 way of printing a
> ssize_t would be "%zd".

GDB is written in C90 currently.

The usual way to handle this is to use plongest (with %s).  As this
is native GNU/Linux code, casting to long (thus keep %ld) would
be fine too.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [OB PATCH] Use pulongest for printing ssize_t
  2015-06-11 11:04       ` Pedro Alves
@ 2015-06-11 12:42         ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-06-11 12:42 UTC (permalink / raw)
  To: gdb-patches
  Cc: James Greenhalgh, Pedro Alves, Eli Zaretskii, Doug Evans,
	Iago López Galeiras

Pedro Alves wrote:
> On 06/11/2015 09:40 AM, James Greenhalgh wrote:
> > I would expect that to mean this is broken for any "long int !=
> > ssize_t" target. I'm not sure which C standards GDB requires
> > compatability with, but I believe the portable C99 way of printing
> > a ssize_t would be "%zd".
> 
> GDB is written in C90 currently.
> 
> The usual way to handle this is to use plongest (with %s).  As this
> is native GNU/Linux code, casting to long (thus keep %ld) would be
> fine too.

This commit changes the debug printing code in linux-namespaces.c
to use pulongest instead of "%ld".

Pushed as obvious.

Thanks,
Gary

--
gdb/ChangeLog:

	* nat/linux-namespaces.c (mnsh_send_message): Use pulongest.
	(mnsh_recv_message): Likewise.
---
 gdb/ChangeLog              |    5 +++++
 gdb/nat/linux-namespaces.c |    9 +++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index 98ae104..f18e40d 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -374,7 +374,7 @@ mnsh_send_message (int sock, enum mnsh_msg_type type,
     {
       debug_printf ("mnsh: send: ");
       mnsh_debug_print_message (type, fd, int1, int2, buf, bufsiz);
-      debug_printf (" -> %ld\n", size);
+      debug_printf (" -> %s\n", pulongest (size));
     }
 
   return size;
@@ -426,7 +426,8 @@ mnsh_recv_message (int sock, enum mnsh_msg_type *type,
   if (size < 0)
     {
       if (debug_linux_namespaces)
-	debug_printf ("namespace-helper: recv failed (%ld)\n", size);
+	debug_printf ("namespace-helper: recv failed (%s)\n",
+		      pulongest (size));
 
       mnsh_maybe_mourn_peer ();
 
@@ -437,8 +438,8 @@ mnsh_recv_message (int sock, enum mnsh_msg_type *type,
   if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
     {
       if (debug_linux_namespaces)
-	debug_printf ("namespace-helper: recv truncated (%ld 0x%x)\n",
-		      size, msg.msg_flags);
+	debug_printf ("namespace-helper: recv truncated (%s 0x%x)\n",
+		      pulongest (size), msg.msg_flags);
 
       mnsh_maybe_mourn_peer ();
 
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-04-30 12:45 ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Gary Benson
       [not found]   ` <20150501000739.740.47967@domU-12-31-39-0A-A0-4F>
  2015-05-21 14:56   ` Pedro Alves
@ 2015-06-15 15:02   ` Michael Eager
  2015-06-15 22:12     ` Michael Eager
  2016-01-08 10:49   ` Yao Qi
  3 siblings, 1 reply; 84+ messages in thread
From: Michael Eager @ 2015-06-15 15:02 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

On 04/30/2015 05:05 AM, Gary Benson wrote:
> This commit introduces new shared files nat/linux-namespaces.[ch]
> containing code to support Linux namespaces that will be used by
> both GDB and gdbserver.
>
> gdb/ChangeLog:
>
> 	* configure.ac (AC_CHECK_FUNCS): Add setns.
> 	* config.in: Regenerate.
> 	* configure: Likewise.
> 	* nat/linux-namespaces.h: New file.
> 	* nat/linux-namespaces.c: Likewise.
> 	* Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-namespaces.h.
> 	(linux-namespaces.o): New rule.
> 	* config/aarch64/linux.mh (NATDEPFILES): Add linux-namespaces.o.
> 	* config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
> 	* config/arm/linux.mh (NATDEPFILES): Likewise.
> 	* config/i386/linux.mh (NATDEPFILES): Likewise.
> 	* config/i386/linux64.mh (NATDEPFILES): Likewise.
> 	* config/ia64/linux.mh (NATDEPFILES): Likewise.
> 	* config/m32r/linux.mh (NATDEPFILES): Likewise.
> 	* config/m68k/linux.mh (NATDEPFILES): Likewise.
> 	* config/mips/linux.mh (NATDEPFILES): Likewise.
> 	* config/pa/linux.mh (NATDEPFILES): Likewise.
> 	* config/powerpc/linux.mh (NATDEPFILES): Likewise.
> 	* config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
> 	* config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
> 	* config/s390/linux.mh (NATDEPFILES): Likewise.
> 	* config/sparc/linux.mh (NATDEPFILES): Likewise.
> 	* config/sparc/linux64.mh (NATDEPFILES): Likewise.
> 	* config/tilegx/linux.mh (NATDEPFILES): Likewise.
> 	* config/xtensa/linux.mh (NATDEPFILES): Likewise.

This patch causes a build failure in nat/linux-namespaces.c with
glibc-2.5, which does not define MSG_CMSG_CLOEXEC.  It looks like
this symbol was introduced in glib-2.7.

-- 
Michael Eager	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-06-15 15:02   ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Michael Eager
@ 2015-06-15 22:12     ` Michael Eager
  2015-06-16  8:40       ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Michael Eager @ 2015-06-15 22:12 UTC (permalink / raw)
  To: Gary Benson, gdb-patches
  Cc: Pedro Alves, Doug Evans, Iago López Galeiras

[-- Attachment #1: Type: text/plain, Size: 2052 bytes --]

On 06/15/2015 08:02 AM, Michael Eager wrote:
> On 04/30/2015 05:05 AM, Gary Benson wrote:
>> This commit introduces new shared files nat/linux-namespaces.[ch]
>> containing code to support Linux namespaces that will be used by
>> both GDB and gdbserver.
>>
>> gdb/ChangeLog:
>>
>>     * configure.ac (AC_CHECK_FUNCS): Add setns.
>>     * config.in: Regenerate.
>>     * configure: Likewise.
>>     * nat/linux-namespaces.h: New file.
>>     * nat/linux-namespaces.c: Likewise.
>>     * Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-namespaces.h.
>>     (linux-namespaces.o): New rule.
>>     * config/aarch64/linux.mh (NATDEPFILES): Add linux-namespaces.o.
>>     * config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
>>     * config/arm/linux.mh (NATDEPFILES): Likewise.
>>     * config/i386/linux.mh (NATDEPFILES): Likewise.
>>     * config/i386/linux64.mh (NATDEPFILES): Likewise.
>>     * config/ia64/linux.mh (NATDEPFILES): Likewise.
>>     * config/m32r/linux.mh (NATDEPFILES): Likewise.
>>     * config/m68k/linux.mh (NATDEPFILES): Likewise.
>>     * config/mips/linux.mh (NATDEPFILES): Likewise.
>>     * config/pa/linux.mh (NATDEPFILES): Likewise.
>>     * config/powerpc/linux.mh (NATDEPFILES): Likewise.
>>     * config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
>>     * config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
>>     * config/s390/linux.mh (NATDEPFILES): Likewise.
>>     * config/sparc/linux.mh (NATDEPFILES): Likewise.
>>     * config/sparc/linux64.mh (NATDEPFILES): Likewise.
>>     * config/tilegx/linux.mh (NATDEPFILES): Likewise.
>>     * config/xtensa/linux.mh (NATDEPFILES): Likewise.
>
> This patch causes a build failure in nat/linux-namespaces.c with
> glibc-2.5, which does not define MSG_CMSG_CLOEXEC.  It looks like
> this symbol was introduced in glib-2.7.

Here is a patch which allows this to compile if the symbol is not defined.

Changelog:

	* nat/linux-namespaces.c (MSG_CMSG_CLOEXEC): Define if not defined.

-- 
Michael Eager	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

[-- Attachment #2: 0001-GDB-Define-MSG_CMSG_CLOEXEC-if-undefined.patch --]
[-- Type: text/x-patch, Size: 681 bytes --]

From 7ccb1f19f15c6ef052d06f1da9e92fda9c2c1fe7 Mon Sep 17 00:00:00 2001
From: Michael Eager <meager@cisco.com>
Date: Mon, 15 Jun 2015 11:26:12 -0700
Subject: [PATCH] GDB -- Define MSG_CMSG_CLOEXEC if undefined

* nat/linux-namespaces.c (MSG_CMSG_CLOEXEC): Define.
---
 gdb/nat/linux-namespaces.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index f18e40d..3fc4326 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -47,6 +47,10 @@ setns (int fd, int nstype)
 }
 #endif

+#ifndef MSG_CMSG_CLOEXEC
+#define MSG_CMSG_CLOEXEC 0
+#endif
+
 /* A Linux namespace.  */

 struct linux_ns
-- 
2.2.1


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-06-15 22:12     ` Michael Eager
@ 2015-06-16  8:40       ` Gary Benson
  2015-06-16 14:19         ` Michael Eager
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2015-06-16  8:40 UTC (permalink / raw)
  To: Michael Eager
  Cc: gdb-patches, Pedro Alves, Doug Evans, Iago López Galeiras

Michael Eager wrote:
> On 06/15/2015 08:02 AM, Michael Eager wrote:
> >On 04/30/2015 05:05 AM, Gary Benson wrote:
> > > This commit introduces new shared files linux-namespaces.[ch]
> > > containing code to support Linux namespaces that will be used
> > > by both GDB and gdbserver.
> >
> > This patch causes a build failure in nat/linux-namespaces.c with
> > glibc-2.5, which does not define MSG_CMSG_CLOEXEC.  It looks like
> > this symbol was introduced in glib-2.7.
> 
> Here is a patch which allows this to compile if the symbol is not
> defined.
[snip]

Looks good, though maybe with a comment (below).
Please commit this.

Cheers,
Gary

--
diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index f18e40d..a7a3e4d 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -47,6 +47,12 @@ setns (int fd, int nstype)
 }
 #endif
 
+/* Handle systems without MSG_CMSG_CLOEXEC.  */
+
+#ifndef MSG_CMSG_CLOEXEC
+#define MSG_CMSG_CLOEXEC 0
+#endif
+
 /* A Linux namespace.  */
 
 struct linux_ns

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-06-16  8:40       ` Gary Benson
@ 2015-06-16 14:19         ` Michael Eager
  2015-06-17  9:51           ` Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Michael Eager @ 2015-06-16 14:19 UTC (permalink / raw)
  To: Gary Benson
  Cc: gdb-patches, Pedro Alves, Doug Evans, Iago López Galeiras

On 06/16/2015 01:40 AM, Gary Benson wrote:
> Michael Eager wrote:
>> On 06/15/2015 08:02 AM, Michael Eager wrote:
>>> On 04/30/2015 05:05 AM, Gary Benson wrote:
>>>> This commit introduces new shared files linux-namespaces.[ch]
>>>> containing code to support Linux namespaces that will be used
>>>> by both GDB and gdbserver.
>>>
>>> This patch causes a build failure in nat/linux-namespaces.c with
>>> glibc-2.5, which does not define MSG_CMSG_CLOEXEC.  It looks like
>>> this symbol was introduced in glib-2.7.
>>
>> Here is a patch which allows this to compile if the symbol is not
>> defined.
> [snip]
>
> Looks good, though maybe with a comment (below).
> Please commit this.
>
> Cheers,
> Gary
>
> --
> diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
> index f18e40d..a7a3e4d 100644
> --- a/gdb/nat/linux-namespaces.c
> +++ b/gdb/nat/linux-namespaces.c
> @@ -47,6 +47,12 @@ setns (int fd, int nstype)
>   }
>   #endif
>
> +/* Handle systems without MSG_CMSG_CLOEXEC.  */
> +
> +#ifndef MSG_CMSG_CLOEXEC
> +#define MSG_CMSG_CLOEXEC 0
> +#endif
> +
>   /* A Linux namespace.  */
>
>   struct linux_ns

Committed: 4da680addb9.

-- 
Michael Eager	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-06-16 14:19         ` Michael Eager
@ 2015-06-17  9:51           ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2015-06-17  9:51 UTC (permalink / raw)
  To: Michael Eager
  Cc: gdb-patches, Pedro Alves, Doug Evans, Iago López Galeiras

Michael Eager wrote:
> On 06/16/2015 01:40 AM, Gary Benson wrote:
> > Michael Eager wrote:
> > > On 06/15/2015 08:02 AM, Michael Eager wrote:
> > > > On 04/30/2015 05:05 AM, Gary Benson wrote:
> > > > > This commit introduces new shared files linux-namespaces.[ch]
> > > > > containing code to support Linux namespaces that will be used
> > > > > by both GDB and gdbserver.
> > > >
> > > > Tis patch causes a build failure in nat/linux-namespaces.c with
> > > > glibc-2.5, which does not define MSG_CMSG_CLOEXEC.  It looks like
> > > > this symbol was introduced in glib-2.7.
> > >
> > > Here is a patch which allows this to compile if the symbol is not
> > > defined.
> > [snip]
> >
> > Looks good, though maybe with a comment (below).
> > Please commit this.
> > 
> > --
> > diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
> > index f18e40d..a7a3e4d 100644
> > --- a/gdb/nat/linux-namespaces.c
> > +++ b/gdb/nat/linux-namespaces.c
> > @@ -47,6 +47,12 @@ setns (int fd, int nstype)
> >   }
> >   #endif
> > 
> > +/* Handle systems without MSG_CMSG_CLOEXEC.  */
> > +
> > +#ifndef MSG_CMSG_CLOEXEC
> > +#define MSG_CMSG_CLOEXEC 0
> > +#endif
> > +
> >   /* A Linux namespace.  */
> > 
> >   struct linux_ns
> 
> Committed: 4da680addb9.

Thanks Michael.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2015-04-30 12:45 ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Gary Benson
                     ` (2 preceding siblings ...)
  2015-06-15 15:02   ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Michael Eager
@ 2016-01-08 10:49   ` Yao Qi
  2016-01-11 16:40     ` Gary Benson
  3 siblings, 1 reply; 84+ messages in thread
From: Yao Qi @ 2016-01-08 10:49 UTC (permalink / raw)
  To: Gary Benson
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

Gary Benson <gbenson@redhat.com> writes:

Hi Gary,

> +/* Return an object representing the mount namespace helper process.
> +   If no mount namespace helper process has been started then start
> +   one.  Return NULL if no mount namespace helper process could be
> +   started.  */
> +
> +static struct linux_mnsh *
> +linux_mntns_get_helper (void)
> +{
> +  static struct linux_mnsh *helper = NULL;
> +
> +  if (helper == NULL)
> +    {
> +      static struct linux_mnsh h;
> +      struct linux_ns *ns;
> +      pid_t helper_creator = getpid ();
> +      int sv[2];
> +
> +      ns = linux_ns_get_namespace (LINUX_NS_MNT);
> +      if (ns == NULL)
> +	return NULL;
> +
> +      if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
> +	return NULL;
> +
> +      h.pid = fork ();
> +      if (h.pid < 0)

Function fork isn't available on uclinux target, so it causes a
compilation error like this below.  Since my work touches
linux-bfin-low.c, I build GDBserver for bfin-uclinux, and the error is found.

cc1: warnings being treated as errors
gdb/gdbserver/../nat/linux-namespaces.c: In function ‘linux_mntns_get_helper’:
gdb/gdbserver/../nat/linux-namespaces.c:647: error: implicit declaration of function ‘fork’

I don't know much about linux namespace stuff, so I didn't give a fix
here.  Could you have a look?

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch]
  2016-01-08 10:49   ` Yao Qi
@ 2016-01-11 16:40     ` Gary Benson
  2016-01-18 11:44       ` [OB PATCH] Fix gdbserver build failure on targets without fork Gary Benson
  0 siblings, 1 reply; 84+ messages in thread
From: Gary Benson @ 2016-01-11 16:40 UTC (permalink / raw)
  To: Yao Qi
  Cc: gdb-patches, Eli Zaretskii, Pedro Alves, Doug Evans,
	Iago López Galeiras

Hi Yao,

Yao Qi wrote:
> Gary Benson <gbenson@redhat.com> writes:
> > +/* Return an object representing the mount namespace helper process.
> > +   If no mount namespace helper process has been started then start
> > +   one.  Return NULL if no mount namespace helper process could be
> > +   started.  */
> > +
> > +static struct linux_mnsh *
> > +linux_mntns_get_helper (void)
> > +{
> > +  static struct linux_mnsh *helper = NULL;
> > +
> > +  if (helper == NULL)
> > +    {
> > +      static struct linux_mnsh h;
> > +      struct linux_ns *ns;
> > +      pid_t helper_creator = getpid ();
> > +      int sv[2];
> > +
> > +      ns = linux_ns_get_namespace (LINUX_NS_MNT);
> > +      if (ns == NULL)
> > +	return NULL;
> > +
> > +      if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
> > +	return NULL;
> > +
> > +      h.pid = fork ();
> > +      if (h.pid < 0)
> 
> Function fork isn't available on uclinux target, so it causes a
> compilation error like this below.  Since my work touches
> linux-bfin-low.c, I build GDBserver for bfin-uclinux, and the error
> is found.
[snip]
> I don't know much about linux namespace stuff, so I didn't give a
> fix here.  Could you have a look?

It probably needs a configure check, I'll add one.

Cheers,
Gary

-- 
http://gbenson.net/

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [OB PATCH] Fix gdbserver build failure on targets without fork
  2016-01-11 16:40     ` Gary Benson
@ 2016-01-18 11:44       ` Gary Benson
  0 siblings, 0 replies; 84+ messages in thread
From: Gary Benson @ 2016-01-18 11:44 UTC (permalink / raw)
  To: gdb-patches
  Cc: Yao Qi, Eli Zaretskii, Pedro Alves, Doug Evans, Iago López Galeiras

Gary Benson wrote:
> Yao Qi wrote:
> > Function fork isn't available on uclinux target, so it causes
> > a compilation error like this below.  Since my work touches
> > linux-bfin-low.c, I build GDBserver for bfin-uclinux, and the
> > error is found.
> [snip]
> > I don't know much about linux namespace stuff, so I didn't give
> > a fix here.  Could you have a look?
>
> It probably needs a configure check, I'll add one.

Added.

---
This commit fixes nat/linux-namespaces.c to build correctly on
targets without fork.

gdb/ChangeLog:

	* nat/linux-namespaces.c (do_fork): New function.
	(linux_mntns_get_helper): Use the above.

gdb/gdbserver/ChangeLog:

	* configure.ac (AC_FUNC_FORK): New check.
	* config.in: Regenerate.
	* configure: Likewise.
---
 gdb/ChangeLog              |    5 +
 gdb/gdbserver/ChangeLog    |    6 +
 gdb/gdbserver/config.in    |   21 +++
 gdb/gdbserver/configure    |  333 +++++++++++++++++++++++++++++++++++++-------
 gdb/gdbserver/configure.ac |    1 +
 gdb/nat/linux-namespaces.c |   15 ++-
 6 files changed, 326 insertions(+), 55 deletions(-)

diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index e2566a9..2c3a69a 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -99,6 +99,9 @@
 /* Define to 1 if you have the `fdwalk' function. */
 #undef HAVE_FDWALK
 
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
 /* Define to 1 if you have the `getauxval' function. */
 #undef HAVE_GETAUXVAL
 
@@ -286,9 +289,21 @@
 /* Define if UST is available */
 #undef HAVE_UST
 
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
 /* Define to 1 if you have the <wait.h> header file. */
 #undef HAVE_WAIT_H
 
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
 /* Define to the address where bug reports for this package should be sent. */
 #undef PACKAGE_BUGREPORT
 
@@ -393,3 +408,9 @@
 
 /* Define to 1 if you need to in order for `stat' and other things to work. */
 #undef _POSIX_SOURCE
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 57af951..763c77d 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -1772,6 +1772,60 @@ fi
 
 } # ac_fn_c_try_link
 
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_type
+
 # ac_fn_c_check_func LINENO FUNC VAR
 # ----------------------------------
 # Tests whether FUNC exists, setting the cache variable VAR accordingly
@@ -1929,60 +1983,6 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_cxx_check_decl
 
-# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
-# -------------------------------------------
-# Tests whether TYPE exists after having included INCLUDES, setting cache
-# variable VAR accordingly.
-ac_fn_c_check_type ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
-  $as_echo_n "(cached) " >&6
-else
-  eval "$3=no"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof ($2))
-	 return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof (($2)))
-	    return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
-  eval "$3=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
-
-} # ac_fn_c_check_type
-
 # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
 # --------------------------------------------
 # Tries to find the compile-time value of EXPR in a program that includes
@@ -5360,6 +5360,231 @@ fi
 
 done
 
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = x""yes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+for ac_header in vfork.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in fork vfork
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if test "${ac_cv_func_fork_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_fork_works=cross
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	  /* By Ruediger Kuhlmann. */
+	  return fork () < 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_fork_works=yes
+else
+  ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+  ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+  case $host in
+    *-*-amigaos* | *-*-msdosdjgpp*)
+      # Override, as these systems have only a dummy fork() stub
+      ac_cv_func_fork_works=no
+      ;;
+    *)
+      ac_cv_func_fork_works=yes
+      ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if test "${ac_cv_func_vfork_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_vfork_works=cross
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Thanks to Paul Eggert for this test.  */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+   argument registers are propagated back to the parent.  The compiler
+   is told about this with #include <vfork.h>, but some compilers
+   (e.g. gcc -O) don't grok <vfork.h>.  Test for this by using a
+   static variable whose address is put into a register that is
+   clobbered by the vfork.  */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+  static pid_t child;
+  if (!child) {
+    child = vfork ();
+    if (child < 0) {
+      perror ("vfork");
+      _exit(2);
+    }
+    if (!child) {
+      arg = getpid();
+      write(-1, "", 0);
+      _exit (arg);
+    }
+  }
+}
+
+int
+main ()
+{
+  pid_t parent = getpid ();
+  pid_t child;
+
+  sparc_address_test (0);
+
+  child = vfork ();
+
+  if (child == 0) {
+    /* Here is another test for sparc vfork register problems.  This
+       test uses lots of local variables, at least as many local
+       variables as main has allocated so far including compiler
+       temporaries.  4 locals are enough for gcc 1.40.3 on a Solaris
+       4.1.3 sparc, but we use 8 to be safe.  A buggy compiler should
+       reuse the register of parent for one of the local variables,
+       since it will think that parent can't possibly be used any more
+       in this routine.  Assigning to the local variable will thus
+       munge parent in the parent process.  */
+    pid_t
+      p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+      p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+    /* Convince the compiler that p..p7 are live; otherwise, it might
+       use the same hardware register for all 8 local variables.  */
+    if (p != p1 || p != p2 || p != p3 || p != p4
+	|| p != p5 || p != p6 || p != p7)
+      _exit(1);
+
+    /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+       from child file descriptors.  If the child closes a descriptor
+       before it execs or exits, this munges the parent's descriptor
+       as well.  Test for this by closing stdout in the child.  */
+    _exit(close(fileno(stdout)) != 0);
+  } else {
+    int status;
+    struct stat st;
+
+    while (wait(&status) != child)
+      ;
+    return (
+	 /* Was there some problem with vforking?  */
+	 child < 0
+
+	 /* Did the child fail?  (This shouldn't happen.)  */
+	 || status
+
+	 /* Did the vfork/compiler bug occur?  */
+	 || parent != getpid()
+
+	 /* Did the file descriptor bug occur?  */
+	 || fstat(fileno(stdout), &st) != 0
+	 );
+  }
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_vfork_works=yes
+else
+  ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+  ac_cv_func_vfork_works=$ac_cv_func_vfork
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
 for ac_func in getauxval pread pwrite pread64 setns
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index 8476fbd..f15ee1f 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -94,6 +94,7 @@ AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl
 		 fcntl.h signal.h sys/file.h dnl
 		 sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
 		 netinet/tcp.h arpa/inet.h)
+AC_FUNC_FORK
 AC_CHECK_FUNCS(getauxval pread pwrite pread64 setns)
 
 GDB_AC_COMMON
diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index fb1467c..e9626ab 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -32,6 +32,19 @@
 /* See nat/linux-namespaces.h.  */
 int debug_linux_namespaces;
 
+/* Handle systems without fork.  */
+
+static inline pid_t
+do_fork (void)
+{
+#ifdef HAVE_FORK
+  return fork ();
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}
+
 /* Handle systems without setns.  */
 
 static inline int
@@ -644,7 +657,7 @@ linux_mntns_get_helper (void)
       if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
 	return NULL;
 
-      h.pid = fork ();
+      h.pid = do_fork ();
       if (h.pid < 0)
 	{
 	  int saved_errno = errno;
-- 
1.7.1

^ permalink raw reply	[flat|nested] 84+ messages in thread

end of thread, other threads:[~2016-01-18 11:44 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-16 12:19 [PATCH 0/7] GNU/Linux mount namespace support Gary Benson
2015-04-16 12:19 ` [PATCH 4/7] Remove linux_proc_pid_get_ns Gary Benson
2015-04-17  4:36   ` Doug Evans
2015-04-17 13:44     ` Gary Benson
2015-04-16 12:20 ` [PATCH 1/7] Move make_cleanup_close to common code Gary Benson
2015-04-17  2:47   ` Doug Evans
2015-04-16 12:20 ` [PATCH 2/7] Introduce target_fileio_set_fs Gary Benson
2015-04-17  3:04   ` Doug Evans
2015-04-17 13:36     ` Gary Benson
2015-04-17 14:21       ` Pedro Alves
2015-04-17 17:28         ` Doug Evans
2015-04-17 17:46           ` Pedro Alves
2015-04-20 11:11             ` Gary Benson
2015-04-16 12:27 ` [PATCH 6/7] Implement multiple-filesystem support for remote targets Gary Benson
2015-04-16 15:12   ` Eli Zaretskii
2015-04-17 15:06   ` Pedro Alves
2015-04-17 16:00     ` Gary Benson
2015-04-17 16:07       ` Pedro Alves
2015-04-17 16:20         ` Gary Benson
2015-04-17 15:31   ` Pedro Alves
2015-04-17 16:01     ` Gary Benson
2015-04-16 12:34 ` [PATCH 3/7] Introduce nat/linux-namespaces.[ch] Gary Benson
2015-04-17  4:26   ` Doug Evans
2015-04-17 13:41     ` Gary Benson
2015-04-17 14:52   ` Pedro Alves
2015-04-17 17:32     ` Doug Evans
2015-04-20 11:12       ` Gary Benson
2015-04-16 12:54 ` [PATCH 7/7] Implement vFile:setfs in gdbserver Gary Benson
2015-04-17 15:30   ` Pedro Alves
2015-04-17 16:47     ` Gary Benson
2015-04-17 16:29       ` Gary Benson
2015-04-17 17:09         ` Pedro Alves
2015-04-16 13:06 ` [PATCH 5/7] Implement multiple-filesystem support for Linux targets Gary Benson
2015-04-17 15:35 ` [PATCH 0/7] GNU/Linux mount namespace support Pedro Alves
2015-04-20 16:49 ` Iago López Galeiras
2015-04-21  7:56   ` Gary Benson
2015-04-30 12:06 ` [PATCH 6/9 v2] Implement mount namespace support for native Linux targets Gary Benson
2015-04-30 16:24   ` Eli Zaretskii
2015-04-30 18:05     ` Gary Benson
2015-05-21 14:59   ` Pedro Alves
2015-05-27 10:16     ` Gary Benson
2015-04-30 12:06 ` [PATCH 0/9 v2] GNU/Linux mount namespace support Gary Benson
2015-06-10 14:23   ` [pushed][PATCH " Gary Benson
2015-04-30 12:06 ` [PATCH 3/9 v2] Remove linux_proc_pid_get_ns Gary Benson
2015-05-21 14:56   ` Pedro Alves
2015-04-30 12:06 ` [PATCH 5/9 v2] Add "inferior" argument to some target_fileio functions Gary Benson
2015-05-21 14:57   ` Pedro Alves
2015-04-30 12:15 ` [PATCH 4/9 v2] Comment and whitespace changes Gary Benson
2015-05-21 14:57   ` Pedro Alves
2015-04-30 12:41 ` [PATCH 8/9 v2] Implement vFile:setfs in gdbserver Gary Benson
2015-05-21 15:00   ` Pedro Alves
2015-06-09 14:11     ` Gary Benson
2015-06-09 14:23       ` Pedro Alves
2015-06-10  9:01         ` Gary Benson
2015-06-10  9:41           ` Gary Benson
2015-06-10 14:53             ` Pedro Alves
2015-04-30 12:45 ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Gary Benson
     [not found]   ` <20150501000739.740.47967@domU-12-31-39-0A-A0-4F>
2015-05-01  9:28     ` Gary Benson
2015-05-01 13:18       ` Alban Crequy
2015-05-01 20:29         ` Gary Benson
2015-05-06 18:55           ` Alban Crequy
2015-05-07  8:42             ` Gary Benson
2015-05-07 10:39           ` Gary Benson
2015-05-21 14:56   ` Pedro Alves
2015-05-27 10:14     ` Gary Benson
2015-06-11  8:40     ` James Greenhalgh
2015-06-11 11:04       ` Pedro Alves
2015-06-11 12:42         ` [OB PATCH] Use pulongest for printing ssize_t Gary Benson
2015-06-15 15:02   ` [PATCH 2/9 v2] Introduce nat/linux-namespaces.[ch] Michael Eager
2015-06-15 22:12     ` Michael Eager
2015-06-16  8:40       ` Gary Benson
2015-06-16 14:19         ` Michael Eager
2015-06-17  9:51           ` Gary Benson
2016-01-08 10:49   ` Yao Qi
2016-01-11 16:40     ` Gary Benson
2016-01-18 11:44       ` [OB PATCH] Fix gdbserver build failure on targets without fork Gary Benson
2015-04-30 14:12 ` [PATCH 7/9 v2] Implement multiple-filesystem support for remote targets Gary Benson
2015-04-30 17:10   ` Eli Zaretskii
2015-05-21 15:04   ` Pedro Alves
2015-04-30 14:12 ` [PATCH 1/9 v2] Move make_cleanup_close to common code Gary Benson
2015-05-21 14:56   ` Pedro Alves
2015-05-27  9:52     ` Gary Benson
2015-04-30 14:14 ` [PATCH 9/9 v2] Announce new container-awareness features for GNU/Linux systems Gary Benson
2015-04-30 16:20   ` Eli Zaretskii

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).