[4/7] Introduce linux_pid_to_exec_file

Message ID 1427887341-31819-5-git-send-email-gbenson@redhat.com
State Committed
Headers

Commit Message

Gary Benson April 1, 2015, 11:22 a.m. UTC
  This commit introduces a new function, linux_pid_to_exec_file, that
shared Linux code can use to discover the filename of the executable
that was run to create a process on the system.

gdb/ChangeLog:

	* nat/linux-nat.h (linux_pid_to_exec_file): New declaration.
	* nat/linux-nat.c: New file.
	* Makefile.in (common-linux-nat.o): New rule.
	* config/aarch64/linux.mh (NATDEPFILES): Add common-linux-nat.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.
	* linux-nat.c (linux_child_pid_to_exec_file): Factored out
	to new function linux_pid_to_exec_file in nat/linux-nat.c.

gdb/gdbserver/ChangeLog:

	* Makefile.in (common-linux-nat.o): New rule.
	* configure.srv (srv_linux_obj): Add common-linux-nat.o.
---
 gdb/ChangeLog                     |   26 ++++++++++++++++++++++++++
 gdb/Makefile.in                   |    4 ++++
 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          |    2 +-
 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 |    2 +-
 gdb/config/powerpc/spu-linux.mh   |    3 ++-
 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/gdbserver/ChangeLog           |    5 +++++
 gdb/gdbserver/Makefile.in         |    3 +++
 gdb/gdbserver/configure.srv       |    2 +-
 gdb/linux-nat.c                   |   10 +---------
 gdb/nat/linux-nat.c               |   37 +++++++++++++++++++++++++++++++++++++
 gdb/nat/linux-nat.h               |    9 +++++++++
 26 files changed, 105 insertions(+), 28 deletions(-)
 create mode 100644 gdb/nat/linux-nat.c
  

Comments

Doug Evans April 6, 2015, 4:40 p.m. UTC | #1
Gary Benson <gbenson@redhat.com> writes:
> This commit introduces a new function, linux_pid_to_exec_file, that
> shared Linux code can use to discover the filename of the executable
> that was run to create a process on the system.
>
> gdb/ChangeLog:
>
> 	* nat/linux-nat.h (linux_pid_to_exec_file): New declaration.
> 	* nat/linux-nat.c: New file.
> 	* Makefile.in (common-linux-nat.o): New rule.
> 	* config/aarch64/linux.mh (NATDEPFILES): Add common-linux-nat.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.
> 	* linux-nat.c (linux_child_pid_to_exec_file): Factored out
> 	to new function linux_pid_to_exec_file in nat/linux-nat.c.
>
> ...
>
> diff --git a/gdb/nat/linux-nat.c b/gdb/nat/linux-nat.c
> new file mode 100644
> index 0000000..b9deae3
> --- /dev/null
> +++ b/gdb/nat/linux-nat.c
> @@ -0,0 +1,37 @@
> +/* Native-dependent code for GNU/Linux
> +
> +   Copyright (C) 2000-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-nat.h"
> +
> +/* See nat/linux-nat.h.  */
> +
> +char *
> +linux_pid_to_exec_file (int pid)
> +{
> +  static char buf[PATH_MAX];
> +  char name[PATH_MAX];
> +
> +  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
> +  memset (buf, 0, PATH_MAX);
> +  if (readlink (name, buf, PATH_MAX - 1) <= 0)
> +    strcpy (buf, name);
> +
> +  return buf;
> +}
> diff --git a/gdb/nat/linux-nat.h b/gdb/nat/linux-nat.h
> index 7cdaf40..81c2edc 100644
> --- a/gdb/nat/linux-nat.h
> +++ b/gdb/nat/linux-nat.h
> @@ -78,4 +78,13 @@ extern enum target_stop_reason lwp_stop_reason (struct lwp_info *lwp);
>  
>  extern void linux_stop_lwp (struct lwp_info *lwp);
>  
> +/* Return the pathname of the executable file that was run to create
> +   the process PID.  If the executable file cannot be determined, NULL
> +   is returned.  Otherwise, a pointer to a character string containing
> +   the pathname is returned.  This string should be copied into a
> +   buffer by the client if the string will not be immediately used, or
> +   if it must persist.  */
> +
> +extern char *linux_pid_to_exec_file (int pid);
> +
>  #endif /* LINUX_NAT_H */

