[1/2] Create new common/pathstuff.[ch]

Message ID 20180210014241.19278-2-sergiodj@redhat.com
State New, archived
Headers

Commit Message

Sergio Durigan Junior Feb. 10, 2018, 1:42 a.m. UTC
  This commit moves the path manipulation routines found on utils.c to a
new common/pathstuff.c, and updates the Makefile.in's accordingly.
The routines moved are "gdb_realpath", "gdb_realpath_keepfile" and
"gdb_abspath".

This will be needed because gdbserver will have to call "gdb_abspath"
on my next patch, which implements a way to expand the path of the
inferior provided by the user in order to allow specifying just the
binary name when starting gdbserver, like:

  $ gdbserver :1234 a.out

With the recent addition of the startup-with-shell feature on
gdbserver, this scenario doesn't work anymore if the user doesn't have
the current directory listed in the PATH variable.

I had to do a minor adjustment on "gdb_abspath" because we don't have
access to "tilde_expand" on gdbserver, so now the function is using
"gdb_tilde_expand" instead.  Otherwise, the code is the same.

Regression tested on the BuildBot, without regressions.

gdb/ChangeLog:
2018-02-09  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add "common/pathstuff.c".
	(HFILES_NO_SRCDIR): Add "common/pathstuff.h".
	(COMMON_OBS): Add "pathstuff.o".
	* common/pathstuff.c: New file.
	* common/pathstuff.h: New file.
	* utils.c (gdb_realpath): Move to "common/pathstuff.c".
	(gdb_realpath_keepfile): Likewise.
	(gdb_abspath): Likewise.
	* utils.h: Include "common/pathstuff.h".
	(gdb_realpath): Move to "common/pathstuff.h".
	(gdb_realpath_keepfile): Likewise.
	(gdb_abspath): Likewise.

gdb/gdbserver/ChangeLog:
2018-02-09  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add "$(srcdir)/common/pathstuff.c".
	(OBJS): Add "pathstuff.o".
---
 gdb/Makefile.in           |   3 +
 gdb/common/pathstuff.c    | 144 ++++++++++++++++++++++++++++++++++++++++++++++
 gdb/common/pathstuff.h    |  39 +++++++++++++
 gdb/gdbserver/Makefile.in |   2 +
 gdb/utils.c               | 119 --------------------------------------
 gdb/utils.h               |   7 +--
 6 files changed, 189 insertions(+), 125 deletions(-)
 create mode 100644 gdb/common/pathstuff.c
 create mode 100644 gdb/common/pathstuff.h
  

Comments

Simon Marchi Feb. 11, 2018, 10:13 p.m. UTC | #1
On 2018-02-09 08:42 PM, Sergio Durigan Junior wrote:
> This commit moves the path manipulation routines found on utils.c to a
> new common/pathstuff.c, and updates the Makefile.in's accordingly.
> The routines moved are "gdb_realpath", "gdb_realpath_keepfile" and
> "gdb_abspath".
> 
> This will be needed because gdbserver will have to call "gdb_abspath"
> on my next patch, which implements a way to expand the path of the
> inferior provided by the user in order to allow specifying just the
> binary name when starting gdbserver, like:
> 
>   $ gdbserver :1234 a.out
> 
> With the recent addition of the startup-with-shell feature on
> gdbserver, this scenario doesn't work anymore if the user doesn't have
> the current directory listed in the PATH variable.
> 
> I had to do a minor adjustment on "gdb_abspath" because we don't have
> access to "tilde_expand" on gdbserver, so now the function is using
> "gdb_tilde_expand" instead.  Otherwise, the code is the same.
> 
> Regression tested on the BuildBot, without regressions.

Hi Sergio,

Thanks for looking into this!

This commit does not build:

/home/simark/src/binutils-gdb/gdb/common/pathstuff.c: In function ‘gdb::unique_xmalloc_ptr<char> gdb_abspath(const char*)’:
/home/simark/src/binutils-gdb/gdb/common/pathstuff.c:140:14: error: ‘current_directory’ was not declared in this scope
     (concat (current_directory,
              ^~~~~~~~~~~~~~~~~
/home/simark/src/binutils-gdb/gdb/common/pathstuff.c:140:14: note: suggested alternative: ‘read_direction’
     (concat (current_directory,
              ^~~~~~~~~~~~~~~~~
              read_direction


I guess you need to move the declaration to common-defs.h in this commit instead of
the next one.  I also got this whitespace error from git am:

.git/rebase-apply/patch:131: trailing whitespace.
  /* Extract the basename of filename, and return immediately

I think it's in code you copied, but if you can remove the extra space while at it
it would be nice.

> +/* See common/pathstuff.h.  */
> +
> +gdb::unique_xmalloc_ptr<char>
> +gdb_abspath (const char *path)
> +{
> +  gdb_assert (path != NULL && path[0] != '\0');
> +
> +  if (path[0] == '~')
> +    {
> +      std::string new_path = gdb_tilde_expand (path);
> +
> +      return gdb::unique_xmalloc_ptr<char> (xstrdup (new_path.c_str ()));

We should try to avoid unnecessary copies, when possible.  Here, we could either make
another version of gdb_tilde_expand (it would have to be another name) that returns
a gdb::unique_xmalloc_ptr<char> or make gdb_abspath return an std::string.  I think the
former would be better for now because some callers require a gdb::unique_xmalloc_ptr<char>,
and would have to do a copy themselves.  So using a gdb::unique_xmalloc_ptr across the
whole chain would give the least amount of copies.

> diff --git a/gdb/utils.h b/gdb/utils.h
> index b234762929..4f25be0968 100644
> --- a/gdb/utils.h
> +++ b/gdb/utils.h
> @@ -23,6 +23,7 @@
>  
>  #include "exceptions.h"
>  #include "common/scoped_restore.h"
> +#include "common/pathstuff.h"

I don't think utils.h should be including common/pathstuff.h, because it is not using it.
I understand why you did this (this ensures that every current user of these functions
will automatically see the new declaration), but in the long term I think it's better if
the users include "pathstuff.h".  The files that use these functions are:

$ grep -e gdb_realpath_keepfile -e gdb_realpath -e gdb_abspath *.c */*.c -l | sort
auto-load.c
common/pathstuff.c
compile/compile.c
dwarf2read.c
exec.c
guile/scm-safe-call.c
linux-thread-db.c
main.c
nto-tdep.c
objfiles.c
source.c
symtab.c
utils.c

They are all files included in a --enable-targets=all build, so it should be easy to
find where #include "common/pathstuff.h" is missing.

Thanks,

Simon
  
Sergio Durigan Junior Feb. 12, 2018, 7:01 p.m. UTC | #2
On Sunday, February 11 2018, Simon Marchi wrote:

> On 2018-02-09 08:42 PM, Sergio Durigan Junior wrote:
>> This commit moves the path manipulation routines found on utils.c to a
>> new common/pathstuff.c, and updates the Makefile.in's accordingly.
>> The routines moved are "gdb_realpath", "gdb_realpath_keepfile" and
>> "gdb_abspath".
>> 
>> This will be needed because gdbserver will have to call "gdb_abspath"
>> on my next patch, which implements a way to expand the path of the
>> inferior provided by the user in order to allow specifying just the
>> binary name when starting gdbserver, like:
>> 
>>   $ gdbserver :1234 a.out
>> 
>> With the recent addition of the startup-with-shell feature on
>> gdbserver, this scenario doesn't work anymore if the user doesn't have
>> the current directory listed in the PATH variable.
>> 
>> I had to do a minor adjustment on "gdb_abspath" because we don't have
>> access to "tilde_expand" on gdbserver, so now the function is using
>> "gdb_tilde_expand" instead.  Otherwise, the code is the same.
>> 
>> Regression tested on the BuildBot, without regressions.
>
> Hi Sergio,

Hey, Simon,

> Thanks for looking into this!

My pleasure.

> This commit does not build:
>
> /home/simark/src/binutils-gdb/gdb/common/pathstuff.c: In function ‘gdb::unique_xmalloc_ptr<char> gdb_abspath(const char*)’:
> /home/simark/src/binutils-gdb/gdb/common/pathstuff.c:140:14: error: ‘current_directory’ was not declared in this scope
>      (concat (current_directory,
>               ^~~~~~~~~~~~~~~~~
> /home/simark/src/binutils-gdb/gdb/common/pathstuff.c:140:14: note: suggested alternative: ‘read_direction’
>      (concat (current_directory,
>               ^~~~~~~~~~~~~~~~~
>               read_direction

Ah.  Sorry about that; that's the problem of testing on BuildBot with
everything-in-one-patch.  I'll include the declaration of
current_directory in common-defs.h and also in gdbserver/server.c.

> I guess you need to move the declaration to common-defs.h in this commit instead of
> the next one.  I also got this whitespace error from git am:
>
> .git/rebase-apply/patch:131: trailing whitespace.
>   /* Extract the basename of filename, and return immediately
>
> I think it's in code you copied, but if you can remove the extra space while at it
> it would be nice.

Sure.

>> +/* See common/pathstuff.h.  */
>> +
>> +gdb::unique_xmalloc_ptr<char>
>> +gdb_abspath (const char *path)
>> +{
>> +  gdb_assert (path != NULL && path[0] != '\0');
>> +
>> +  if (path[0] == '~')
>> +    {
>> +      std::string new_path = gdb_tilde_expand (path);
>> +
>> +      return gdb::unique_xmalloc_ptr<char> (xstrdup (new_path.c_str ()));
>
> We should try to avoid unnecessary copies, when possible.  Here, we could either make
> another version of gdb_tilde_expand (it would have to be another name) that returns
> a gdb::unique_xmalloc_ptr<char> or make gdb_abspath return an std::string.  I think the
> former would be better for now because some callers require a gdb::unique_xmalloc_ptr<char>,
> and would have to do a copy themselves.  So using a gdb::unique_xmalloc_ptr across the
> whole chain would give the least amount of copies.

OK.

>> diff --git a/gdb/utils.h b/gdb/utils.h
>> index b234762929..4f25be0968 100644
>> --- a/gdb/utils.h
>> +++ b/gdb/utils.h
>> @@ -23,6 +23,7 @@
>>  
>>  #include "exceptions.h"
>>  #include "common/scoped_restore.h"
>> +#include "common/pathstuff.h"
>
> I don't think utils.h should be including common/pathstuff.h, because it is not using it.
> I understand why you did this (this ensures that every current user of these functions
> will automatically see the new declaration), but in the long term I think it's better if
> the users include "pathstuff.h".  The files that use these functions are:
>
> $ grep -e gdb_realpath_keepfile -e gdb_realpath -e gdb_abspath *.c */*.c -l | sort
> auto-load.c
> common/pathstuff.c
> compile/compile.c
> dwarf2read.c
> exec.c
> guile/scm-safe-call.c
> linux-thread-db.c
> main.c
> nto-tdep.c
> objfiles.c
> source.c
> symtab.c
> utils.c
>
> They are all files included in a --enable-targets=all build, so it should be easy to
> find where #include "common/pathstuff.h" is missing.

Alright, no problem.

I'll send a v2 soon.

Thanks,
  
Joel Brobecker Feb. 21, 2018, 7:56 a.m. UTC | #3
Hi Sergio,


On Fri, Feb 09, 2018 at 08:42:40PM -0500, Sergio Durigan Junior wrote:
> This commit moves the path manipulation routines found on utils.c to a
> new common/pathstuff.c, and updates the Makefile.in's accordingly.
> The routines moved are "gdb_realpath", "gdb_realpath_keepfile" and
> "gdb_abspath".
> 
> This will be needed because gdbserver will have to call "gdb_abspath"
> on my next patch, which implements a way to expand the path of the
> inferior provided by the user in order to allow specifying just the
> binary name when starting gdbserver, like:
> 
>   $ gdbserver :1234 a.out
> 
> With the recent addition of the startup-with-shell feature on
> gdbserver, this scenario doesn't work anymore if the user doesn't have
> the current directory listed in the PATH variable.
> 
> I had to do a minor adjustment on "gdb_abspath" because we don't have
> access to "tilde_expand" on gdbserver, so now the function is using
> "gdb_tilde_expand" instead.  Otherwise, the code is the same.
> 
> Regression tested on the BuildBot, without regressions.
> 
> gdb/ChangeLog:
> 2018-02-09  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* Makefile.in (SFILES): Add "common/pathstuff.c".
> 	(HFILES_NO_SRCDIR): Add "common/pathstuff.h".
> 	(COMMON_OBS): Add "pathstuff.o".
> 	* common/pathstuff.c: New file.
> 	* common/pathstuff.h: New file.
> 	* utils.c (gdb_realpath): Move to "common/pathstuff.c".
> 	(gdb_realpath_keepfile): Likewise.
> 	(gdb_abspath): Likewise.
> 	* utils.h: Include "common/pathstuff.h".
> 	(gdb_realpath): Move to "common/pathstuff.h".
> 	(gdb_realpath_keepfile): Likewise.
> 	(gdb_abspath): Likewise.
> 
> gdb/gdbserver/ChangeLog:
> 2018-02-09  Sergio Durigan Junior  <sergiodj@redhat.com>

Thanks for doing this work!

> 	* Makefile.in (SFILES): Add "$(srcdir)/common/pathstuff.c".
> 	(OBJS): Add "pathstuff.o".
> +++ b/gdb/common/pathstuff.c
> @@ -0,0 +1,144 @@
[...]
> +gdb::unique_xmalloc_ptr<char>
> +gdb_realpath (const char *filename)

I realize you are just moving the function, but the function's missing
some documentation. I think it would be useful to add.

What lead me to this is the fact that there is one particularly
important element, is that this function used the current working
directory to expand relative paths. In the case of GDB, I verified
that when the user does a "cd DIR", GDB updates both current_directory
and its actual current working directory (in other words, we always
maintain the property current_directory == getcwd ().

In GDBserver, however, it doesn't seem to be the case. So I think
we need to be explicit about that, because calls to gdb_realpath
and gdb_abspath with the same filename  might actually return
the path to two different files if the conditions are right!

Ideally, I think we would want gdb_realpath and gdb_abspath to
return the same value. But, if we are interested, I suggest we
discuss that separately from this thread. This is potentially
disruptive (and potentially in a good way ;-)).

> +/* Return PATH in absolute form, performing tilde-expansion if necessary.
> +   PATH cannot be NULL or the empty string.
> +   This does not resolve symlinks however, use gdb_realpath for that.  */
> +
> +extern gdb::unique_xmalloc_ptr<char> gdb_abspath (const char *path);

Similar to the above, I think we should be clear that the expansion
of relative path is done relative to the current_directory (or
the current working directory if NULL). Something like that.
  
Sergio Durigan Junior Feb. 22, 2018, 6:43 p.m. UTC | #4
On Wednesday, February 21 2018, Joel Brobecker wrote:

> Hi Sergio,

Hi Joel,

>
> On Fri, Feb 09, 2018 at 08:42:40PM -0500, Sergio Durigan Junior wrote:
>> This commit moves the path manipulation routines found on utils.c to a
>> new common/pathstuff.c, and updates the Makefile.in's accordingly.
>> The routines moved are "gdb_realpath", "gdb_realpath_keepfile" and
>> "gdb_abspath".
>> 
>> This will be needed because gdbserver will have to call "gdb_abspath"
>> on my next patch, which implements a way to expand the path of the
>> inferior provided by the user in order to allow specifying just the
>> binary name when starting gdbserver, like:
>> 
>>   $ gdbserver :1234 a.out
>> 
>> With the recent addition of the startup-with-shell feature on
>> gdbserver, this scenario doesn't work anymore if the user doesn't have
>> the current directory listed in the PATH variable.
>> 
>> I had to do a minor adjustment on "gdb_abspath" because we don't have
>> access to "tilde_expand" on gdbserver, so now the function is using
>> "gdb_tilde_expand" instead.  Otherwise, the code is the same.
>> 
>> Regression tested on the BuildBot, without regressions.
>> 
>> gdb/ChangeLog:
>> 2018-02-09  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* Makefile.in (SFILES): Add "common/pathstuff.c".
>> 	(HFILES_NO_SRCDIR): Add "common/pathstuff.h".
>> 	(COMMON_OBS): Add "pathstuff.o".
>> 	* common/pathstuff.c: New file.
>> 	* common/pathstuff.h: New file.
>> 	* utils.c (gdb_realpath): Move to "common/pathstuff.c".
>> 	(gdb_realpath_keepfile): Likewise.
>> 	(gdb_abspath): Likewise.
>> 	* utils.h: Include "common/pathstuff.h".
>> 	(gdb_realpath): Move to "common/pathstuff.h".
>> 	(gdb_realpath_keepfile): Likewise.
>> 	(gdb_abspath): Likewise.
>> 
>> gdb/gdbserver/ChangeLog:
>> 2018-02-09  Sergio Durigan Junior  <sergiodj@redhat.com>
>
> Thanks for doing this work!

No problem.

>> 	* Makefile.in (SFILES): Add "$(srcdir)/common/pathstuff.c".
>> 	(OBJS): Add "pathstuff.o".
>> +++ b/gdb/common/pathstuff.c
>> @@ -0,0 +1,144 @@
> [...]
>> +gdb::unique_xmalloc_ptr<char>
>> +gdb_realpath (const char *filename)
>
> I realize you are just moving the function, but the function's missing
> some documentation. I think it would be useful to add.
>
> What lead me to this is the fact that there is one particularly
> important element, is that this function used the current working
> directory to expand relative paths. In the case of GDB, I verified
> that when the user does a "cd DIR", GDB updates both current_directory
> and its actual current working directory (in other words, we always
> maintain the property current_directory == getcwd ().
>
> In GDBserver, however, it doesn't seem to be the case. So I think
> we need to be explicit about that, because calls to gdb_realpath
> and gdb_abspath with the same filename  might actually return
> the path to two different files if the conditions are right!

Exactly.  GDB has different concepts for "inferior CWD" and "GDB CWD".
gdbserver, after my patch which implemented the inferior CWD handling,
just cares about the "inferior CWD".  But now, with the current patch
we're discussing, gdbserver will have a "current_directory" variable and
will be more aware of its own CWD.

> Ideally, I think we would want gdb_realpath and gdb_abspath to
> return the same value. But, if we are interested, I suggest we
> discuss that separately from this thread. This is potentially
> disruptive (and potentially in a good way ;-)).

Yes, that's a good point.  I will include a comment about this.

>> +/* Return PATH in absolute form, performing tilde-expansion if necessary.
>> +   PATH cannot be NULL or the empty string.
>> +   This does not resolve symlinks however, use gdb_realpath for that.  */
>> +
>> +extern gdb::unique_xmalloc_ptr<char> gdb_abspath (const char *path);
>
> Similar to the above, I think we should be clear that the expansion
> of relative path is done relative to the current_directory (or
> the current working directory if NULL). Something like that.

Consider it done.

Thanks,
  

Patch

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 957654c9bd..64c9df3eaf 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1136,6 +1136,7 @@  SFILES = \
 	common/gdb_tilde_expand.c \
 	common/gdb_vecs.c \
 	common/new-op.c \
+	common/pathstuff.c \
 	common/print-utils.c \
 	common/ptid.c \
 	common/rsp-low.c \
@@ -1427,6 +1428,7 @@  HFILES_NO_SRCDIR = \
 	common/gdb_wait.h \
 	common/common-inferior.h \
 	common/host-defs.h \
+	common/pathstuff.h \
 	common/print-utils.h \
 	common/ptid.h \
 	common/queue.h \
@@ -1552,6 +1554,7 @@  COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	gdb_vecs.o \
 	mi/mi-common.o \
 	new-op.o \
+	pathstuff.o \
 	print-utils.o \
 	ptid.o \
 	rsp-low.o \
diff --git a/gdb/common/pathstuff.c b/gdb/common/pathstuff.c
new file mode 100644
index 0000000000..42af3fa65a
--- /dev/null
+++ b/gdb/common/pathstuff.c
@@ -0,0 +1,144 @@ 
+/* Path manipulation routines for GDB and gdbserver.
+
+   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "common-defs.h"
+#include "pathstuff.h"
+#include "host-defs.h"
+#include "filenames.h"
+#include "gdb_tilde_expand.h"
+
+gdb::unique_xmalloc_ptr<char>
+gdb_realpath (const char *filename)
+{
+/* On most hosts, we rely on canonicalize_file_name to compute
+   the FILENAME's realpath.
+
+   But the situation is slightly more complex on Windows, due to some
+   versions of GCC which were reported to generate paths where
+   backlashes (the directory separator) were doubled.  For instance:
+      c:\\some\\double\\slashes\\dir
+   ... instead of ...
+      c:\some\double\slashes\dir
+   Those double-slashes were getting in the way when comparing paths,
+   for instance when trying to insert a breakpoint as follow:
+      (gdb) b c:/some/double/slashes/dir/foo.c:4
+      No source file named c:/some/double/slashes/dir/foo.c:4.
+      (gdb) b c:\some\double\slashes\dir\foo.c:4
+      No source file named c:\some\double\slashes\dir\foo.c:4.
+   To prevent this from happening, we need this function to always
+   strip those extra backslashes.  While canonicalize_file_name does
+   perform this simplification, it only works when the path is valid.
+   Since the simplification would be useful even if the path is not
+   valid (one can always set a breakpoint on a file, even if the file
+   does not exist locally), we rely instead on GetFullPathName to
+   perform the canonicalization.  */
+
+#if defined (_WIN32)
+  {
+    char buf[MAX_PATH];
+    DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL);
+
+    /* The file system is case-insensitive but case-preserving.
+       So it is important we do not lowercase the path.  Otherwise,
+       we might not be able to display the original casing in a given
+       path.  */
+    if (len > 0 && len < MAX_PATH)
+      return gdb::unique_xmalloc_ptr<char> (xstrdup (buf));
+  }
+#else
+  {
+    char *rp = canonicalize_file_name (filename);
+
+    if (rp != NULL)
+      return gdb::unique_xmalloc_ptr<char> (rp);
+  }
+#endif
+
+  /* This system is a lost cause, just dup the buffer.  */
+  return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
+}
+
+/* See common/pathstuff.h.  */
+
+gdb::unique_xmalloc_ptr<char>
+gdb_realpath_keepfile (const char *filename)
+{
+  const char *base_name = lbasename (filename);
+  char *dir_name;
+  char *result;
+
+  /* Extract the basename of filename, and return immediately 
+     a copy of filename if it does not contain any directory prefix.  */
+  if (base_name == filename)
+    return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
+
+  dir_name = (char *) alloca ((size_t) (base_name - filename + 2));
+  /* Allocate enough space to store the dir_name + plus one extra
+     character sometimes needed under Windows (see below), and
+     then the closing \000 character.  */
+  strncpy (dir_name, filename, base_name - filename);
+  dir_name[base_name - filename] = '\000';
+
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  /* We need to be careful when filename is of the form 'd:foo', which
+     is equivalent of d:./foo, which is totally different from d:/foo.  */
+  if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
+    {
+      dir_name[2] = '.';
+      dir_name[3] = '\000';
+    }
+#endif
+
+  /* Canonicalize the directory prefix, and build the resulting
+     filename.  If the dirname realpath already contains an ending
+     directory separator, avoid doubling it.  */
+  gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
+  const char *real_path = path_storage.get ();
+  if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
+    result = concat (real_path, base_name, (char *) NULL);
+  else
+    result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
+
+  return gdb::unique_xmalloc_ptr<char> (result);
+}
+
+/* See common/pathstuff.h.  */
+
+gdb::unique_xmalloc_ptr<char>
+gdb_abspath (const char *path)
+{
+  gdb_assert (path != NULL && path[0] != '\0');
+
+  if (path[0] == '~')
+    {
+      std::string new_path = gdb_tilde_expand (path);
+
+      return gdb::unique_xmalloc_ptr<char> (xstrdup (new_path.c_str ()));
+    }
+
+  if (IS_ABSOLUTE_PATH (path))
+    return gdb::unique_xmalloc_ptr<char> (xstrdup (path));
+
+  /* Beware the // my son, the Emacs barfs, the botch that catch...  */
+  return gdb::unique_xmalloc_ptr<char>
+    (concat (current_directory,
+	     IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
+	     ? "" : SLASH_STRING,
+	     path, (char *) NULL));
+}
diff --git a/gdb/common/pathstuff.h b/gdb/common/pathstuff.h
new file mode 100644
index 0000000000..909fd786bb
--- /dev/null
+++ b/gdb/common/pathstuff.h
@@ -0,0 +1,39 @@ 
+/* Path manipulation routines for GDB and gdbserver.
+
+   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef PATHSTUFF_H
+#define PATHSTUFF_H
+
+/* Path utilities.  */
+
+extern gdb::unique_xmalloc_ptr<char> gdb_realpath (const char *filename);
+
+/* Return a copy of FILENAME, with its directory prefix canonicalized
+   by gdb_realpath.  */
+
+extern gdb::unique_xmalloc_ptr<char>
+  gdb_realpath_keepfile (const char *filename);
+
+/* Return PATH in absolute form, performing tilde-expansion if necessary.
+   PATH cannot be NULL or the empty string.
+   This does not resolve symlinks however, use gdb_realpath for that.  */
+
+extern gdb::unique_xmalloc_ptr<char> gdb_abspath (const char *path);
+
+#endif /* PATHSTUFF_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 3ce086d70f..4ac068c6dd 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -209,6 +209,7 @@  SFILES = \
 	$(srcdir)/common/gdb_tilde_expand.c \
 	$(srcdir)/common/gdb_vecs.c \
 	$(srcdir)/common/new-op.c \
+	$(srcdir)/common/pathstuff.c \
 	$(srcdir)/common/print-utils.c \
 	$(srcdir)/common/ptid.c \
 	$(srcdir)/common/rsp-low.c \
@@ -256,6 +257,7 @@  OBS = \
 	mem-break.o \
 	new-op.o \
 	notif.o \
+	pathstuff.o \
 	print-utils.o \
 	ptid.o \
 	regcache.o \
diff --git a/gdb/utils.c b/gdb/utils.c
index c531748fe4..0acfad60cf 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -2838,57 +2838,6 @@  string_to_core_addr (const char *my_string)
   return addr;
 }
 
-gdb::unique_xmalloc_ptr<char>
-gdb_realpath (const char *filename)
-{
-/* On most hosts, we rely on canonicalize_file_name to compute
-   the FILENAME's realpath.
-
-   But the situation is slightly more complex on Windows, due to some
-   versions of GCC which were reported to generate paths where
-   backlashes (the directory separator) were doubled.  For instance:
-      c:\\some\\double\\slashes\\dir
-   ... instead of ...
-      c:\some\double\slashes\dir
-   Those double-slashes were getting in the way when comparing paths,
-   for instance when trying to insert a breakpoint as follow:
-      (gdb) b c:/some/double/slashes/dir/foo.c:4
-      No source file named c:/some/double/slashes/dir/foo.c:4.
-      (gdb) b c:\some\double\slashes\dir\foo.c:4
-      No source file named c:\some\double\slashes\dir\foo.c:4.
-   To prevent this from happening, we need this function to always
-   strip those extra backslashes.  While canonicalize_file_name does
-   perform this simplification, it only works when the path is valid.
-   Since the simplification would be useful even if the path is not
-   valid (one can always set a breakpoint on a file, even if the file
-   does not exist locally), we rely instead on GetFullPathName to
-   perform the canonicalization.  */
-
-#if defined (_WIN32)
-  {
-    char buf[MAX_PATH];
-    DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL);
-
-    /* The file system is case-insensitive but case-preserving.
-       So it is important we do not lowercase the path.  Otherwise,
-       we might not be able to display the original casing in a given
-       path.  */
-    if (len > 0 && len < MAX_PATH)
-      return gdb::unique_xmalloc_ptr<char> (xstrdup (buf));
-  }
-#else
-  {
-    char *rp = canonicalize_file_name (filename);
-
-    if (rp != NULL)
-      return gdb::unique_xmalloc_ptr<char> (rp);
-  }
-#endif
-
-  /* This system is a lost cause, just dup the buffer.  */
-  return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
-}
-
 #if GDB_SELF_TEST
 
 static void
@@ -2925,74 +2874,6 @@  gdb_realpath_tests ()
 
 #endif /* GDB_SELF_TEST */
 
-/* Return a copy of FILENAME, with its directory prefix canonicalized
-   by gdb_realpath.  */
-
-gdb::unique_xmalloc_ptr<char>
-gdb_realpath_keepfile (const char *filename)
-{
-  const char *base_name = lbasename (filename);
-  char *dir_name;
-  char *result;
-
-  /* Extract the basename of filename, and return immediately 
-     a copy of filename if it does not contain any directory prefix.  */
-  if (base_name == filename)
-    return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
-
-  dir_name = (char *) alloca ((size_t) (base_name - filename + 2));
-  /* Allocate enough space to store the dir_name + plus one extra
-     character sometimes needed under Windows (see below), and
-     then the closing \000 character.  */
-  strncpy (dir_name, filename, base_name - filename);
-  dir_name[base_name - filename] = '\000';
-
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-  /* We need to be careful when filename is of the form 'd:foo', which
-     is equivalent of d:./foo, which is totally different from d:/foo.  */
-  if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
-    {
-      dir_name[2] = '.';
-      dir_name[3] = '\000';
-    }
-#endif
-
-  /* Canonicalize the directory prefix, and build the resulting
-     filename.  If the dirname realpath already contains an ending
-     directory separator, avoid doubling it.  */
-  gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
-  const char *real_path = path_storage.get ();
-  if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
-    result = concat (real_path, base_name, (char *) NULL);
-  else
-    result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
-
-  return gdb::unique_xmalloc_ptr<char> (result);
-}
-
-/* Return PATH in absolute form, performing tilde-expansion if necessary.
-   PATH cannot be NULL or the empty string.
-   This does not resolve symlinks however, use gdb_realpath for that.  */
-
-gdb::unique_xmalloc_ptr<char>
-gdb_abspath (const char *path)
-{
-  gdb_assert (path != NULL && path[0] != '\0');
-
-  if (path[0] == '~')
-    return gdb::unique_xmalloc_ptr<char> (tilde_expand (path));
-
-  if (IS_ABSOLUTE_PATH (path))
-    return gdb::unique_xmalloc_ptr<char> (xstrdup (path));
-
-  /* Beware the // my son, the Emacs barfs, the botch that catch...  */
-  return gdb::unique_xmalloc_ptr<char>
-    (concat (current_directory,
-	     IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
-	     ? "" : SLASH_STRING,
-	     path, (char *) NULL));
-}
-
 ULONGEST
 align_up (ULONGEST v, int n)
 {
diff --git a/gdb/utils.h b/gdb/utils.h
index b234762929..4f25be0968 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -23,6 +23,7 @@ 
 
 #include "exceptions.h"
 #include "common/scoped_restore.h"
+#include "common/pathstuff.h"
 #include <chrono>
 
 extern void initialize_utils (void);
@@ -295,12 +296,6 @@  extern struct cleanup *make_bpstat_clear_actions_cleanup (void);
 
 /* Path utilities.  */
 
-extern gdb::unique_xmalloc_ptr<char> gdb_realpath (const char *);
-
-extern gdb::unique_xmalloc_ptr<char> gdb_realpath_keepfile (const char *);
-
-extern gdb::unique_xmalloc_ptr<char> gdb_abspath (const char *);
-
 extern int gdb_filename_fnmatch (const char *pattern, const char *string,
 				 int flags);