Hi.

I like the idea of returning NULL if the executable file cannot be
determined, but the implementation doesn't do this.

Also, while I don't have a strong opinion, it seems preferable
to return a const char *.
  
Gary Benson April 7, 2015, 9:07 a.m. UTC | #2
Doug Evans wrote:
> Gary Benson <gbenson@redhat.com> writes:
> > diff --git a/gdb/nat/linux-nat.c b/gdb/nat/linux-nat.c
> > new file mode 100644
> > index 0000000..b9deae3
> > --- /dev/null
> > +++ b/gdb/nat/linux-nat.c
> > @@ -0,0 +1,37 @@
...
> > +/* See nat/linux-nat.h.  */
> > +
> > +char *
> > +linux_pid_to_exec_file (int pid)
> > +{
> > +  static char buf[PATH_MAX];
> > +  char name[PATH_MAX];
> > +
> > +  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
> > +  memset (buf, 0, PATH_MAX);
> > +  if (readlink (name, buf, PATH_MAX - 1) <= 0)
> > +    strcpy (buf, name);
> > +
> > +  return buf;
> > +}
> > diff --git a/gdb/nat/linux-nat.h b/gdb/nat/linux-nat.h
> > index 7cdaf40..81c2edc 100644
> > --- a/gdb/nat/linux-nat.h
> > +++ b/gdb/nat/linux-nat.h
> > @@ -78,4 +78,13 @@
> >  
> >  extern void linux_stop_lwp (struct lwp_info *lwp);
> >  
> > +/* Return the pathname of the executable file that was run to create
> > +   the process PID.  If the executable file cannot be determined, NULL
> > +   is returned.  Otherwise, a pointer to a character string containing
> > +   the pathname is returned.  This string should be copied into a
> > +   buffer by the client if the string will not be immediately used, or
> > +   if it must persist.  */
> > +
> > +extern char *linux_pid_to_exec_file (int pid);
> > +
> >  #endif /* LINUX_NAT_H */
> 
> I like the idea of returning NULL if the executable file cannot be
> determined, but the implementation doesn't do this.

You're right, I will remove that part of the documentation comment.

> Also, while I don't have a strong opinion, it seems preferable
> to return a const char *.

The function is the implementation of target_pid_to_exec_file, via
a wrapper, and that does not return const.  I briefly attempted to
constify this but it snowballed.

Thanks,
Gary
  
Doug Evans April 8, 2015, 3:15 a.m. UTC | #3
On Tue, Apr 7, 2015 at 2:07 AM, Gary Benson <gbenson@redhat.com> wrote:
> Doug Evans wrote:
>> Gary Benson <gbenson@redhat.com> writes:
>> > diff --git a/gdb/nat/linux-nat.c b/gdb/nat/linux-nat.c
>> > new file mode 100644
>> > index 0000000..b9deae3
>> > --- /dev/null
>> > +++ b/gdb/nat/linux-nat.c
>> > @@ -0,0 +1,37 @@
> ...
>> > +/* See nat/linux-nat.h.  */
>> > +
>> > +char *
>> > +linux_pid_to_exec_file (int pid)
>> > +{
>> > +  static char buf[PATH_MAX];
>> > +  char name[PATH_MAX];
>> > +
>> > +  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
>> > +  memset (buf, 0, PATH_MAX);
>> > +  if (readlink (name, buf, PATH_MAX - 1) <= 0)
>> > +    strcpy (buf, name);
>> > +
>> > +  return buf;
>> > +}

Hi. Another nit.

Since readlink does not nul-terminate the string, I think it would be
clearer to explicitly nul-terminate the result instead of doing
the initial memset. I realize the current linux-nat.c version
doesn't do this, but we can still improve things here.

[One might also want the code to protect itself in the case
where the buf is not large enough, but one can leave that
for now since we assume PATH_MAX is big enough
throughout.]
  
Gary Benson April 8, 2015, 8:06 a.m. UTC | #4
Doug Evans wrote:
> On Tue, Apr 7, 2015 at 2:07 AM, Gary Benson <gbenson@redhat.com> wrote:
> > Doug Evans wrote:
> > > Gary Benson <gbenson@redhat.com> writes:
> > > > +/* See nat/linux-nat.h.  */
> > > > +
> > > > +char *
> > > > +linux_pid_to_exec_file (int pid)
> > > > +{
> > > > +  static char buf[PATH_MAX];
> > > > +  char name[PATH_MAX];
> > > > +
> > > > +  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
> > > > +  memset (buf, 0, PATH_MAX);
> > > > +  if (readlink (name, buf, PATH_MAX - 1) <= 0)
> > > > +    strcpy (buf, name);
> > > > +
> > > > +  return buf;
> > > > +}
> 
> Hi. Another nit.
> 
> Since readlink does not nul-terminate the string, I think it would
> be clearer to explicitly nul-terminate the result instead of doing
> the initial memset. I realize the current linux-nat.c version
> doesn't do this, but we can still improve things here.

Ok, I'll do that.

> [One might also want the code to protect itself in the case where
> the buf is not large enough, but one can leave that for now since
> we assume PATH_MAX is big enough throughout.]

I don't know how you'd tell, readlink doesn't seem to indicate whether
it truncated or not.

Cheers,
Gary
  
Pedro Alves April 15, 2015, 9:37 a.m. UTC | #5
On 04/01/2015 12:22 PM, Gary Benson wrote:
> This commit introduces a new function, linux_pid_to_exec_file, that
> shared Linux code can use to discover the filename of the executable
> that was run to create a process on the system.
> 
> gdb/ChangeLog:
> 
> 	* nat/linux-nat.h (linux_pid_to_exec_file): New declaration.
> 	* nat/linux-nat.c: New file.
> 	* Makefile.in (common-linux-nat.o): New rule.
> 	* config/aarch64/linux.mh (NATDEPFILES): Add common-linux-nat.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.
> 	* linux-nat.c (linux_child_pid_to_exec_file): Factored out
> 	to new function linux_pid_to_exec_file in nat/linux-nat.c.

Sorry for pushing back a after you touched all these files, but,
there's already a natural place for this shared function.

> --- /dev/null
> +++ b/gdb/nat/linux-nat.c
> @@ -0,0 +1,37 @@
> +/* Native-dependent code for GNU/Linux
...
> +char *
> +linux_pid_to_exec_file (int pid)
> +{
> +  static char buf[PATH_MAX];
> +  char name[PATH_MAX];
> +
> +  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
> +  memset (buf, 0, PATH_MAX);
> +  if (readlink (name, buf, PATH_MAX - 1) <= 0)
> +    strcpy (buf, name);
> +
> +  return buf;
> +}

Instead please move this function to nat/linux-procfs.c,
(and call it linux_proc_pid_to_exec_file).

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 907997b..6920358 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -2310,6 +2310,10 @@  x86-linux-dregs.o: ${srcdir}/nat/x86-linux-dregs.c
 	$(COMPILE) $(srcdir)/nat/x86-linux-dregs.c
 	$(POSTCOMPILE)
 
+common-linux-nat.o: ${srcdir}/nat/linux-nat.c
+	$(COMPILE) $(srcdir)/nat/linux-nat.c
+	$(POSTCOMPILE)
+
 #
 # gdb/tui/ dependencies
 #
diff --git a/gdb/config/aarch64/linux.mh b/gdb/config/aarch64/linux.mh
index 7f96e4d..d22150a 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 common-linux-nat.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..81b1199 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 common-linux-nat.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..e92188a 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 common-linux-nat.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..a32d940 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 common-linux-nat.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..7666814 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 common-linux-nat.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..8d9dc12 100644
--- a/gdb/config/ia64/linux.mh
+++ b/gdb/config/ia64/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-personality.o \
-	linux-procfs.o linux-ptrace.o linux-waitpid.o
+	linux-procfs.o linux-ptrace.o linux-waitpid.o common-linux-nat.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..d83df66 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 common-linux-nat.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..1bc1d78 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 common-linux-nat.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..577e410 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 common-linux-nat.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..97230b8 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 common-linux-nat.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..f8f8a6e 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 common-linux-nat.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..f9194a0 100644
--- a/gdb/config/powerpc/ppc64-linux.mh
+++ b/gdb/config/powerpc/ppc64-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 ppc-linux.o linux-personality.o
+	linux-waitpid.o ppc-linux.o linux-personality.o common-linux-nat.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..345ac8d 100644
--- a/gdb/config/powerpc/spu-linux.mh
+++ b/gdb/config/powerpc/spu-linux.mh
@@ -4,5 +4,6 @@ 
 # 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 common-linux-nat.o
 
diff --git a/gdb/config/s390/linux.mh b/gdb/config/s390/linux.mh
index e1ad899..9938e73 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 common-linux-nat.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..30cc477 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 common-linux-nat.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..73fa282 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 common-linux-nat.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..cd5528d 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 common-linux-nat.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..9737442 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 common-linux-nat.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 9d698c6..e30636c 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -615,6 +615,9 @@  x86-linux.o: ../nat/x86-linux.c
 x86-linux-dregs.o: ../nat/x86-linux-dregs.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+common-linux-nat.o: ../nat/linux-nat.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/configure.srv b/gdb/gdbserver/configure.srv
index 81dd235..11c9bc0 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 common-linux-nat.o"
 
 # Input is taken from the "${target}" variable.
 
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 0376299..de4dc1a 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4086,15 +4086,7 @@  linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
 static char *
 linux_child_pid_to_exec_file (struct target_ops *self, int pid)
 {
-  static char buf[PATH_MAX];
-  char name[PATH_MAX];
-
-  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
-  memset (buf, 0, PATH_MAX);
-  if (readlink (name, buf, PATH_MAX - 1) <= 0)
-    strcpy (buf, name);
-
-  return buf;
+  return linux_pid_to_exec_file (pid);
 }
 
 /* Implement the to_xfer_partial interface for memory reads using the /proc
diff --git a/gdb/nat/linux-nat.c b/gdb/nat/linux-nat.c
new file mode 100644
index 0000000..b9deae3
--- /dev/null
+++ b/gdb/nat/linux-nat.c
@@ -0,0 +1,37 @@ 
+/* Native-dependent code for GNU/Linux
+
+   Copyright (C) 2000-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-nat.h"
+
+/* See nat/linux-nat.h.  */
+
+char *
+linux_pid_to_exec_file (int pid)
+{
+  static char buf[PATH_MAX];
+  char name[PATH_MAX];
+
+  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
+  memset (buf, 0, PATH_MAX);
+  if (readlink (name, buf, PATH_MAX - 1) <= 0)
+    strcpy (buf, name);
+
+  return buf;
+}
diff --git a/gdb/nat/linux-nat.h b/gdb/nat/linux-nat.h
index 7cdaf40..81c2edc 100644
--- a/gdb/nat/linux-nat.h
+++ b/gdb/nat/linux-nat.h
@@ -78,4 +78,13 @@  extern enum target_stop_reason lwp_stop_reason (struct lwp_info *lwp);
 
 extern void linux_stop_lwp (struct lwp_info *lwp);
 
+/* Return the pathname of the executable file that was run to create
+   the process PID.  If the executable file cannot be determined, NULL
+   is returned.  Otherwise, a pointer to a character string containing
+   the pathname is returned.  This string should be copied into a
+   buffer by the client if the string will not be immediately used, or
+   if it must persist.  */
+
+extern char *linux_pid_to_exec_file (int pid);
+
 #endif /* LINUX_NAT_H */