public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 3/4] Introduce gdb_chdir
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
  2017-09-12  4:23 ` [PATCH 4/4] Implement " Sergio Durigan Junior
@ 2017-09-12  4:23 ` Sergio Durigan Junior
  2017-09-12 14:53   ` Eli Zaretskii
  2017-09-13 16:07   ` Pedro Alves
  2017-09-12  4:23 ` [PATCH 2/4] Import "glob" module from gnulib Sergio Durigan Junior
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-12  4:23 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

In order to be able to change the inferior's directory before its
execution, it is necessary to perform a tilde expansion of the
directory provided by the user and then chdir into the resulting dir.
This is what gdb_chdir does.

Unfortunately it is not possible to use "tilde_expand" from readline
because this is common code and gdbserver doesn't use readline.  For
that reason I decided to go with "glob" and its GNU extension,
GLOB_TILDE.  With the import of the "glob" module from gnulib, this is
a no-brainer.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add gdb_chdir.c.
	(HFILES_NO_SRCDIR): Add gdb_chdir.h.
	(COMMON_OBS): Add gdb_chdir.o.
	* common/gdb_chdir.c: New file.
	* common/gdb_chdir.h: Likewise.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add $(srcdir)/common/gdb_chdir.c.
	(OBS): Add gdb_chdir.o.
---
 gdb/Makefile.in           |  3 +++
 gdb/common/gdb_chdir.c    | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 gdb/common/gdb_chdir.h    | 26 ++++++++++++++++++++
 gdb/gdbserver/Makefile.in |  2 ++
 4 files changed, 91 insertions(+)
 create mode 100644 gdb/common/gdb_chdir.c
 create mode 100644 gdb/common/gdb_chdir.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2aa474e598..38c89761dd 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1243,6 +1243,7 @@ SFILES = \
 	common/filestuff.c \
 	common/format.c \
 	common/job-control.c \
+	common/gdb_chdir.c \
 	common/gdb_vecs.c \
 	common/new-op.c \
 	common/print-utils.c \
@@ -1527,6 +1528,7 @@ HFILES_NO_SRCDIR = \
 	common/fileio.h \
 	common/format.h \
 	common/gdb_assert.h \
+	common/gdb_chdir.h \
 	common/gdb_locale.h \
 	common/gdb_setjmp.h \
 	common/gdb_signals.h \
@@ -1732,6 +1734,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	frame-unwind.o \
 	gcore.o \
 	gdb_bfd.o \
+	gdb_chdir.o \
 	gdb-dlfcn.o \
 	gdb_obstack.o \
 	gdb_regex.o \
diff --git a/gdb/common/gdb_chdir.c b/gdb/common/gdb_chdir.c
new file mode 100644
index 0000000000..16e2b3adf0
--- /dev/null
+++ b/gdb/common/gdb_chdir.c
@@ -0,0 +1,60 @@
+/* chdir(2) wrapper for GDB and gdbserver.
+
+   Copyright (C) 2017 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 <glob.h>
+#include "gdb_chdir.h"
+
+/* Perform path expansion (i.e., tilde expansion) on DIR, and return
+   the full path.  */
+
+static std::string
+expand_path (const char *dir)
+{
+  glob_t g;
+  std::string expanded_dir;
+  int err = glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL, &g);
+
+  if (err != 0)
+    {
+      if (err == GLOB_NOMATCH)
+	error (_("No such directory '%s'.  Failure to set cwd."), dir);
+
+      error (_("Could not process directory '%s'."), dir);
+    }
+
+  gdb_assert (g.gl_pathc > 0);
+  /* "glob" may return more than one match to the path provided by the
+     user, but we are only interested in the first match.  */
+  expanded_dir = g.gl_pathv[0];
+  globfree (&g);
+
+  return expanded_dir;
+}
+
+/* See gdb_chdir.h.  */
+
+void
+gdb_chdir (const char *dir)
+{
+  std::string expanded_dir = expand_path (dir);
+
+  if (chdir (expanded_dir.c_str ()) < 0)
+    perror_with_name (expanded_dir.c_str ());
+}
diff --git a/gdb/common/gdb_chdir.h b/gdb/common/gdb_chdir.h
new file mode 100644
index 0000000000..5e6253e3b5
--- /dev/null
+++ b/gdb/common/gdb_chdir.h
@@ -0,0 +1,26 @@
+/* chdir(2) wrapper for GDB and gdbserver.
+
+   Copyright (C) 2017 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 HAVE_GDB_CHDIR_H
+#define HAVE_GDB_CHDIR_H
+
+/* Perform a "chdir" to DIR, doing the proper tilde expansion before.  */
+extern void gdb_chdir (const char *dir);
+
+#endif /* ! HAVE_GDB_CHDIR_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 1bbe515629..ecd12a7dcc 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -205,6 +205,7 @@ SFILES = \
 	$(srcdir)/common/fileio.c \
 	$(srcdir)/common/filestuff.c \
 	$(srcdir)/common/job-control.c \
+	$(srcdir)/common/gdb_chdir.c \
 	$(srcdir)/common/gdb_vecs.c \
 	$(srcdir)/common/new-op.c \
 	$(srcdir)/common/print-utils.c \
@@ -247,6 +248,7 @@ OBS = \
 	fileio.o \
 	filestuff.o \
 	format.o \
+	gdb_chdir.o \
 	gdb_vecs.o \
 	hostio.o \
 	inferiors.o \
-- 
2.13.3

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

* [PATCH 1/4] Make gdb_dirbuf local to functions
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
                   ` (2 preceding siblings ...)
  2017-09-12  4:23 ` [PATCH 2/4] Import "glob" module from gnulib Sergio Durigan Junior
@ 2017-09-12  4:23 ` Sergio Durigan Junior
  2017-09-13 15:12   ` Pedro Alves
  2017-09-12 14:55 ` [PATCH 0/4] New "set cwd" command Eli Zaretskii
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-12  4:23 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This is not a requirement for the feature, but I think it's a good
cleanup and is related anyway.  Currently we have "current_directory"
and "gdb_dirbuf" globals, which means that we basically have two
possible places to consult when we want to know GDB's current working
directory.

This is not ideal and can lead to confusion, so my proposal is to
"internalize" the "gdb_dirbuf" variable, because it is really just
that: a buffer to be used when calling "getcwd".  With this, only
"current_directory" should be used to determine the cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* cli/cli-cmds.c (quit_command): Declare "gdb_dirbuf".
	(cd_command): Free "current_directory" before assigning to it.
	* main.c (captured_main_1): Likewise.  Call "xstrdup" when
	storing it on "current_directory".
	* mi/mi-cmd-env.c (mi_cmd_env_pwd): Declare "gdb_dirbuf".
	* top.c (gdb_dirbuf): Remove global declaration.
	* top.h (gdb_dirbuf): Likewise.
---
 gdb/cli/cli-cmds.c  | 7 ++++++-
 gdb/main.c          | 4 +++-
 gdb/mi/mi-cmd-env.c | 1 +
 gdb/top.c           | 3 ---
 gdb/top.h           | 1 -
 5 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 883844ee70..64e893c784 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -380,6 +380,8 @@ quit_command (char *args, int from_tty)
 static void
 pwd_command (char *args, int from_tty)
 {
+  char gdb_dirbuf[BUFSIZ];
+
   if (args)
     error (_("The \"pwd\" command does not take an argument: %s"), args);
   if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
@@ -434,7 +436,10 @@ cd_command (char *dir, int from_tty)
 
   dir_holder.reset (savestring (dir, len));
   if (IS_ABSOLUTE_PATH (dir_holder.get ()))
-    current_directory = dir_holder.release ();
+    {
+      xfree (current_directory);
+      current_directory = dir_holder.release ();
+    }
   else
     {
       if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
diff --git a/gdb/main.c b/gdb/main.c
index a0646edad6..9837729966 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -549,10 +549,12 @@ captured_main_1 (struct captured_main_args *context)
     (xstrprintf ("%s: warning: ", gdb_program_name));
   warning_pre_print = tmp_warn_preprint.get ();
 
+  char gdb_dirbuf[BUFSIZ];
+
   if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
     perror_warning_with_name (_("error finding working directory"));
 
-  current_directory = gdb_dirbuf;
+  current_directory = xstrdup (gdb_dirbuf);
 
   /* Set the sysroot path.  */
   gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT,
diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
index 977b6e274d..55d08ee5f2 100644
--- a/gdb/mi/mi-cmd-env.c
+++ b/gdb/mi/mi-cmd-env.c
@@ -62,6 +62,7 @@ void
 mi_cmd_env_pwd (const char *command, char **argv, int argc)
 {
   struct ui_out *uiout = current_uiout;
+  char gdb_dirbuf[BUFSIZ];
 
   if (argc > 0)
     error (_("-environment-pwd: No arguments allowed"));
diff --git a/gdb/top.c b/gdb/top.c
index 742c1e7a07..0f36dce760 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -133,9 +133,6 @@ show_confirm (struct ui_file *file, int from_tty,
 
 char *current_directory;
 
-/* The directory name is actually stored here (usually).  */
-char gdb_dirbuf[1024];
-
 /* The last command line executed on the console.  Used for command
    repetitions.  */
 char *saved_command_line;
diff --git a/gdb/top.h b/gdb/top.h
index 45798897f6..6b66083995 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -219,7 +219,6 @@ extern void ui_unregister_input_event_handler (struct ui *ui);
 /* From top.c.  */
 extern char *saved_command_line;
 extern int confirm;
-extern char gdb_dirbuf[1024];
 extern int inhibit_gdbinit;
 extern const char gdbinit[];
 
-- 
2.13.3

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

* [PATCH 0/4] New "set cwd" command
@ 2017-09-12  4:23 Sergio Durigan Junior
  2017-09-12  4:23 ` [PATCH 4/4] Implement " Sergio Durigan Junior
                   ` (9 more replies)
  0 siblings, 10 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-12  4:23 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves

This patch series is a followup of the discussion that happened at:

  https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html

It implements a new GDB command, "set cwd", which is used to set the
current working directory of the inferior that will be started.  This
is a GDB-only command for now; its gdbserver counterpart will come
later.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.

This has been regtested on BuildBot, and the only failures I'm seeing
are related to a (very strange) stack overflow on guile, which just
happens on certain builders.  I don't think this series has anything
to do about it, but if I find something related later I'll let you
know.

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

* [PATCH 2/4] Import "glob" module from gnulib
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
  2017-09-12  4:23 ` [PATCH 4/4] Implement " Sergio Durigan Junior
  2017-09-12  4:23 ` [PATCH 3/4] Introduce gdb_chdir Sergio Durigan Junior
@ 2017-09-12  4:23 ` Sergio Durigan Junior
  2017-09-12  4:23 ` [PATCH 1/4] Make gdb_dirbuf local to functions Sergio Durigan Junior
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-12  4:23 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This module is necessary because of the rework that will be done in
the "change directory" logic on GDB/gdbserver in the next commit.

We will have a way to "cd" to a directory also on gdbserver, but in
order to do that uniformly, there must be a way to do tilde expansion
on directories provided by the user.  Currently, GDB uses
"tilde_expand" from readline to do that, but gdbserver doesn't link
against readline and therefore cannot use this function.  The solution
is to use "glob" instead, which can perform tilde expansion as a GNU
extension.  Therefore, we need gnulib's version of "glob".

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gnulib/aclocal.m4: Regenerate.
	* gnulib/config.in: Likewise.
	* gnulib/configure: Likewise.
	* gnulib/import/Makefile.am: Likewise.
	* gnulib/import/Makefile.in: Likewise.
	* gnulib/import/closedir.c: New file.
	* gnulib/import/dirent-private.h: Likewise.
	* gnulib/import/filename.h: Likewise.
	* gnulib/import/getlogin_r.c: Likewise.
	* gnulib/import/glob-libc.h: Likewise.
	* gnulib/import/glob.c: Likewise.
	* gnulib/import/glob.in.h: Likewise.
	* gnulib/import/m4/closedir.m4: Likewise.
	* gnulib/import/m4/d-type.m4: Likewise.
	* gnulib/import/m4/getlogin_r.m4: Likewise.
	* gnulib/import/m4/glob.m4: Likewise.
	* gnulib/import/m4/gnulib-cache.m4: Regenerate.
	* gnulib/import/m4/gnulib-comp.m4: Likewise.
	* gnulib/import/m4/mempcpy.m4: New file.
	* gnulib/import/m4/opendir.m4: Likewise.
	* gnulib/import/m4/readdir.m4: Likewise.
	* gnulib/import/mempcpy.c: Likewise.
	* gnulib/import/opendir.c: Likewise.
	* gnulib/import/readdir.c: Likewise.
	* gnulib/update-gnulib.sh (IMPORTED_GNULIB_MODULES): Add glob.
---
 gdb/gnulib/aclocal.m4                |    7 +
 gdb/gnulib/config.in                 |   51 +
 gdb/gnulib/configure                 |  523 +++++++++-
 gdb/gnulib/import/Makefile.am        |   83 +-
 gdb/gnulib/import/Makefile.in        |   93 +-
 gdb/gnulib/import/closedir.c         |   71 ++
 gdb/gnulib/import/dirent-private.h   |   40 +
 gdb/gnulib/import/filename.h         |   54 +
 gdb/gnulib/import/getlogin_r.c       |   87 ++
 gdb/gnulib/import/glob-libc.h        |  212 ++++
 gdb/gnulib/import/glob.c             | 1808 ++++++++++++++++++++++++++++++++++
 gdb/gnulib/import/glob.in.h          |   93 ++
 gdb/gnulib/import/m4/closedir.m4     |   30 +
 gdb/gnulib/import/m4/d-type.m4       |   32 +
 gdb/gnulib/import/m4/getlogin_r.m4   |   88 ++
 gdb/gnulib/import/m4/glob.m4         |   76 ++
 gdb/gnulib/import/m4/gnulib-cache.m4 |    3 +-
 gdb/gnulib/import/m4/gnulib-comp.m4  |   58 ++
 gdb/gnulib/import/m4/mempcpy.m4      |   26 +
 gdb/gnulib/import/m4/opendir.m4      |   31 +
 gdb/gnulib/import/m4/readdir.m4      |   15 +
 gdb/gnulib/import/mempcpy.c          |   28 +
 gdb/gnulib/import/opendir.c          |  169 ++++
 gdb/gnulib/import/readdir.c          |   98 ++
 gdb/gnulib/update-gnulib.sh          |    1 +
 25 files changed, 3743 insertions(+), 34 deletions(-)
 create mode 100644 gdb/gnulib/import/closedir.c
 create mode 100644 gdb/gnulib/import/dirent-private.h
 create mode 100644 gdb/gnulib/import/filename.h
 create mode 100644 gdb/gnulib/import/getlogin_r.c
 create mode 100644 gdb/gnulib/import/glob-libc.h
 create mode 100644 gdb/gnulib/import/glob.c
 create mode 100644 gdb/gnulib/import/glob.in.h
 create mode 100644 gdb/gnulib/import/m4/closedir.m4
 create mode 100644 gdb/gnulib/import/m4/d-type.m4
 create mode 100644 gdb/gnulib/import/m4/getlogin_r.m4
 create mode 100644 gdb/gnulib/import/m4/glob.m4
 create mode 100644 gdb/gnulib/import/m4/mempcpy.m4
 create mode 100644 gdb/gnulib/import/m4/opendir.m4
 create mode 100644 gdb/gnulib/import/m4/readdir.m4
 create mode 100644 gdb/gnulib/import/mempcpy.c
 create mode 100644 gdb/gnulib/import/opendir.c
 create mode 100644 gdb/gnulib/import/readdir.c

diff --git a/gdb/gnulib/aclocal.m4 b/gdb/gnulib/aclocal.m4
index a4ce6a6b47..e9e0be9d71 100644
--- a/gdb/gnulib/aclocal.m4
+++ b/gdb/gnulib/aclocal.m4
@@ -1016,8 +1016,10 @@ m4_include([import/m4/00gnulib.m4])
 m4_include([import/m4/absolute-header.m4])
 m4_include([import/m4/alloca.m4])
 m4_include([import/m4/canonicalize.m4])
+m4_include([import/m4/closedir.m4])
 m4_include([import/m4/codeset.m4])
 m4_include([import/m4/configmake.m4])
+m4_include([import/m4/d-type.m4])
 m4_include([import/m4/dirent_h.m4])
 m4_include([import/m4/dirfd.m4])
 m4_include([import/m4/dirname.m4])
@@ -1036,8 +1038,10 @@ m4_include([import/m4/fnmatch.m4])
 m4_include([import/m4/fpieee.m4])
 m4_include([import/m4/frexp.m4])
 m4_include([import/m4/frexpl.m4])
+m4_include([import/m4/getlogin_r.m4])
 m4_include([import/m4/gettimeofday.m4])
 m4_include([import/m4/glibc21.m4])
+m4_include([import/m4/glob.m4])
 m4_include([import/m4/gnulib-common.m4])
 m4_include([import/m4/gnulib-comp.m4])
 m4_include([import/m4/hard-locale.m4])
@@ -1063,12 +1067,15 @@ m4_include([import/m4/mbsrtowcs.m4])
 m4_include([import/m4/mbstate_t.m4])
 m4_include([import/m4/memchr.m4])
 m4_include([import/m4/memmem.m4])
+m4_include([import/m4/mempcpy.m4])
 m4_include([import/m4/mmap-anon.m4])
 m4_include([import/m4/multiarch.m4])
 m4_include([import/m4/nocrash.m4])
 m4_include([import/m4/off_t.m4])
+m4_include([import/m4/opendir.m4])
 m4_include([import/m4/pathmax.m4])
 m4_include([import/m4/rawmemchr.m4])
+m4_include([import/m4/readdir.m4])
 m4_include([import/m4/readlink.m4])
 m4_include([import/m4/rename.m4])
 m4_include([import/m4/rmdir.m4])
diff --git a/gdb/gnulib/config.in b/gdb/gnulib/config.in
index 6061520f0a..b78df1a46f 100644
--- a/gdb/gnulib/config.in
+++ b/gdb/gnulib/config.in
@@ -92,6 +92,9 @@
 /* Define to 1 when the gnulib module chdir should be tested. */
 #undef GNULIB_TEST_CHDIR
 
+/* Define to 1 when the gnulib module closedir should be tested. */
+#undef GNULIB_TEST_CLOSEDIR
+
 /* Define to 1 when the gnulib module dirfd should be tested. */
 #undef GNULIB_TEST_DIRFD
 
@@ -104,6 +107,9 @@
 /* Define to 1 when the gnulib module frexpl should be tested. */
 #undef GNULIB_TEST_FREXPL
 
+/* Define to 1 when the gnulib module getlogin_r should be tested. */
+#undef GNULIB_TEST_GETLOGIN_R
+
 /* Define to 1 when the gnulib module gettimeofday should be tested. */
 #undef GNULIB_TEST_GETTIMEOFDAY
 
@@ -128,9 +134,18 @@
 /* Define to 1 when the gnulib module memmem should be tested. */
 #undef GNULIB_TEST_MEMMEM
 
+/* Define to 1 when the gnulib module mempcpy should be tested. */
+#undef GNULIB_TEST_MEMPCPY
+
+/* Define to 1 when the gnulib module opendir should be tested. */
+#undef GNULIB_TEST_OPENDIR
+
 /* Define to 1 when the gnulib module rawmemchr should be tested. */
 #undef GNULIB_TEST_RAWMEMCHR
 
+/* Define to 1 when the gnulib module readdir should be tested. */
+#undef GNULIB_TEST_READDIR
+
 /* Define to 1 when the gnulib module readlink should be tested. */
 #undef GNULIB_TEST_READLINK
 
@@ -178,6 +193,9 @@
 /* Define to 1 if you have the `canonicalize_file_name' function. */
 #undef HAVE_CANONICALIZE_FILE_NAME
 
+/* Define to 1 if you have the `closedir' function. */
+#undef HAVE_CLOSEDIR
+
 /* Define to 1 if you have the declaration of `alarm', and to 0 if you don't.
    */
 #undef HAVE_DECL_ALARM
@@ -190,6 +208,14 @@
    don't. */
 #undef HAVE_DECL_GETC_UNLOCKED
 
+/* Define to 1 if you have the declaration of `getlogin', and to 0 if you
+   don't. */
+#undef HAVE_DECL_GETLOGIN
+
+/* Define to 1 if you have the declaration of `getlogin_r', and to 0 if you
+   don't. */
+#undef HAVE_DECL_GETLOGIN_R
+
 /* Define to 1 if you have the declaration of `isblank', and to 0 if you
    don't. */
 #undef HAVE_DECL_ISBLANK
@@ -244,12 +270,24 @@
 /* Define if the frexpl() function is available. */
 #undef HAVE_FREXPL
 
+/* Define to 1 if you have the `fstatat' function. */
+#undef HAVE_FSTATAT
+
 /* Define to 1 if you have the `getcwd' function. */
 #undef HAVE_GETCWD
 
+/* Define to 1 if you have the `getlogin_r' function. */
+#undef HAVE_GETLOGIN_R
+
+/* Define to 1 if you have the `getpwnam_r' function. */
+#undef HAVE_GETPWNAM_R
+
 /* Define to 1 if you have the `gettimeofday' function. */
 #undef HAVE_GETTIMEOFDAY
 
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
@@ -317,6 +355,9 @@
 /* Define to 1 if you have the `mprotect' function. */
 #undef HAVE_MPROTECT
 
+/* Define to 1 if you have the `opendir' function. */
+#undef HAVE_OPENDIR
+
 /* Define to 1 if you have the `rawmemchr' function. */
 #undef HAVE_RAWMEMCHR
 
@@ -1137,6 +1178,9 @@
 /* Define to 1 if _Exit is declared even after undefining macros. */
 #undef HAVE_RAW_DECL__EXIT
 
+/* Define to 1 if you have the `readdir' function. */
+#undef HAVE_READDIR
+
 /* Define to 1 if you have the `readlink' function. */
 #undef HAVE_READLINK
 
@@ -1182,12 +1226,19 @@
 /* Define to 1 if you have the `strtok_r' function. */
 #undef HAVE_STRTOK_R
 
+/* Define if there is a member named d_type in the struct describing directory
+   headers. */
+#undef HAVE_STRUCT_DIRENT_D_TYPE
+
 /* Define to 1 if you have the `symlink' function. */
 #undef HAVE_SYMLINK
 
 /* Define to 1 if you have the <sys/bitypes.h> header file. */
 #undef HAVE_SYS_BITYPES_H
 
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#undef HAVE_SYS_CDEFS_H
+
 /* Define to 1 if you have the <sys/inttypes.h> header file. */
 #undef HAVE_SYS_INTTYPES_H
 
diff --git a/gdb/gnulib/configure b/gdb/gnulib/configure
index 2a0dfc2d66..7d72e22bbd 100644
--- a/gdb/gnulib/configure
+++ b/gdb/gnulib/configure
@@ -1078,6 +1078,10 @@ GL_GENERATE_LIMITS_H_TRUE
 LIMITS_H
 NEXT_AS_FIRST_DIRECTIVE_LIMITS_H
 NEXT_LIMITS_H
+HAVE_SYS_CDEFS_H
+GL_GENERATE_GLOB_H_FALSE
+GL_GENERATE_GLOB_H_TRUE
+GLOB_H
 HAVE_WINSOCK2_H
 NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H
 NEXT_SYS_TIME_H
@@ -1372,6 +1376,9 @@ PRAGMA_COLUMNS
 PRAGMA_SYSTEM_HEADER
 INCLUDE_NEXT_AS_FIRST_DIRECTIVE
 INCLUDE_NEXT
+pkglibexecdir
+runstatedir
+lispdir
 REPLACE_FDOPENDIR
 REPLACE_DIRFD
 REPLACE_CLOSEDIR
@@ -1393,9 +1400,6 @@ GNULIB_CLOSEDIR
 GNULIB_REWINDDIR
 GNULIB_READDIR
 GNULIB_OPENDIR
-pkglibexecdir
-runstatedir
-lispdir
 UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS
 UNISTD_H_HAVE_WINSOCK2_H
 REPLACE_WRITE
@@ -3318,9 +3322,13 @@ as_fn_append ac_func_list " wmemcpy"
 as_fn_append ac_func_list " wmempcpy"
 as_fn_append ac_header_list " wctype.h"
 gl_fnmatch_required=GNU
+as_fn_append ac_func_list " getlogin_r"
 as_fn_append ac_header_list " sys/time.h"
 as_fn_append ac_header_list " sys/socket.h"
 as_fn_append ac_func_list " gettimeofday"
+as_fn_append ac_header_list " sys/cdefs.h"
+as_fn_append ac_func_list " fstatat"
+as_fn_append ac_func_list " getpwnam_r"
 as_fn_append ac_header_list " limits.h"
 as_fn_append ac_header_list " wchar.h"
 as_fn_append ac_header_list " stdint.h"
@@ -5306,7 +5314,9 @@ fi
   # Code from module alloca-opt:
   # Code from module canonicalize-lgpl:
   # Code from module chdir:
+  # Code from module closedir:
   # Code from module configmake:
+  # Code from module d-type:
   # Code from module dirent:
   # Code from module dirfd:
   # Code from module dirname-lgpl:
@@ -5316,6 +5326,7 @@ fi
   # Code from module errno:
   # Code from module extensions:
   # Code from module extern-inline:
+  # Code from module filename:
   # Code from module flexmember:
   # Code from module float:
   # Code from module fnmatch:
@@ -5325,7 +5336,9 @@ fi
   # Code from module fpucw:
   # Code from module frexp:
   # Code from module frexpl:
+  # Code from module getlogin_r:
   # Code from module gettimeofday:
+  # Code from module glob:
   # Code from module hard-locale:
   # Code from module include_next:
   # Code from module inttypes:
@@ -5346,10 +5359,13 @@ fi
   # Code from module memchr:
   # Code from module memmem:
   # Code from module memmem-simple:
+  # Code from module mempcpy:
   # Code from module multiarch:
   # Code from module nocrash:
+  # Code from module opendir:
   # Code from module pathmax:
   # Code from module rawmemchr:
+  # Code from module readdir:
   # Code from module readlink:
   # Code from module rename:
   # Code from module rmdir:
@@ -7663,6 +7679,30 @@ $as_echo "#define HAVE_SAME_LONG_DOUBLE_AS_DOUBLE 1" >>confdefs.h
   fi
 
 
+ac_fn_c_check_decl "$LINENO" "getlogin_r" "ac_cv_have_decl_getlogin_r" "$ac_includes_default"
+if test "x$ac_cv_have_decl_getlogin_r" = x""yes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_GETLOGIN_R $ac_have_decl
+_ACEOF
+
+
+
+ac_fn_c_check_decl "$LINENO" "getlogin" "ac_cv_have_decl_getlogin" "$ac_includes_default"
+if test "x$ac_cv_have_decl_getlogin" = x""yes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_GETLOGIN $ac_have_decl
+_ACEOF
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
 $as_echo_n "checking for C/C++ restrict keyword... " >&6; }
 if test "${ac_cv_c_restrict+set}" = set; then :
@@ -7979,6 +8019,12 @@ fi
 
 
 
+
+
+
+
+
+
      if test $gl_cv_have_include_next = yes; then
        gl_cv_next_limits_h='<'limits.h'>'
      else
@@ -12669,6 +12715,56 @@ $as_echo "#define GNULIB_TEST_CHDIR 1" >>confdefs.h
 
 
 
+
+
+  for ac_func in closedir
+do :
+  ac_fn_c_check_func "$LINENO" "closedir" "ac_cv_func_closedir"
+if test "x$ac_cv_func_closedir" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CLOSEDIR 1
+_ACEOF
+
+fi
+done
+
+  if test $ac_cv_func_closedir = no; then
+    HAVE_CLOSEDIR=0
+  fi
+
+    case $host_os,$HAVE_CLOSEDIR in
+    os2*,1)
+      REPLACE_CLOSEDIR=1;;
+  esac
+
+  if test $HAVE_CLOSEDIR = 0 || test $REPLACE_CLOSEDIR = 1; then
+
+
+
+
+
+
+
+
+  gl_LIBOBJS="$gl_LIBOBJS closedir.$ac_objext"
+
+  fi
+
+
+
+
+
+          GNULIB_CLOSEDIR=1
+
+
+
+
+
+$as_echo "#define GNULIB_TEST_CLOSEDIR 1" >>confdefs.h
+
+
+
+
           if test "x$datarootdir" = x; then
     datarootdir='${datadir}'
 
@@ -12709,6 +12805,44 @@ $as_echo "#define GNULIB_TEST_CHDIR 1" >>confdefs.h
       pkglibexecdir='${libexecdir}/${PACKAGE}'
 
 
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for d_type member in directory struct" >&5
+$as_echo_n "checking for d_type member in directory struct... " >&6; }
+if test "${gl_cv_struct_dirent_d_type+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <dirent.h>
+
+int
+main ()
+{
+struct dirent dp; dp.d_type = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  gl_cv_struct_dirent_d_type=yes
+else
+  gl_cv_struct_dirent_d_type=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_struct_dirent_d_type" >&5
+$as_echo "$gl_cv_struct_dirent_d_type" >&6; }
+   if test $gl_cv_struct_dirent_d_type = yes; then
+
+$as_echo "#define HAVE_STRUCT_DIRENT_D_TYPE 1" >>confdefs.h
+
+   fi
+
+
 
 
 
@@ -13982,6 +14116,114 @@ $as_echo "#define GNULIB_TEST_FREXPL 1" >>confdefs.h
 
 
 
+  if test $ac_cv_have_decl_getlogin_r = no; then
+    HAVE_DECL_GETLOGIN_R=0
+  fi
+
+
+  if test $ac_cv_func_getlogin_r = no; then
+    HAVE_GETLOGIN_R=0
+  else
+    HAVE_GETLOGIN_R=1
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getlogin_r works with small buffers" >&5
+$as_echo_n "checking whether getlogin_r works with small buffers... " >&6; }
+if test "${gl_cv_func_getlogin_r_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+                case "$host_os" in
+                # Guess no on OSF/1.
+          osf*) gl_cv_func_getlogin_r_works="guessing no" ;;
+                # Guess yes otherwise.
+          *)    gl_cv_func_getlogin_r_works="guessing yes" ;;
+        esac
+        if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stddef.h>
+#include <unistd.h>
+#if !HAVE_DECL_GETLOGIN_R
+extern
+# ifdef __cplusplus
+"C"
+# endif
+int getlogin_r (char *, size_t);
+#endif
+int
+main (void)
+{
+  int result = 0;
+  char buf[100];
+
+  if (getlogin_r (buf, 0) == 0)
+    result |= 16;
+  if (getlogin_r (buf, 1) == 0)
+    result |= 17;
+  return result;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  gl_cv_func_getlogin_r_works=yes
+else
+  case $? in
+             16 | 17) gl_cv_func_getlogin_r_works=no ;;
+           esac
+
+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: $gl_cv_func_getlogin_r_works" >&5
+$as_echo "$gl_cv_func_getlogin_r_works" >&6; }
+    case "$gl_cv_func_getlogin_r_works" in
+      *yes) ;;
+      *) REPLACE_GETLOGIN_R=1 ;;
+    esac
+  fi
+
+  if test $HAVE_GETLOGIN_R = 0 || test $REPLACE_GETLOGIN_R = 1; then
+
+
+
+
+
+
+
+
+  gl_LIBOBJS="$gl_LIBOBJS getlogin_r.$ac_objext"
+
+
+
+
+  fi
+
+
+
+
+
+          GNULIB_GETLOGIN_R=1
+
+
+
+
+
+$as_echo "#define GNULIB_TEST_GETLOGIN_R 1" >>confdefs.h
+
+
+
+
+
+
+
+
+
   gl_gettimeofday_timezone=void
   if test $ac_cv_func_gettimeofday != yes; then
     HAVE_GETTIMEOFDAY=0
@@ -14177,6 +14419,131 @@ $as_echo "#define GNULIB_TEST_GETTIMEOFDAY 1" >>confdefs.h
 
 
 
+   GLOB_H=
+  for ac_header in glob.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default"
+if test "x$ac_cv_header_glob_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GLOB_H 1
+_ACEOF
+
+else
+  GLOB_H=glob.h
+fi
+
+done
+
+
+  if test -z "$GLOB_H"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU glob interface version 1" >&5
+$as_echo_n "checking for GNU glob interface version 1... " >&6; }
+if test "${gl_cv_gnu_glob_interface_version_1+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <gnu-versions.h>
+char a[_GNU_GLOB_INTERFACE_VERSION == 1 ? 1 : -1];
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  gl_cv_gnu_glob_interface_version_1=yes
+else
+  gl_cv_gnu_glob_interface_version_1=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_gnu_glob_interface_version_1" >&5
+$as_echo "$gl_cv_gnu_glob_interface_version_1" >&6; }
+
+    if test "$gl_cv_gnu_glob_interface_version_1" = "no"; then
+      GLOB_H=glob.h
+    fi
+  fi
+
+  if test -z "$GLOB_H"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether glob lists broken symlinks" >&5
+$as_echo_n "checking whether glob lists broken symlinks... " >&6; }
+if test "${gl_cv_glob_lists_symlinks+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+       if ln -s conf-doesntexist conf$$-globtest 2>/dev/null; then
+        gl_cv_glob_lists_symlinks=maybe
+      else
+        # If we can't make a symlink, then we cannot test this issue.  Be
+        # pessimistic about this.
+        gl_cv_glob_lists_symlinks=no
+      fi
+
+      if test $gl_cv_glob_lists_symlinks = maybe; then
+        if test "$cross_compiling" = yes; then :
+  gl_cv_glob_lists_symlinks=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stddef.h>
+#include <glob.h>
+int
+main ()
+{
+glob_t found;
+if (glob ("conf*-globtest", 0, NULL, &found) == GLOB_NOMATCH) return 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  gl_cv_glob_lists_symlinks=yes
+else
+  gl_cv_glob_lists_symlinks=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
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_glob_lists_symlinks" >&5
+$as_echo "$gl_cv_glob_lists_symlinks" >&6; }
+
+    if test $gl_cv_glob_lists_symlinks = no; then
+      GLOB_H=glob.h
+    fi
+  fi
+
+  rm -f conf$$-globtest
+
+
+   if test -n "$GLOB_H"; then
+  GL_GENERATE_GLOB_H_TRUE=
+  GL_GENERATE_GLOB_H_FALSE='#'
+else
+  GL_GENERATE_GLOB_H_TRUE='#'
+  GL_GENERATE_GLOB_H_FALSE=
+fi
+
+
+  if test -n "$GLOB_H"; then
+
+
+
+
+
+
+
+
+  gl_LIBOBJS="$gl_LIBOBJS glob.$ac_objext"
+
+
+          if test $ac_cv_header_sys_cdefs_h = yes; then
+    HAVE_SYS_CDEFS_H=1
+  else
+    HAVE_SYS_CDEFS_H=0
+  fi
+
+
+  fi
 
   :
 
@@ -16665,6 +17032,107 @@ $as_echo "#define GNULIB_TEST_MEMMEM 1" >>confdefs.h
 
 
 
+  for ac_func in mempcpy
+do :
+  ac_fn_c_check_func "$LINENO" "mempcpy" "ac_cv_func_mempcpy"
+if test "x$ac_cv_func_mempcpy" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MEMPCPY 1
+_ACEOF
+
+fi
+done
+
+  if test $ac_cv_func_mempcpy = no; then
+    HAVE_MEMPCPY=0
+  fi
+
+  if test $HAVE_MEMPCPY = 0; then
+
+
+
+
+
+
+
+
+  gl_LIBOBJS="$gl_LIBOBJS mempcpy.$ac_objext"
+
+
+  :
+
+  fi
+
+
+
+
+
+          GNULIB_MEMPCPY=1
+
+
+
+
+
+$as_echo "#define GNULIB_TEST_MEMPCPY 1" >>confdefs.h
+
+
+
+
+
+
+
+  for ac_func in opendir
+do :
+  ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir"
+if test "x$ac_cv_func_opendir" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENDIR 1
+_ACEOF
+
+fi
+done
+
+  if test $ac_cv_func_opendir = no; then
+    HAVE_OPENDIR=0
+  fi
+
+      case $host_os,$HAVE_OPENDIR in
+    os2*,1)
+      REPLACE_OPENDIR=1;;
+  esac
+
+  if test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1; then
+
+
+
+
+
+
+
+
+  gl_LIBOBJS="$gl_LIBOBJS opendir.$ac_objext"
+
+  fi
+
+
+
+
+
+          GNULIB_OPENDIR=1
+
+
+
+
+
+$as_echo "#define GNULIB_TEST_OPENDIR 1" >>confdefs.h
+
+
+
+
+
+
+
+
 
 
   for ac_func in rawmemchr
@@ -16713,6 +17181,51 @@ $as_echo "#define GNULIB_TEST_RAWMEMCHR 1" >>confdefs.h
 
 
 
+  for ac_func in readdir
+do :
+  ac_fn_c_check_func "$LINENO" "readdir" "ac_cv_func_readdir"
+if test "x$ac_cv_func_readdir" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_READDIR 1
+_ACEOF
+
+fi
+done
+
+  if test $ac_cv_func_readdir = no; then
+    HAVE_READDIR=0
+  fi
+
+  if test $HAVE_READDIR = 0; then
+
+
+
+
+
+
+
+
+  gl_LIBOBJS="$gl_LIBOBJS readdir.$ac_objext"
+
+  fi
+
+
+
+
+
+          GNULIB_READDIR=1
+
+
+
+
+
+$as_echo "#define GNULIB_TEST_READDIR 1" >>confdefs.h
+
+
+
+
+
+
   if test $ac_cv_func_readlink = no; then
     HAVE_READLINK=0
   else
@@ -20526,6 +21039,10 @@ if test -z "${GL_GENERATE_FNMATCH_H_TRUE}" && test -z "${GL_GENERATE_FNMATCH_H_F
   as_fn_error "conditional \"GL_GENERATE_FNMATCH_H\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${GL_GENERATE_GLOB_H_TRUE}" && test -z "${GL_GENERATE_GLOB_H_FALSE}"; then
+  as_fn_error "conditional \"GL_GENERATE_GLOB_H\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${GL_GENERATE_LIMITS_H_TRUE}" && test -z "${GL_GENERATE_LIMITS_H_FALSE}"; then
   as_fn_error "conditional \"GL_GENERATE_LIMITS_H\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/gdb/gnulib/import/Makefile.am b/gdb/gnulib/import/Makefile.am
index 26f249d16a..defa7b34ca 100644
--- a/gdb/gnulib/import/Makefile.am
+++ b/gdb/gnulib/import/Makefile.am
@@ -21,7 +21,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=import --m4-base=import/m4 --doc-base=doc --tests-base=tests --aux-dir=import/extra --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca canonicalize-lgpl dirent dirfd errno fnmatch-gnu frexpl inttypes limits-h lstat memchr memmem pathmax rawmemchr readlink rename setenv signal-h strchrnul strstr strtok_r sys_stat unistd unsetenv update-copyright wchar wctype-h
+# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=import --m4-base=import/m4 --doc-base=doc --tests-base=tests --aux-dir=import/extra --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca canonicalize-lgpl dirent dirfd errno fnmatch-gnu frexpl glob inttypes limits-h lstat memchr memmem pathmax rawmemchr readlink rename setenv signal-h strchrnul strstr strtok_r sys_stat unistd unsetenv update-copyright wchar wctype-h
 
 AUTOMAKE_OPTIONS = 1.9.6 gnits
 
@@ -101,6 +101,15 @@ EXTRA_libgnu_a_SOURCES += canonicalize-lgpl.c
 
 ## end   gnulib module canonicalize-lgpl
 
+## begin gnulib module closedir
+
+
+EXTRA_DIST += closedir.c dirent-private.h
+
+EXTRA_libgnu_a_SOURCES += closedir.c
+
+## end   gnulib module closedir
+
 ## begin gnulib module configmake
 
 # Listed in the same order as the GNU makefile conventions, and
@@ -252,6 +261,13 @@ EXTRA_DIST += errno.in.h
 
 ## end   gnulib module errno
 
+## begin gnulib module filename
+
+
+EXTRA_DIST += filename.h
+
+## end   gnulib module filename
+
 ## begin gnulib module flexmember
 
 
@@ -341,6 +357,15 @@ EXTRA_libgnu_a_SOURCES += frexp.c frexpl.c
 
 ## end   gnulib module frexpl
 
+## begin gnulib module getlogin_r
+
+
+EXTRA_DIST += getlogin_r.c
+
+EXTRA_libgnu_a_SOURCES += getlogin_r.c
+
+## end   gnulib module getlogin_r
+
 ## begin gnulib module gettimeofday
 
 
@@ -350,6 +375,35 @@ EXTRA_libgnu_a_SOURCES += gettimeofday.c
 
 ## end   gnulib module gettimeofday
 
+## begin gnulib module glob
+
+BUILT_SOURCES += $(GLOB_H)
+
+# We need the following in order to create <glob.h> when the system
+# doesn't have one that works with the given compiler.
+if GL_GENERATE_GLOB_H
+glob.h: glob.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/glob.in.h; \
+	} > $@-t && \
+	mv -f $@-t $@
+else
+glob.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += glob.h glob.h-t
+
+EXTRA_DIST += glob-libc.h glob.c glob.in.h
+
+EXTRA_libgnu_a_SOURCES += glob.c
+
+## end   gnulib module glob
+
 ## begin gnulib module hard-locale
 
 libgnu_a_SOURCES += hard-locale.c
@@ -878,6 +932,24 @@ EXTRA_libgnu_a_SOURCES += memmem.c
 
 ## end   gnulib module memmem-simple
 
+## begin gnulib module mempcpy
+
+
+EXTRA_DIST += mempcpy.c
+
+EXTRA_libgnu_a_SOURCES += mempcpy.c
+
+## end   gnulib module mempcpy
+
+## begin gnulib module opendir
+
+
+EXTRA_DIST += dirent-private.h opendir.c
+
+EXTRA_libgnu_a_SOURCES += opendir.c
+
+## end   gnulib module opendir
+
 ## begin gnulib module pathmax
 
 
@@ -894,6 +966,15 @@ EXTRA_libgnu_a_SOURCES += rawmemchr.c
 
 ## end   gnulib module rawmemchr
 
+## begin gnulib module readdir
+
+
+EXTRA_DIST += dirent-private.h readdir.c
+
+EXTRA_libgnu_a_SOURCES += readdir.c
+
+## end   gnulib module readdir
+
 ## begin gnulib module readlink
 
 
diff --git a/gdb/gnulib/import/Makefile.in b/gdb/gnulib/import/Makefile.in
index ca7a73d970..d02fcfb9f9 100644
--- a/gdb/gnulib/import/Makefile.in
+++ b/gdb/gnulib/import/Makefile.in
@@ -36,7 +36,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=import --m4-base=import/m4 --doc-base=doc --tests-base=tests --aux-dir=import/extra --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca canonicalize-lgpl dirent dirfd errno fnmatch-gnu frexpl inttypes limits-h lstat memchr memmem pathmax rawmemchr readlink rename setenv signal-h strchrnul strstr strtok_r sys_stat unistd unsetenv update-copyright wchar wctype-h
+# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=import --m4-base=import/m4 --doc-base=doc --tests-base=tests --aux-dir=import/extra --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca canonicalize-lgpl dirent dirfd errno fnmatch-gnu frexpl glob inttypes limits-h lstat memchr memmem pathmax rawmemchr readlink rename setenv signal-h strchrnul strstr strtok_r sys_stat unistd unsetenv update-copyright wchar wctype-h
 
 
 
@@ -67,8 +67,10 @@ am__aclocal_m4_deps = $(top_srcdir)/import/m4/00gnulib.m4 \
 	$(top_srcdir)/import/m4/absolute-header.m4 \
 	$(top_srcdir)/import/m4/alloca.m4 \
 	$(top_srcdir)/import/m4/canonicalize.m4 \
+	$(top_srcdir)/import/m4/closedir.m4 \
 	$(top_srcdir)/import/m4/codeset.m4 \
 	$(top_srcdir)/import/m4/configmake.m4 \
+	$(top_srcdir)/import/m4/d-type.m4 \
 	$(top_srcdir)/import/m4/dirent_h.m4 \
 	$(top_srcdir)/import/m4/dirfd.m4 \
 	$(top_srcdir)/import/m4/dirname.m4 \
@@ -87,8 +89,10 @@ am__aclocal_m4_deps = $(top_srcdir)/import/m4/00gnulib.m4 \
 	$(top_srcdir)/import/m4/fpieee.m4 \
 	$(top_srcdir)/import/m4/frexp.m4 \
 	$(top_srcdir)/import/m4/frexpl.m4 \
+	$(top_srcdir)/import/m4/getlogin_r.m4 \
 	$(top_srcdir)/import/m4/gettimeofday.m4 \
 	$(top_srcdir)/import/m4/glibc21.m4 \
+	$(top_srcdir)/import/m4/glob.m4 \
 	$(top_srcdir)/import/m4/gnulib-common.m4 \
 	$(top_srcdir)/import/m4/gnulib-comp.m4 \
 	$(top_srcdir)/import/m4/hard-locale.m4 \
@@ -114,12 +118,15 @@ am__aclocal_m4_deps = $(top_srcdir)/import/m4/00gnulib.m4 \
 	$(top_srcdir)/import/m4/mbstate_t.m4 \
 	$(top_srcdir)/import/m4/memchr.m4 \
 	$(top_srcdir)/import/m4/memmem.m4 \
+	$(top_srcdir)/import/m4/mempcpy.m4 \
 	$(top_srcdir)/import/m4/mmap-anon.m4 \
 	$(top_srcdir)/import/m4/multiarch.m4 \
 	$(top_srcdir)/import/m4/nocrash.m4 \
 	$(top_srcdir)/import/m4/off_t.m4 \
+	$(top_srcdir)/import/m4/opendir.m4 \
 	$(top_srcdir)/import/m4/pathmax.m4 \
 	$(top_srcdir)/import/m4/rawmemchr.m4 \
+	$(top_srcdir)/import/m4/readdir.m4 \
 	$(top_srcdir)/import/m4/readlink.m4 \
 	$(top_srcdir)/import/m4/rename.m4 \
 	$(top_srcdir)/import/m4/rmdir.m4 \
@@ -256,6 +263,7 @@ FNMATCH_H = @FNMATCH_H@
 FREXPL_LIBM = @FREXPL_LIBM@
 FREXP_LIBM = @FREXP_LIBM@
 GLIBC21 = @GLIBC21@
+GLOB_H = @GLOB_H@
 GNULIB_ACOSF = @GNULIB_ACOSF@
 GNULIB_ACOSL = @GNULIB_ACOSL@
 GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
@@ -856,6 +864,7 @@ HAVE_STRVERSCMP = @HAVE_STRVERSCMP@
 HAVE_SYMLINK = @HAVE_SYMLINK@
 HAVE_SYMLINKAT = @HAVE_SYMLINKAT@
 HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
+HAVE_SYS_CDEFS_H = @HAVE_SYS_CDEFS_H@
 HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
 HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
 HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
@@ -1281,17 +1290,20 @@ noinst_HEADERS =
 noinst_LIBRARIES = libgnu.a
 noinst_LTLIBRARIES = 
 EXTRA_DIST = m4/gnulib-cache.m4 alloca.c alloca.in.h \
-	canonicalize-lgpl.c dirent.in.h dirfd.c dirname.h dosname.h \
-	errno.in.h flexmember.h float.c float.in.h itold.c fnmatch.c \
-	fnmatch.in.h fnmatch_loop.c fpucw.h frexp.c frexp.c frexpl.c \
-	gettimeofday.c hard-locale.h inttypes.in.h float+.h isnan.c \
-	isnand-nolibm.h isnand.c float+.h isnan.c isnanl-nolibm.h \
-	isnanl.c limits.in.h config.charset ref-add.sin ref-del.sin \
-	lstat.c malloc.c malloca.h malloca.valgrind math.in.h \
-	mbrtowc.c mbsinit.c mbsrtowcs-impl.h mbsrtowcs-state.c \
-	mbsrtowcs.c memchr.c memchr.valgrind memmem.c str-two-way.h \
-	pathmax.h rawmemchr.c rawmemchr.valgrind readlink.c rename.c \
-	rmdir.c same-inode.h setenv.c signal.in.h \
+	canonicalize-lgpl.c closedir.c dirent-private.h dirent.in.h \
+	dirfd.c dirname.h dosname.h errno.in.h filename.h flexmember.h \
+	float.c float.in.h itold.c fnmatch.c fnmatch.in.h \
+	fnmatch_loop.c fpucw.h frexp.c frexp.c frexpl.c getlogin_r.c \
+	gettimeofday.c glob-libc.h glob.c glob.in.h hard-locale.h \
+	inttypes.in.h float+.h isnan.c isnand-nolibm.h isnand.c \
+	float+.h isnan.c isnanl-nolibm.h isnanl.c limits.in.h \
+	config.charset ref-add.sin ref-del.sin lstat.c malloc.c \
+	malloca.h malloca.valgrind math.in.h mbrtowc.c mbsinit.c \
+	mbsrtowcs-impl.h mbsrtowcs-state.c mbsrtowcs.c memchr.c \
+	memchr.valgrind memmem.c str-two-way.h mempcpy.c \
+	dirent-private.h opendir.c pathmax.h rawmemchr.c \
+	rawmemchr.valgrind dirent-private.h readdir.c readlink.c \
+	rename.c rmdir.c same-inode.h setenv.c signal.in.h \
 	$(top_srcdir)/import/extra/snippet/_Noreturn.h \
 	$(top_srcdir)/import/extra/snippet/arg-nonnull.h \
 	$(top_srcdir)/import/extra/snippet/c++defs.h \
@@ -1313,21 +1325,22 @@ EXTRA_DIST = m4/gnulib-cache.m4 alloca.c alloca.in.h \
 # present in all Makefile.am that need it. This is ensured by the applicability
 # 'all' defined above.
 BUILT_SOURCES = $(ALLOCA_H) configmake.h dirent.h $(ERRNO_H) \
-	$(FLOAT_H) $(FNMATCH_H) inttypes.h $(LIMITS_H) math.h signal.h \
-	arg-nonnull.h c++defs.h warn-on-use.h $(STDBOOL_H) $(STDDEF_H) \
-	$(STDINT_H) stdio.h stdlib.h string.h sys/stat.h sys/time.h \
-	sys/types.h time.h unistd.h wchar.h wctype.h
+	$(FLOAT_H) $(FNMATCH_H) $(GLOB_H) inttypes.h $(LIMITS_H) \
+	math.h signal.h arg-nonnull.h c++defs.h warn-on-use.h \
+	$(STDBOOL_H) $(STDDEF_H) $(STDINT_H) stdio.h stdlib.h string.h \
+	sys/stat.h sys/time.h sys/types.h time.h unistd.h wchar.h \
+	wctype.h
 SUFFIXES = .sed .sin
 MOSTLYCLEANFILES = core *.stackdump alloca.h alloca.h-t dirent.h \
 	dirent.h-t errno.h errno.h-t float.h float.h-t fnmatch.h \
-	fnmatch.h-t inttypes.h inttypes.h-t limits.h limits.h-t math.h \
-	math.h-t signal.h signal.h-t arg-nonnull.h arg-nonnull.h-t \
-	c++defs.h c++defs.h-t warn-on-use.h warn-on-use.h-t stdbool.h \
-	stdbool.h-t stddef.h stddef.h-t stdint.h stdint.h-t stdio.h \
-	stdio.h-t stdlib.h stdlib.h-t string.h string.h-t sys/stat.h \
-	sys/stat.h-t sys/time.h sys/time.h-t sys/types.h sys/types.h-t \
-	time.h time.h-t unistd.h unistd.h-t wchar.h wchar.h-t wctype.h \
-	wctype.h-t
+	fnmatch.h-t glob.h glob.h-t inttypes.h inttypes.h-t limits.h \
+	limits.h-t math.h math.h-t signal.h signal.h-t arg-nonnull.h \
+	arg-nonnull.h-t c++defs.h c++defs.h-t warn-on-use.h \
+	warn-on-use.h-t stdbool.h stdbool.h-t stddef.h stddef.h-t \
+	stdint.h stdint.h-t stdio.h stdio.h-t stdlib.h stdlib.h-t \
+	string.h string.h-t sys/stat.h sys/stat.h-t sys/time.h \
+	sys/time.h-t sys/types.h sys/types.h-t time.h time.h-t \
+	unistd.h unistd.h-t wchar.h wchar.h-t wctype.h wctype.h-t
 MOSTLYCLEANDIRS = sys
 CLEANFILES = configmake.h configmake.h-t charset.alias ref-add.sed \
 	ref-del.sed
@@ -1340,11 +1353,12 @@ libgnu_a_SOURCES = dirname-lgpl.c basename-lgpl.c stripslash.c \
 	strnlen1.h strnlen1.c unistd.c wctype-h.c
 libgnu_a_LIBADD = $(gl_LIBOBJS) @ALLOCA@
 libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) @ALLOCA@
-EXTRA_libgnu_a_SOURCES = alloca.c canonicalize-lgpl.c dirfd.c float.c \
-	itold.c fnmatch.c fnmatch_loop.c frexp.c frexp.c frexpl.c \
-	gettimeofday.c isnan.c isnand.c isnan.c isnanl.c lstat.c \
-	malloc.c mbrtowc.c mbsinit.c mbsrtowcs-state.c mbsrtowcs.c \
-	memchr.c memmem.c rawmemchr.c readlink.c rename.c rmdir.c \
+EXTRA_libgnu_a_SOURCES = alloca.c canonicalize-lgpl.c closedir.c \
+	dirfd.c float.c itold.c fnmatch.c fnmatch_loop.c frexp.c \
+	frexp.c frexpl.c getlogin_r.c gettimeofday.c glob.c isnan.c \
+	isnand.c isnan.c isnanl.c lstat.c malloc.c mbrtowc.c mbsinit.c \
+	mbsrtowcs-state.c mbsrtowcs.c memchr.c memmem.c mempcpy.c \
+	opendir.c rawmemchr.c readdir.c readlink.c rename.c rmdir.c \
 	setenv.c stat.c strchrnul.c strstr.c strtok_r.c unsetenv.c
 
 # Use this preprocessor expression to decide whether #include_next works.
@@ -1423,6 +1437,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloca.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basename-lgpl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canonicalize-lgpl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/closedir.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirfd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirname-lgpl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/float.Po@am__quote@
@@ -1430,7 +1445,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch_loop.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frexp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frexpl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getlogin_r.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glob.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hard-locale.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isnan.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isnand.Po@am__quote@
@@ -1447,7 +1464,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbsrtowcs.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memchr.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memmem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mempcpy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opendir.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rawmemchr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readlink.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rename.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rmdir.Po@am__quote@
@@ -1936,6 +1956,21 @@ dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 @GL_GENERATE_FNMATCH_H_FALSE@fnmatch.h: $(top_builddir)/config.status
 @GL_GENERATE_FNMATCH_H_FALSE@	rm -f $@
 
+# We need the following in order to create <glob.h> when the system
+# doesn't have one that works with the given compiler.
+@GL_GENERATE_GLOB_H_TRUE@glob.h: glob.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+@GL_GENERATE_GLOB_H_TRUE@	$(AM_V_GEN)rm -f $@-t $@ && \
+@GL_GENERATE_GLOB_H_TRUE@	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+@GL_GENERATE_GLOB_H_TRUE@	  sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \
+@GL_GENERATE_GLOB_H_TRUE@	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+@GL_GENERATE_GLOB_H_TRUE@	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+@GL_GENERATE_GLOB_H_TRUE@	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+@GL_GENERATE_GLOB_H_TRUE@	      < $(srcdir)/glob.in.h; \
+@GL_GENERATE_GLOB_H_TRUE@	} > $@-t && \
+@GL_GENERATE_GLOB_H_TRUE@	mv -f $@-t $@
+@GL_GENERATE_GLOB_H_FALSE@glob.h: $(top_builddir)/config.status
+@GL_GENERATE_GLOB_H_FALSE@	rm -f $@
+
 # We need the following in order to create <inttypes.h> when the system
 # doesn't have one that works with the given compiler.
 inttypes.h: inttypes.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H)
diff --git a/gdb/gnulib/import/closedir.c b/gdb/gnulib/import/closedir.c
new file mode 100644
index 0000000000..30d1290351
--- /dev/null
+++ b/gdb/gnulib/import/closedir.c
@@ -0,0 +1,71 @@
+/* Stop reading the entries of a directory.
+   Copyright (C) 2006-2016 Free Software Foundation, Inc.
+
+   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 <config.h>
+
+/* Specification.  */
+#include <dirent.h>
+
+#if REPLACE_FCHDIR
+# include <unistd.h>
+#endif
+
+#if HAVE_CLOSEDIR
+
+/* Override closedir(), to keep track of the open file descriptors.
+   Needed because there is a function dirfd().  */
+
+#else
+
+# include <stdlib.h>
+
+# include "dirent-private.h"
+
+#endif
+
+int
+closedir (DIR *dirp)
+{
+# if REPLACE_FCHDIR || REPLACE_DIRFD
+  int fd = dirfd (dirp);
+# endif
+  int retval;
+
+#if HAVE_CLOSEDIR
+# undef closedir
+
+  retval = closedir (dirp);
+
+# ifdef __KLIBC__
+  if (!retval)
+    _gl_unregister_dirp_fd (fd);
+# endif
+#else
+
+  if (dirp->current != INVALID_HANDLE_VALUE)
+    FindClose (dirp->current);
+  free (dirp);
+
+  retval = 0;
+
+#endif
+
+#if REPLACE_FCHDIR
+  if (retval >= 0)
+    _gl_unregister_fd (fd);
+#endif
+  return retval;
+}
diff --git a/gdb/gnulib/import/dirent-private.h b/gdb/gnulib/import/dirent-private.h
new file mode 100644
index 0000000000..9b200f30da
--- /dev/null
+++ b/gdb/gnulib/import/dirent-private.h
@@ -0,0 +1,40 @@
+/* Private details of the DIR type.
+   Copyright (C) 2011-2016 Free Software Foundation, Inc.
+
+   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 _DIRENT_PRIVATE_H
+#define _DIRENT_PRIVATE_H 1
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+struct gl_directory
+{
+  /* Status, or error code to produce in next readdir() call.
+     -2 means the end of the directory is already reached,
+     -1 means the entry was already filled by FindFirstFile,
+     0 means the entry needs to be filled using FindNextFile.
+     A positive value is an error code.  */
+  int status;
+  /* Handle, reading the directory, at current position.  */
+  HANDLE current;
+  /* Found directory entry.  */
+  WIN32_FIND_DATA entry;
+  /* Argument to pass to FindFirstFile.  It consists of the absolutized
+     directory name, followed by a directory separator and the wildcards.  */
+  char dir_name_mask[1];
+};
+
+#endif /* _DIRENT_PRIVATE_H */
diff --git a/gdb/gnulib/import/filename.h b/gdb/gnulib/import/filename.h
new file mode 100644
index 0000000000..7d2c31a8c3
--- /dev/null
+++ b/gdb/gnulib/import/filename.h
@@ -0,0 +1,54 @@
+/* Basic filename support macros.
+   Copyright (C) 2001-2004, 2007-2016 Free Software Foundation, Inc.
+
+   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 _FILENAME_H
+#define _FILENAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Pathname support.
+   ISSLASH(C)           tests whether C is a directory separator character.
+   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
+                        it may be concatenated to a directory pathname.
+   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+  /* Native Windows, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+     && (P)[1] == ':')
+# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
+# define IS_PATH_WITH_DIR(P) \
+    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
+#else
+  /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+# define FILE_SYSTEM_PREFIX_LEN(P) 0
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FILENAME_H */
diff --git a/gdb/gnulib/import/getlogin_r.c b/gdb/gnulib/import/getlogin_r.c
new file mode 100644
index 0000000000..2bafb55fb1
--- /dev/null
+++ b/gdb/gnulib/import/getlogin_r.c
@@ -0,0 +1,87 @@
+/* Provide a working getlogin_r for systems which lack it.
+
+   Copyright (C) 2005-2007, 2010-2016 Free Software Foundation, Inc.
+
+   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, 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/>.  */
+
+/* Written by Paul Eggert, Derek Price, and Bruno Haible.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+#include <string.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#else
+# if !HAVE_DECL_GETLOGIN
+extern char *getlogin (void);
+# endif
+#endif
+
+/* See unistd.in.h for documentation.  */
+int
+getlogin_r (char *name, size_t size)
+{
+#undef getlogin_r
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* Native Windows platform.  */
+  DWORD sz;
+
+  /* When size > 0x7fff, the doc says that GetUserName will fail.
+     Actually, on Windows XP SP3, it succeeds.  But let's be safe,
+     for the sake of older Windows versions.  */
+  if (size > 0x7fff)
+    size = 0x7fff;
+  sz = size;
+  if (!GetUserName (name, &sz))
+    {
+      if (GetLastError () == ERROR_INSUFFICIENT_BUFFER)
+        /* In this case, the doc says that sz contains the required size, but
+           actually, on Windows XP SP3, it contains 2 * the required size.  */
+        return ERANGE;
+      else
+        return ENOENT;
+    }
+  return 0;
+#elif HAVE_GETLOGIN_R
+  /* Platform with a getlogin_r() function.  */
+  int ret = getlogin_r (name, size);
+
+  if (ret == 0 && memchr (name, '\0', size) == NULL)
+    /* name contains a truncated result.  */
+    return ERANGE;
+  return ret;
+#else
+  /* Platform with a getlogin() function.  */
+  char *n;
+  size_t nlen;
+
+  errno = 0;
+  n = getlogin ();
+  if (!n)
+    /* ENOENT is a reasonable errno value if getlogin returns NULL.  */
+    return (errno != 0 ? errno : ENOENT);
+
+  nlen = strlen (n);
+  if (size <= nlen)
+    return ERANGE;
+  memcpy (name, n, nlen + 1);
+  return 0;
+#endif
+}
diff --git a/gdb/gnulib/import/glob-libc.h b/gdb/gnulib/import/glob-libc.h
new file mode 100644
index 0000000000..6256077f70
--- /dev/null
+++ b/gdb/gnulib/import/glob-libc.h
@@ -0,0 +1,212 @@
+/* Copyright (C) 1991-1992, 1995-1998, 2000-2001, 2004-2007, 2009-2016 Free
+   Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 _GLOB_H
+#define _GLOB_H 1
+
+#ifndef __GLOB_GNULIB
+# include <sys/cdefs.h>
+#endif
+
+/* GCC 2.95 and later have "__restrict"; C99 compilers have
+   "restrict", and "configure" may have defined "restrict".
+   Other compilers use __restrict, __restrict__, and _Restrict, and
+   'configure' might #define 'restrict' to those words, so pick a
+   different name.  */
+#ifndef _Restrict_
+# if 199901L <= __STDC_VERSION__
+#  define _Restrict_ restrict
+# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)
+#  define _Restrict_ __restrict
+# else
+#  define _Restrict_
+# endif
+#endif
+
+__BEGIN_DECLS
+
+/* We need 'size_t' for the following definitions.  */
+#ifndef __size_t
+# if defined __GNUC__ && __GNUC__ >= 2
+typedef __SIZE_TYPE__ __size_t;
+#  ifdef __USE_XOPEN
+typedef __SIZE_TYPE__ size_t;
+#  endif
+# else
+#  include <stddef.h>
+#  ifndef __size_t
+#   define __size_t size_t
+#  endif
+# endif
+#else
+/* The GNU CC stddef.h version defines __size_t as empty.  We need a real
+   definition.  */
+# undef __size_t
+# define __size_t size_t
+#endif
+
+/* Bits set in the FLAGS argument to 'glob'.  */
+#define GLOB_ERR        (1 << 0)/* Return on read errors.  */
+#define GLOB_MARK       (1 << 1)/* Append a slash to each name.  */
+#define GLOB_NOSORT     (1 << 2)/* Don't sort the names.  */
+#define GLOB_DOOFFS     (1 << 3)/* Insert PGLOB->gl_offs NULLs.  */
+#define GLOB_NOCHECK    (1 << 4)/* If nothing matches, return the pattern.  */
+#define GLOB_APPEND     (1 << 5)/* Append to results of a previous call.  */
+#define GLOB_NOESCAPE   (1 << 6)/* Backslashes don't quote metacharacters.  */
+#define GLOB_PERIOD     (1 << 7)/* Leading '.' can be matched by metachars.  */
+
+#if !defined __USE_POSIX2 || defined __USE_BSD || defined __USE_GNU
+# define GLOB_MAGCHAR    (1 << 8)/* Set in gl_flags if any metachars seen.  */
+# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions.  */
+# define GLOB_BRACE      (1 << 10)/* Expand "{a,b}" to "a" "b".  */
+# define GLOB_NOMAGIC    (1 << 11)/* If no magic chars, return the pattern.  */
+# define GLOB_TILDE      (1 << 12)/* Expand ~user and ~ to home directories. */
+# define GLOB_ONLYDIR    (1 << 13)/* Match only directories.  */
+# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error
+                                      if the user name is not available.  */
+# define __GLOB_FLAGS   (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+                         GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
+                         GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \
+                         GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)
+#else
+# define __GLOB_FLAGS   (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+                         GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \
+                         GLOB_PERIOD)
+#endif
+
+/* Error returns from 'glob'.  */
+#define GLOB_NOSPACE    1       /* Ran out of memory.  */
+#define GLOB_ABORTED    2       /* Read error.  */
+#define GLOB_NOMATCH    3       /* No matches found.  */
+#define GLOB_NOSYS      4       /* Not implemented.  */
+#ifdef __USE_GNU
+/* Previous versions of this file defined GLOB_ABEND instead of
+   GLOB_ABORTED.  Provide a compatibility definition here.  */
+# define GLOB_ABEND GLOB_ABORTED
+#endif
+
+/* Structure describing a globbing run.  */
+#ifdef __USE_GNU
+struct stat;
+#endif
+typedef struct
+  {
+    __size_t gl_pathc;          /* Count of paths matched by the pattern.  */
+    char **gl_pathv;            /* List of matched pathnames.  */
+    __size_t gl_offs;           /* Slots to reserve in 'gl_pathv'.  */
+    int gl_flags;               /* Set to FLAGS, maybe | GLOB_MAGCHAR.  */
+
+    /* If the GLOB_ALTDIRFUNC flag is set, the following functions
+       are used instead of the normal file access functions.  */
+    void (*gl_closedir) (void *);
+#ifdef __USE_GNU
+    struct dirent *(*gl_readdir) (void *);
+#else
+    void *(*gl_readdir) (void *);
+#endif
+    void *(*gl_opendir) (const char *);
+#ifdef __USE_GNU
+    int (*gl_lstat) (const char *_Restrict_, struct stat *_Restrict_);
+    int (*gl_stat) (const char *_Restrict_, struct stat *_Restrict_);
+#else
+    int (*gl_lstat) (const char *_Restrict_, void *_Restrict_);
+    int (*gl_stat) (const char *_Restrict_, void *_Restrict_);
+#endif
+  } glob_t;
+
+#if defined __USE_LARGEFILE64 && !defined __GLOB_GNULIB
+# ifdef __USE_GNU
+struct stat64;
+# endif
+typedef struct
+  {
+    __size_t gl_pathc;
+    char **gl_pathv;
+    __size_t gl_offs;
+    int gl_flags;
+
+    /* If the GLOB_ALTDIRFUNC flag is set, the following functions
+       are used instead of the normal file access functions.  */
+    void (*gl_closedir) (void *);
+# ifdef __USE_GNU
+    struct dirent64 *(*gl_readdir) (void *);
+# else
+    void *(*gl_readdir) (void *);
+# endif
+    void *(*gl_opendir) (const char *);
+# ifdef __USE_GNU
+    int (*gl_lstat) (const char *_Restrict_, struct stat64 *_Restrict_);
+    int (*gl_stat) (const char *_Restrict_, struct stat64 *_Restrict_);
+# else
+    int (*gl_lstat) (const char *_Restrict_, void *_Restrict_);
+    int (*gl_stat) (const char *_Restrict_, void *_Restrict_);
+# endif
+  } glob64_t;
+#endif
+
+#if __USE_FILE_OFFSET64 && __GNUC__ < 2 && !defined __GLOB_GNULIB
+# define glob glob64
+# define globfree globfree64
+#endif
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+   The bits defined above may be set in FLAGS.
+   If a directory cannot be opened or read and ERRFUNC is not nil,
+   it is called with the pathname that caused the error, and the
+   'errno' value from the failing call; if it returns non-zero
+   'glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
+   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+   Otherwise, 'glob' returns zero.  */
+#if !defined __USE_FILE_OFFSET64 || __GNUC__ < 2 || defined __GLOB_GNULIB
+extern int glob (const char *_Restrict_ __pattern, int __flags,
+                 int (*__errfunc) (const char *, int),
+                 glob_t *_Restrict_ __pglob) __THROW _GL_ARG_NONNULL ((1, 4));
+
+/* Free storage allocated in PGLOB by a previous 'glob' call.  */
+extern void globfree (glob_t *__pglob) __THROW _GL_ARG_NONNULL ((1));
+#else
+extern int __REDIRECT_NTH (glob, (const char *_Restrict_ __pattern,
+                                  int __flags,
+                                  int (*__errfunc) (const char *, int),
+                                  glob_t *_Restrict_ __pglob), glob64);
+
+extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64);
+#endif
+
+#if defined __USE_LARGEFILE64 && !defined __GLOB_GNULIB
+extern int glob64 (const char *_Restrict_ __pattern, int __flags,
+                   int (*__errfunc) (const char *, int),
+                   glob64_t *_Restrict_ __pglob)
+     __THROW _GL_ARG_NONNULL ((1, 4));
+
+extern void globfree64 (glob64_t *__pglob) __THROW _GL_ARG_NONNULL ((1));
+#endif
+
+
+#ifdef __USE_GNU
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.
+
+   This function is not part of the interface specified by POSIX.2
+   but several programs want to use it.  */
+extern int glob_pattern_p (const char *__pattern, int __quote)
+     __THROW _GL_ARG_NONNULL ((1));
+#endif
+
+__END_DECLS
+
+#endif /* glob.h  */
diff --git a/gdb/gnulib/import/glob.c b/gdb/gnulib/import/glob.c
new file mode 100644
index 0000000000..4b04b902e5
--- /dev/null
+++ b/gdb/gnulib/import/glob.c
@@ -0,0 +1,1808 @@
+/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library 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.
+
+   The GNU C Library 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 the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   optimizes away the pattern == NULL || pglob == NULL tests below.  */
+# define _GL_ARG_NONNULL(params)
+# include <config.h>
+#endif
+
+#include <glob.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* Outcomment the following line for production quality code.  */
+/* #define NDEBUG 1 */
+#include <assert.h>
+
+#include <stdio.h>              /* Needed on stupid SunOS for assert.  */
+
+#ifndef GLOB_ONLY_P
+
+#include <unistd.h>
+#if !defined POSIX && defined _POSIX_VERSION
+# define POSIX
+#endif
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WINDOWS32
+#endif
+
+#ifndef WINDOWS32
+# include <pwd.h>
+#endif
+
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <alloca.h>
+
+#ifdef _LIBC
+# undef strdup
+# define strdup(str) __strdup (str)
+# define sysconf(id) __sysconf (id)
+# define closedir(dir) __closedir (dir)
+# define opendir(name) __opendir (name)
+# define readdir(str) __readdir64 (str)
+# define getpwnam_r(name, bufp, buf, len, res) \
+   __getpwnam_r (name, bufp, buf, len, res)
+# ifndef __stat64
+#  define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
+# endif
+# define struct_stat64          struct stat64
+#else /* !_LIBC */
+# define __getlogin_r(buf, len) getlogin_r (buf, len)
+# define __stat64(fname, buf)   stat (fname, buf)
+# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
+# define struct_stat64          struct stat
+# ifndef __MVS__
+#  define __alloca              alloca
+# endif
+# define __readdir              readdir
+# define __glob_pattern_p       glob_pattern_p
+# define COMPILE_GLOB64
+#endif /* _LIBC */
+
+#include <fnmatch.h>
+
+#include "flexmember.h"
+
+#ifdef _SC_GETPW_R_SIZE_MAX
+# define GETPW_R_SIZE_MAX()     sysconf (_SC_GETPW_R_SIZE_MAX)
+#else
+# define GETPW_R_SIZE_MAX()     (-1)
+#endif
+#ifdef _SC_LOGIN_NAME_MAX
+# define GET_LOGIN_NAME_MAX()   sysconf (_SC_LOGIN_NAME_MAX)
+#else
+# define GET_LOGIN_NAME_MAX()   (-1)
+#endif
+\f
+static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
+
+/* A representation of a directory entry which does not depend on the
+   layout of struct dirent, or the size of ino_t.  */
+struct readdir_result
+{
+  const char *name;
+# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+  uint8_t type;
+# endif
+  bool skip_entry;
+};
+
+# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+/* Initializer based on the d_type member of struct dirent.  */
+#  define D_TYPE_TO_RESULT(source) (source)->d_type,
+
+/* True if the directory entry D might be a symbolic link.  */
+static bool
+readdir_result_might_be_symlink (struct readdir_result d)
+{
+  return d.type == DT_UNKNOWN || d.type == DT_LNK;
+}
+
+/* True if the directory entry D might be a directory.  */
+static bool
+readdir_result_might_be_dir (struct readdir_result d)
+{
+  return d.type == DT_DIR || readdir_result_might_be_symlink (d);
+}
+# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+#  define D_TYPE_TO_RESULT(source)
+
+/* If we do not have type information, symbolic links and directories
+   are always a possibility.  */
+
+static bool
+readdir_result_might_be_symlink (struct readdir_result d)
+{
+  return true;
+}
+
+static bool
+readdir_result_might_be_dir (struct readdir_result d)
+{
+  return true;
+}
+
+# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+
+# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+/* Initializer for skip_entry.  POSIX does not require that the d_ino
+   field be present, and some systems do not provide it. */
+#  define D_INO_TO_RESULT(source) false,
+# else
+#  define D_INO_TO_RESULT(source) (source)->d_ino == 0,
+# endif
+
+/* Construct an initializer for a struct readdir_result object from a
+   struct dirent *.  No copy of the name is made.  */
+#define READDIR_RESULT_INITIALIZER(source) \
+  {                                        \
+    source->d_name,                        \
+    D_TYPE_TO_RESULT (source)              \
+    D_INO_TO_RESULT (source)               \
+  }
+
+#endif /* !defined GLOB_ONLY_P */
+
+/* Call gl_readdir on STREAM.  This macro can be overridden to reduce
+   type safety if an old interface version needs to be supported.  */
+#ifndef GL_READDIR
+# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
+#endif
+
+/* Extract name and type from directory entry.  No copy of the name is
+   made.  If SOURCE is NULL, result name is NULL.  Keep in sync with
+   convert_dirent64 below.  */
+static struct readdir_result
+convert_dirent (const struct dirent *source)
+{
+  if (source == NULL)
+    {
+      struct readdir_result result = { NULL, };
+      return result;
+    }
+  struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
+  return result;
+}
+
+#ifndef COMPILE_GLOB64
+/* Like convert_dirent, but works on struct dirent64 instead.  Keep in
+   sync with convert_dirent above.  */
+static struct readdir_result
+convert_dirent64 (const struct dirent64 *source)
+{
+  if (source == NULL)
+    {
+      struct readdir_result result = { NULL, };
+      return result;
+    }
+  struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
+  return result;
+}
+#endif
+
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+#ifndef __attribute_noinline__
+# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1)
+#  define __attribute_noinline__ /* Ignore */
+#else
+#  define __attribute_noinline__ __attribute__ ((__noinline__))
+# endif
+#endif
+
+#if ! defined __builtin_expect && __GNUC__ < 3
+# define __builtin_expect(expr, expected) (expr)
+#endif
+
+#ifndef __glibc_unlikely
+# define __glibc_unlikely(expr) __builtin_expect (expr, 0)
+#endif
+
+#ifndef _LIBC
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+   and we do not leak fds to any single-threaded code that could use stdio,
+   therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
+   FIXME - if the kernel ever adds support for multi-thread safety for
+   avoiding standard fds, then we should use opendir_safer.  */
+# ifdef GNULIB_defined_opendir
+#  undef opendir
+# endif
+# ifdef GNULIB_defined_closedir
+#  undef closedir
+# endif
+
+/* Just use malloc.  */
+# define __libc_use_alloca(n) false
+# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
+# define extend_alloca_account(buf, len, newlen, avar) \
+    ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/* Set *R = A + B.  Return true if the answer is mathematically
+   incorrect due to overflow; in this case, *R is the low order
+   bits of the correct answer..  */
+
+static bool
+size_add_wrapv (size_t a, size_t b, size_t *r)
+{
+#if 5 <= __GNUC__ || __has_builtin (__builtin_add_overflow)
+  return __builtin_add_overflow (a, b, r);
+#else
+  *r = a + b;
+  return *r < a;
+#endif
+}
+
+static bool
+glob_use_alloca (size_t alloca_used, size_t len)
+{
+  size_t size;
+  return (!size_add_wrapv (alloca_used, len, &size)
+          && __libc_use_alloca (size));
+}
+
+static int glob_in_dir (const char *pattern, const char *directory,
+                        int flags, int (*errfunc) (const char *, int),
+                        glob_t *pglob, size_t alloca_used);
+extern int __glob_pattern_type (const char *pattern, int quote)
+    attribute_hidden;
+
+#ifndef GLOB_ONLY_P
+static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
+static int collated_compare (const void *, const void *) __THROWNL;
+
+
+/* Find the end of the sub-pattern in a brace expression.  */
+static const char *
+next_brace_sub (const char *cp, int flags)
+{
+  size_t depth = 0;
+  while (*cp != '\0')
+    if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
+      {
+        if (*++cp == '\0')
+          break;
+        ++cp;
+      }
+    else
+      {
+        if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
+          break;
+
+        if (*cp++ == '{')
+          depth++;
+      }
+
+  return *cp != '\0' ? cp : NULL;
+}
+
+#endif /* !defined GLOB_ONLY_P */
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+   The bits defined above may be set in FLAGS.
+   If a directory cannot be opened or read and ERRFUNC is not nil,
+   it is called with the pathname that caused the error, and the
+   'errno' value from the failing call; if it returns non-zero
+   'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
+   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+   Otherwise, 'glob' returns zero.  */
+int
+#ifdef GLOB_ATTRIBUTE
+GLOB_ATTRIBUTE
+#endif
+glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+      glob_t *pglob)
+{
+  const char *filename;
+  char *dirname = NULL;
+  size_t dirlen;
+  int status;
+  size_t oldcount;
+  int meta;
+  int dirname_modified;
+  int malloc_dirname = 0;
+  glob_t dirs;
+  int retval = 0;
+  size_t alloca_used = 0;
+
+  if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  /* POSIX requires all slashes to be matched.  This means that with
+     a trailing slash we must match only directories.  */
+  if (pattern[0] && pattern[strlen (pattern) - 1] == '/')
+    flags |= GLOB_ONLYDIR;
+
+  if (!(flags & GLOB_DOOFFS))
+    /* Have to do this so 'globfree' knows where to start freeing.  It
+       also makes all the code that uses gl_offs simpler. */
+    pglob->gl_offs = 0;
+
+  if (flags & GLOB_BRACE)
+    {
+      const char *begin;
+
+      if (flags & GLOB_NOESCAPE)
+        begin = strchr (pattern, '{');
+      else
+        {
+          begin = pattern;
+          while (1)
+            {
+              if (*begin == '\0')
+                {
+                  begin = NULL;
+                  break;
+                }
+
+              if (*begin == '\\' && begin[1] != '\0')
+                ++begin;
+              else if (*begin == '{')
+                break;
+
+              ++begin;
+            }
+        }
+
+      if (begin != NULL)
+        {
+          /* Allocate working buffer large enough for our work.  Note that
+            we have at least an opening and closing brace.  */
+          size_t firstc;
+          char *alt_start;
+          const char *p;
+          const char *next;
+          const char *rest;
+          size_t rest_len;
+          char *onealt;
+          size_t pattern_len = strlen (pattern) - 1;
+          int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
+          if (alloca_onealt)
+            onealt = alloca_account (pattern_len, alloca_used);
+          else
+            {
+              onealt = malloc (pattern_len);
+              if (onealt == NULL)
+                {
+                  if (!(flags & GLOB_APPEND))
+                    {
+                      pglob->gl_pathc = 0;
+                      pglob->gl_pathv = NULL;
+                    }
+                  return GLOB_NOSPACE;
+                }
+            }
+
+          /* We know the prefix for all sub-patterns.  */
+          alt_start = mempcpy (onealt, pattern, begin - pattern);
+
+          /* Find the first sub-pattern and at the same time find the
+             rest after the closing brace.  */
+          next = next_brace_sub (begin + 1, flags);
+          if (next == NULL)
+            {
+              /* It is an invalid expression.  */
+            illegal_brace:
+              if (__glibc_unlikely (!alloca_onealt))
+                free (onealt);
+              return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+            }
+
+          /* Now find the end of the whole brace expression.  */
+          rest = next;
+          while (*rest != '}')
+            {
+              rest = next_brace_sub (rest + 1, flags);
+              if (rest == NULL)
+                /* It is an illegal expression.  */
+                goto illegal_brace;
+            }
+          /* Please note that we now can be sure the brace expression
+             is well-formed.  */
+          rest_len = strlen (++rest) + 1;
+
+          /* We have a brace expression.  BEGIN points to the opening {,
+             NEXT points past the terminator of the first element, and END
+             points past the final }.  We will accumulate result names from
+             recursive runs for each brace alternative in the buffer using
+             GLOB_APPEND.  */
+
+          if (!(flags & GLOB_APPEND))
+            {
+              /* This call is to set a new vector, so clear out the
+                 vector so we can append to it.  */
+              pglob->gl_pathc = 0;
+              pglob->gl_pathv = NULL;
+            }
+          firstc = pglob->gl_pathc;
+
+          p = begin + 1;
+          while (1)
+            {
+              int result;
+
+              /* Construct the new glob expression.  */
+              mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
+
+              result = glob (onealt,
+                             ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
+                              | GLOB_APPEND), errfunc, pglob);
+
+              /* If we got an error, return it.  */
+              if (result && result != GLOB_NOMATCH)
+                {
+                  if (__glibc_unlikely (!alloca_onealt))
+                    free (onealt);
+                  if (!(flags & GLOB_APPEND))
+                    {
+                      globfree (pglob);
+                      pglob->gl_pathc = 0;
+                    }
+                  return result;
+                }
+
+              if (*next == '}')
+                /* We saw the last entry.  */
+                break;
+
+              p = next + 1;
+              next = next_brace_sub (p, flags);
+              assert (next != NULL);
+            }
+
+          if (__glibc_unlikely (!alloca_onealt))
+            free (onealt);
+
+          if (pglob->gl_pathc != firstc)
+            /* We found some entries.  */
+            return 0;
+          else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+            return GLOB_NOMATCH;
+        }
+    }
+
+  if (!(flags & GLOB_APPEND))
+    {
+      pglob->gl_pathc = 0;
+      if (!(flags & GLOB_DOOFFS))
+        pglob->gl_pathv = NULL;
+      else
+        {
+          size_t i;
+
+          if (pglob->gl_offs >= SIZE_MAX / sizeof (char *))
+            return GLOB_NOSPACE;
+
+          pglob->gl_pathv = malloc ((pglob->gl_offs + 1) * sizeof (char *));
+          if (pglob->gl_pathv == NULL)
+            return GLOB_NOSPACE;
+
+          for (i = 0; i <= pglob->gl_offs; ++i)
+            pglob->gl_pathv[i] = NULL;
+        }
+    }
+
+  oldcount = pglob->gl_pathc + pglob->gl_offs;
+
+  /* Find the filename.  */
+  filename = strrchr (pattern, '/');
+#if defined __MSDOS__ || defined WINDOWS32
+  /* The case of "d:pattern".  Since ':' is not allowed in
+     file names, we can safely assume that wherever it
+     happens in pattern, it signals the filename part.  This
+     is so we could some day support patterns like "[a-z]:foo".  */
+  if (filename == NULL)
+    filename = strchr (pattern, ':');
+#endif /* __MSDOS__ || WINDOWS32 */
+  dirname_modified = 0;
+  if (filename == NULL)
+    {
+      /* This can mean two things: a simple name or "~name".  The latter
+         case is nothing but a notation for a directory.  */
+      if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
+        {
+          dirname = (char *) pattern;
+          dirlen = strlen (pattern);
+
+          /* Set FILENAME to NULL as a special flag.  This is ugly but
+             other solutions would require much more code.  We test for
+             this special case below.  */
+          filename = NULL;
+        }
+      else
+        {
+          if (__glibc_unlikely (pattern[0] == '\0'))
+            {
+              dirs.gl_pathv = NULL;
+              goto no_matches;
+            }
+
+          filename = pattern;
+#ifdef _AMIGA
+          dirname = (char *) "";
+#else
+          dirname = (char *) ".";
+#endif
+          dirlen = 0;
+        }
+    }
+  else if (filename == pattern
+           || (filename == pattern + 1 && pattern[0] == '\\'
+               && (flags & GLOB_NOESCAPE) == 0))
+    {
+      /* "/pattern" or "\\/pattern".  */
+      dirname = (char *) "/";
+      dirlen = 1;
+      ++filename;
+    }
+  else
+    {
+      char *newp;
+      dirlen = filename - pattern;
+#if defined __MSDOS__ || defined WINDOWS32
+      if (*filename == ':'
+          || (filename > pattern + 1 && filename[-1] == ':'))
+        {
+          char *drive_spec;
+
+          ++dirlen;
+          drive_spec = __alloca (dirlen + 1);
+          *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+          /* For now, disallow wildcards in the drive spec, to
+             prevent infinite recursion in glob.  */
+          if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+            return GLOB_NOMATCH;
+          /* If this is "d:pattern", we need to copy ':' to DIRNAME
+             as well.  If it's "d:/pattern", don't remove the slash
+             from "d:/", since "d:" and "d:/" are not the same.*/
+        }
+#endif
+      if (glob_use_alloca (alloca_used, dirlen + 1))
+        newp = alloca_account (dirlen + 1, alloca_used);
+      else
+        {
+          newp = malloc (dirlen + 1);
+          if (newp == NULL)
+            return GLOB_NOSPACE;
+          malloc_dirname = 1;
+        }
+      *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
+      dirname = newp;
+      ++filename;
+
+      if (filename[0] == '\0'
+#if defined __MSDOS__ || defined WINDOWS32
+          && dirname[dirlen - 1] != ':'
+          && (dirlen < 3 || dirname[dirlen - 2] != ':'
+              || dirname[dirlen - 1] != '/')
+#endif
+          && dirlen > 1)
+        /* "pattern/".  Expand "pattern", appending slashes.  */
+        {
+          int orig_flags = flags;
+          int val;
+          if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
+            {
+              /* "pattern\\/".  Remove the final backslash if it hasn't
+                 been quoted.  */
+              char *p = (char *) &dirname[dirlen - 1];
+
+              while (p > dirname && p[-1] == '\\') --p;
+              if ((&dirname[dirlen] - p) & 1)
+                {
+                  *(char *) &dirname[--dirlen] = '\0';
+                  flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
+                }
+            }
+          val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+          if (val == 0)
+            pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
+                               | (flags & GLOB_MARK));
+          else if (val == GLOB_NOMATCH && flags != orig_flags)
+            {
+              /* Make sure globfree (&dirs); is a nop.  */
+              dirs.gl_pathv = NULL;
+              flags = orig_flags;
+              oldcount = pglob->gl_pathc + pglob->gl_offs;
+              goto no_matches;
+            }
+          retval = val;
+          goto out;
+        }
+    }
+
+  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
+    {
+      if (dirname[1] == '\0' || dirname[1] == '/'
+          || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
+              && (dirname[2] == '\0' || dirname[2] == '/')))
+        {
+          /* Look up home directory.  */
+          char *home_dir = getenv ("HOME");
+          int malloc_home_dir = 0;
+# ifdef _AMIGA
+          if (home_dir == NULL || home_dir[0] == '\0')
+            home_dir = "SYS:";
+# else
+#  ifdef WINDOWS32
+          /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give preference
+             to HOME, because the user can change HOME.  */
+          if (home_dir == NULL || home_dir[0] == '\0')
+            {
+              const char *home_drive = getenv ("HOMEDRIVE");
+              const char *home_path = getenv ("HOMEPATH");
+
+              if (home_drive != NULL && home_path != NULL)
+                {
+                  size_t home_drive_len = strlen (home_drive);
+                  size_t home_path_len = strlen (home_path);
+                  char *mem = alloca (home_drive_len + home_path_len + 1);
+
+                  memcpy (mem, home_drive, home_drive_len);
+                  memcpy (mem + home_drive_len, home_path, home_path_len + 1);
+                  home_dir = mem;
+                }
+              else
+                home_dir = "c:/users/default"; /* poor default */
+            }
+#  else
+          if (home_dir == NULL || home_dir[0] == '\0')
+            {
+              int success;
+              char *name;
+              int malloc_name = 0;
+              size_t buflen = GET_LOGIN_NAME_MAX () + 1;
+
+              if (buflen == 0)
+                /* 'sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
+                   a moderate value.  */
+                buflen = 20;
+              if (glob_use_alloca (alloca_used, buflen))
+                name = alloca_account (buflen, alloca_used);
+              else
+                {
+                  name = malloc (buflen);
+                  if (name == NULL)
+                    {
+                      retval = GLOB_NOSPACE;
+                      goto out;
+                    }
+                  malloc_name = 1;
+                }
+
+              success = __getlogin_r (name, buflen) == 0;
+              if (success)
+                {
+                  struct passwd *p;
+#   if defined HAVE_GETPWNAM_R || defined _LIBC
+                  long int pwbuflenmax = GETPW_R_SIZE_MAX ();
+                  size_t pwbuflen = pwbuflenmax;
+                  char *pwtmpbuf;
+                  struct passwd pwbuf;
+                  char *malloc_pwtmpbuf = NULL;
+                  int save = errno;
+
+#    ifndef _LIBC
+                  if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
+                    /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.
+                       Try a moderate value.  */
+                    pwbuflen = 1024;
+#    endif
+                  if (glob_use_alloca (alloca_used, pwbuflen))
+                    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
+                  else
+                    {
+                      pwtmpbuf = malloc (pwbuflen);
+                      if (pwtmpbuf == NULL)
+                        {
+                          retval = GLOB_NOSPACE;
+                          goto out;
+                        }
+                      malloc_pwtmpbuf = pwtmpbuf;
+                    }
+
+                  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+                         != 0)
+                    {
+                      size_t newlen;
+                      bool v;
+                      if (errno != ERANGE)
+                        {
+                          p = NULL;
+                          break;
+                        }
+                      v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
+                      if (!v && malloc_pwtmpbuf == NULL
+                          && glob_use_alloca (alloca_used, newlen))
+                        pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
+                                                          newlen, alloca_used);
+                      else
+                        {
+                          char *newp = (v ? NULL
+                                        : realloc (malloc_pwtmpbuf, newlen));
+                          if (newp == NULL)
+                            {
+                              free (malloc_pwtmpbuf);
+                              retval = GLOB_NOSPACE;
+                              goto out;
+                            }
+                          malloc_pwtmpbuf = pwtmpbuf = newp;
+                        }
+                      pwbuflen = newlen;
+                      __set_errno (save);
+                    }
+#   else
+                  p = getpwnam (name);
+#   endif
+                  if (__glibc_unlikely (malloc_name))
+                    free (name);
+                  if (p != NULL)
+                    {
+                      if (malloc_pwtmpbuf == NULL)
+                        home_dir = p->pw_dir;
+                      else
+                        {
+                          size_t home_dir_len = strlen (p->pw_dir) + 1;
+                          if (glob_use_alloca (alloca_used, home_dir_len))
+                            home_dir = alloca_account (home_dir_len,
+                                                       alloca_used);
+                          else
+                            {
+                              home_dir = malloc (home_dir_len);
+                              if (home_dir == NULL)
+                                {
+                                  free (pwtmpbuf);
+                                  retval = GLOB_NOSPACE;
+                                  goto out;
+                                }
+                              malloc_home_dir = 1;
+                            }
+                          memcpy (home_dir, p->pw_dir, home_dir_len);
+
+                          free (pwtmpbuf);
+                        }
+                    }
+                }
+            }
+          if (home_dir == NULL || home_dir[0] == '\0')
+            {
+              if (flags & GLOB_TILDE_CHECK)
+                {
+                  if (__glibc_unlikely (malloc_home_dir))
+                    free (home_dir);
+                  retval = GLOB_NOMATCH;
+                  goto out;
+                }
+              else
+                home_dir = (char *) "~"; /* No luck.  */
+            }
+#  endif /* WINDOWS32 */
+# endif
+          /* Now construct the full directory.  */
+          if (dirname[1] == '\0')
+            {
+              if (__glibc_unlikely (malloc_dirname))
+                free (dirname);
+
+              dirname = home_dir;
+              dirlen = strlen (dirname);
+              malloc_dirname = malloc_home_dir;
+            }
+          else
+            {
+              char *newp;
+              size_t home_len = strlen (home_dir);
+              int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
+              if (use_alloca)
+                newp = alloca_account (home_len + dirlen, alloca_used);
+              else
+                {
+                  newp = malloc (home_len + dirlen);
+                  if (newp == NULL)
+                    {
+                      if (__glibc_unlikely (malloc_home_dir))
+                        free (home_dir);
+                      retval = GLOB_NOSPACE;
+                      goto out;
+                    }
+                }
+
+              mempcpy (mempcpy (newp, home_dir, home_len),
+                       &dirname[1], dirlen);
+
+              if (__glibc_unlikely (malloc_dirname))
+                free (dirname);
+
+              dirname = newp;
+              dirlen += home_len - 1;
+              malloc_dirname = !use_alloca;
+            }
+          dirname_modified = 1;
+        }
+# if !defined _AMIGA && !defined WINDOWS32
+      else
+        {
+          char *end_name = strchr (dirname, '/');
+          char *user_name;
+          int malloc_user_name = 0;
+          char *unescape = NULL;
+
+          if (!(flags & GLOB_NOESCAPE))
+            {
+              if (end_name == NULL)
+                {
+                  unescape = strchr (dirname, '\\');
+                  if (unescape)
+                    end_name = strchr (unescape, '\0');
+                }
+              else
+                unescape = memchr (dirname, '\\', end_name - dirname);
+            }
+          if (end_name == NULL)
+            user_name = dirname + 1;
+          else
+            {
+              char *newp;
+              if (glob_use_alloca (alloca_used, end_name - dirname))
+                newp = alloca_account (end_name - dirname, alloca_used);
+              else
+                {
+                  newp = malloc (end_name - dirname);
+                  if (newp == NULL)
+                    {
+                      retval = GLOB_NOSPACE;
+                      goto out;
+                    }
+                  malloc_user_name = 1;
+                }
+              if (unescape != NULL)
+                {
+                  char *p = mempcpy (newp, dirname + 1,
+                                     unescape - dirname - 1);
+                  char *q = unescape;
+                  while (*q != '\0')
+                    {
+                      if (*q == '\\')
+                        {
+                          if (q[1] == '\0')
+                            {
+                              /* "~fo\\o\\" unescape to user_name "foo\\",
+                                 but "~fo\\o\\/" unescape to user_name
+                                 "foo".  */
+                              if (filename == NULL)
+                                *p++ = '\\';
+                              break;
+                            }
+                          ++q;
+                        }
+                      *p++ = *q++;
+                    }
+                  *p = '\0';
+                }
+              else
+                *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
+                  = '\0';
+              user_name = newp;
+            }
+
+          /* Look up specific user's home directory.  */
+          {
+            struct passwd *p;
+#  if defined HAVE_GETPWNAM_R || defined _LIBC
+            long int buflenmax = GETPW_R_SIZE_MAX ();
+            size_t buflen = buflenmax;
+            char *pwtmpbuf;
+            char *malloc_pwtmpbuf = NULL;
+            struct passwd pwbuf;
+            int save = errno;
+
+#   ifndef _LIBC
+            if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
+              /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
+                 moderate value.  */
+              buflen = 1024;
+#   endif
+            if (glob_use_alloca (alloca_used, buflen))
+              pwtmpbuf = alloca_account (buflen, alloca_used);
+            else
+              {
+                pwtmpbuf = malloc (buflen);
+                if (pwtmpbuf == NULL)
+                  {
+                  nomem_getpw:
+                    if (__glibc_unlikely (malloc_user_name))
+                      free (user_name);
+                    retval = GLOB_NOSPACE;
+                    goto out;
+                  }
+                malloc_pwtmpbuf = pwtmpbuf;
+              }
+
+            while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+              {
+                size_t newlen;
+                bool v;
+                if (errno != ERANGE)
+                  {
+                    p = NULL;
+                    break;
+                  }
+                v = size_add_wrapv (buflen, buflen, &newlen);
+                if (!v && malloc_pwtmpbuf == NULL
+                    && glob_use_alloca (alloca_used, newlen))
+                  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
+                                                    newlen, alloca_used);
+                else
+                  {
+                    char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
+                    if (newp == NULL)
+                      {
+                        free (malloc_pwtmpbuf);
+                        goto nomem_getpw;
+                      }
+                    malloc_pwtmpbuf = pwtmpbuf = newp;
+                  }
+                __set_errno (save);
+              }
+#  else
+            p = getpwnam (user_name);
+#  endif
+
+            if (__glibc_unlikely (malloc_user_name))
+              free (user_name);
+
+            /* If we found a home directory use this.  */
+            if (p != NULL)
+              {
+                size_t home_len = strlen (p->pw_dir);
+                size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+
+                if (__glibc_unlikely (malloc_dirname))
+                  free (dirname);
+                malloc_dirname = 0;
+
+                if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
+                  dirname = alloca_account (home_len + rest_len + 1,
+                                            alloca_used);
+                else
+                  {
+                    dirname = malloc (home_len + rest_len + 1);
+                    if (dirname == NULL)
+                      {
+                        free (malloc_pwtmpbuf);
+                        retval = GLOB_NOSPACE;
+                        goto out;
+                      }
+                    malloc_dirname = 1;
+                  }
+                *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
+                                    end_name, rest_len)) = '\0';
+
+                dirlen = home_len + rest_len;
+                dirname_modified = 1;
+
+                free (malloc_pwtmpbuf);
+              }
+            else
+              {
+                free (malloc_pwtmpbuf);
+
+                if (flags & GLOB_TILDE_CHECK)
+                  /* We have to regard it as an error if we cannot find the
+                     home directory.  */
+                  return GLOB_NOMATCH;
+              }
+          }
+        }
+# endif /* Not Amiga && not WINDOWS32.  */
+    }
+
+  /* Now test whether we looked for "~" or "~NAME".  In this case we
+     can give the answer now.  */
+  if (filename == NULL)
+    {
+      struct stat st;
+      struct_stat64 st64;
+
+      /* Return the directory if we don't check for error or if it exists.  */
+      if ((flags & GLOB_NOCHECK)
+          || (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+               ? ((*pglob->gl_stat) (dirname, &st) == 0
+                  && S_ISDIR (st.st_mode))
+               : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
+        {
+          size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+          char **new_gl_pathv;
+
+          if (newcount > SIZE_MAX / sizeof (char *) - 2)
+            {
+            nospace:
+              free (pglob->gl_pathv);
+              pglob->gl_pathv = NULL;
+              pglob->gl_pathc = 0;
+              return GLOB_NOSPACE;
+            }
+
+          new_gl_pathv = realloc (pglob->gl_pathv,
+                                  (newcount + 2) * sizeof (char *));
+          if (new_gl_pathv == NULL)
+            goto nospace;
+          pglob->gl_pathv = new_gl_pathv;
+
+          if (flags & GLOB_MARK)
+            {
+              char *p;
+              pglob->gl_pathv[newcount] = malloc (dirlen + 2);
+              if (pglob->gl_pathv[newcount] == NULL)
+                goto nospace;
+              p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
+              p[0] = '/';
+              p[1] = '\0';
+            }
+          else
+            {
+              pglob->gl_pathv[newcount] = strdup (dirname);
+              if (pglob->gl_pathv[newcount] == NULL)
+                goto nospace;
+            }
+          pglob->gl_pathv[++newcount] = NULL;
+          ++pglob->gl_pathc;
+          pglob->gl_flags = flags;
+
+          return 0;
+        }
+
+      /* Not found.  */
+      return GLOB_NOMATCH;
+    }
+
+  meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
+  /* meta is 1 if correct glob pattern containing metacharacters.
+     If meta has bit (1 << 2) set, it means there was an unterminated
+     [ which we handle the same, using fnmatch.  Broken unterminated
+     pattern bracket expressions ought to be rare enough that it is
+     not worth special casing them, fnmatch will do the right thing.  */
+  if (meta & 5)
+    {
+      /* The directory name contains metacharacters, so we
+         have to glob for the directory, and then glob for
+         the pattern in each directory found.  */
+      size_t i;
+
+      if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
+        {
+          /* "foo\\/bar".  Remove the final backslash from dirname
+             if it has not been quoted.  */
+          char *p = (char *) &dirname[dirlen - 1];
+
+          while (p > dirname && p[-1] == '\\') --p;
+          if ((&dirname[dirlen] - p) & 1)
+            *(char *) &dirname[--dirlen] = '\0';
+        }
+
+      if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
+        {
+          /* Use the alternative access functions also in the recursive
+             call.  */
+          dirs.gl_opendir = pglob->gl_opendir;
+          dirs.gl_readdir = pglob->gl_readdir;
+          dirs.gl_closedir = pglob->gl_closedir;
+          dirs.gl_stat = pglob->gl_stat;
+          dirs.gl_lstat = pglob->gl_lstat;
+        }
+
+      status = glob (dirname,
+                     ((flags & (GLOB_ERR | GLOB_NOESCAPE
+                                | GLOB_ALTDIRFUNC))
+                      | GLOB_NOSORT | GLOB_ONLYDIR),
+                     errfunc, &dirs);
+      if (status != 0)
+        {
+          if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
+            return status;
+          goto no_matches;
+        }
+
+      /* We have successfully globbed the preceding directory name.
+         For each name we found, call glob_in_dir on it and FILENAME,
+         appending the results to PGLOB.  */
+      for (i = 0; i < dirs.gl_pathc; ++i)
+        {
+          size_t old_pathc;
+
+#ifdef SHELL
+          {
+            /* Make globbing interruptible in the bash shell. */
+            extern int interrupt_state;
+
+            if (interrupt_state)
+              {
+                globfree (&dirs);
+                return GLOB_ABORTED;
+              }
+          }
+#endif /* SHELL.  */
+
+          old_pathc = pglob->gl_pathc;
+          status = glob_in_dir (filename, dirs.gl_pathv[i],
+                                ((flags | GLOB_APPEND)
+                                 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
+                                errfunc, pglob, alloca_used);
+          if (status == GLOB_NOMATCH)
+            /* No matches in this directory.  Try the next.  */
+            continue;
+
+          if (status != 0)
+            {
+              globfree (&dirs);
+              globfree (pglob);
+              pglob->gl_pathc = 0;
+              return status;
+            }
+
+          /* Stick the directory on the front of each name.  */
+          if (prefix_array (dirs.gl_pathv[i],
+                            &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+                            pglob->gl_pathc - old_pathc))
+            {
+              globfree (&dirs);
+              globfree (pglob);
+              pglob->gl_pathc = 0;
+              return GLOB_NOSPACE;
+            }
+        }
+
+      flags |= GLOB_MAGCHAR;
+
+      /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
+         But if we have not found any matching entry and the GLOB_NOCHECK
+         flag was set we must return the input pattern itself.  */
+      if (pglob->gl_pathc + pglob->gl_offs == oldcount)
+        {
+        no_matches:
+          /* No matches.  */
+          if (flags & GLOB_NOCHECK)
+            {
+              size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+              char **new_gl_pathv;
+
+              if (newcount > SIZE_MAX / sizeof (char *) - 2)
+                {
+                nospace2:
+                  globfree (&dirs);
+                  return GLOB_NOSPACE;
+                }
+
+              new_gl_pathv = realloc (pglob->gl_pathv,
+                                      (newcount + 2) * sizeof (char *));
+              if (new_gl_pathv == NULL)
+                goto nospace2;
+              pglob->gl_pathv = new_gl_pathv;
+
+              pglob->gl_pathv[newcount] = strdup (pattern);
+              if (pglob->gl_pathv[newcount] == NULL)
+                {
+                  globfree (&dirs);
+                  globfree (pglob);
+                  pglob->gl_pathc = 0;
+                  return GLOB_NOSPACE;
+                }
+
+              ++pglob->gl_pathc;
+              ++newcount;
+
+              pglob->gl_pathv[newcount] = NULL;
+              pglob->gl_flags = flags;
+            }
+          else
+            {
+              globfree (&dirs);
+              return GLOB_NOMATCH;
+            }
+        }
+
+      globfree (&dirs);
+    }
+  else
+    {
+      size_t old_pathc = pglob->gl_pathc;
+      int orig_flags = flags;
+
+      if (meta & 2)
+        {
+          char *p = strchr (dirname, '\\'), *q;
+          /* We need to unescape the dirname string.  It is certainly
+             allocated by alloca, as otherwise filename would be NULL
+             or dirname wouldn't contain backslashes.  */
+          q = p;
+          do
+            {
+              if (*p == '\\')
+                {
+                  *q = *++p;
+                  --dirlen;
+                }
+              else
+                *q = *p;
+              ++q;
+            }
+          while (*p++ != '\0');
+          dirname_modified = 1;
+        }
+      if (dirname_modified)
+        flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
+      status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
+                            alloca_used);
+      if (status != 0)
+        {
+          if (status == GLOB_NOMATCH && flags != orig_flags
+              && pglob->gl_pathc + pglob->gl_offs == oldcount)
+            {
+              /* Make sure globfree (&dirs); is a nop.  */
+              dirs.gl_pathv = NULL;
+              flags = orig_flags;
+              goto no_matches;
+            }
+          return status;
+        }
+
+      if (dirlen > 0)
+        {
+          /* Stick the directory on the front of each name.  */
+          if (prefix_array (dirname,
+                            &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+                            pglob->gl_pathc - old_pathc))
+            {
+              globfree (pglob);
+              pglob->gl_pathc = 0;
+              return GLOB_NOSPACE;
+            }
+        }
+    }
+
+  if (flags & GLOB_MARK)
+    {
+      /* Append slashes to directory names.  */
+      size_t i;
+      struct stat st;
+      struct_stat64 st64;
+
+      for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
+        if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+             ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
+                && S_ISDIR (st.st_mode))
+             : (__stat64 (pglob->gl_pathv[i], &st64) == 0
+                && S_ISDIR (st64.st_mode))))
+          {
+            size_t len = strlen (pglob->gl_pathv[i]) + 2;
+            char *new = realloc (pglob->gl_pathv[i], len);
+            if (new == NULL)
+              {
+                globfree (pglob);
+                pglob->gl_pathc = 0;
+                return GLOB_NOSPACE;
+              }
+            strcpy (&new[len - 2], "/");
+            pglob->gl_pathv[i] = new;
+          }
+    }
+
+  if (!(flags & GLOB_NOSORT))
+    {
+      /* Sort the vector.  */
+      qsort (&pglob->gl_pathv[oldcount],
+             pglob->gl_pathc + pglob->gl_offs - oldcount,
+             sizeof (char *), collated_compare);
+    }
+
+ out:
+  if (__glibc_unlikely (malloc_dirname))
+    free (dirname);
+
+  return retval;
+}
+#if defined _LIBC && !defined glob
+libc_hidden_def (glob)
+#endif
+
+
+#ifndef GLOB_ONLY_P
+
+/* Free storage allocated in PGLOB by a previous 'glob' call.  */
+void
+globfree (glob_t *pglob)
+{
+  if (pglob->gl_pathv != NULL)
+    {
+      size_t i;
+      for (i = 0; i < pglob->gl_pathc; ++i)
+        free (pglob->gl_pathv[pglob->gl_offs + i]);
+      free (pglob->gl_pathv);
+      pglob->gl_pathv = NULL;
+    }
+}
+#if defined _LIBC && !defined globfree
+libc_hidden_def (globfree)
+#endif
+
+
+/* Do a collated comparison of A and B.  */
+static int
+collated_compare (const void *a, const void *b)
+{
+  char *const *ps1 = a; char *s1 = *ps1;
+  char *const *ps2 = b; char *s2 = *ps2;
+
+  if (s1 == s2)
+    return 0;
+  if (s1 == NULL)
+    return 1;
+  if (s2 == NULL)
+    return -1;
+  return strcoll (s1, s2);
+}
+
+
+/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
+   elements in place.  Return nonzero if out of memory, zero if successful.
+   A slash is inserted between DIRNAME and each elt of ARRAY,
+   unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
+static int
+prefix_array (const char *dirname, char **array, size_t n)
+{
+  size_t i;
+  size_t dirlen = strlen (dirname);
+#if defined __MSDOS__ || defined WINDOWS32
+  int sep_char = '/';
+# define DIRSEP_CHAR sep_char
+#else
+# define DIRSEP_CHAR '/'
+#endif
+
+  if (dirlen == 1 && dirname[0] == '/')
+    /* DIRNAME is just "/", so normal prepending would get us "//foo".
+       We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
+    dirlen = 0;
+#if defined __MSDOS__ || defined WINDOWS32
+  else if (dirlen > 1)
+    {
+      if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
+        /* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
+        --dirlen;
+      else if (dirname[dirlen - 1] == ':')
+        {
+          /* DIRNAME is "d:".  Use ':' instead of '/'.  */
+          --dirlen;
+          sep_char = ':';
+        }
+    }
+#endif
+
+  for (i = 0; i < n; ++i)
+    {
+      size_t eltlen = strlen (array[i]) + 1;
+      char *new = malloc (dirlen + 1 + eltlen);
+      if (new == NULL)
+        {
+          while (i > 0)
+            free (array[--i]);
+          return 1;
+        }
+
+      {
+        char *endp = mempcpy (new, dirname, dirlen);
+        *endp++ = DIRSEP_CHAR;
+        mempcpy (endp, array[i], eltlen);
+      }
+      free (array[i]);
+      array[i] = new;
+    }
+
+  return 0;
+}
+
+
+/* We must not compile this function twice.  */
+#ifndef NO_GLOB_PATTERN_P
+int
+__glob_pattern_type (const char *pattern, int quote)
+{
+  const char *p;
+  int ret = 0;
+
+  for (p = pattern; *p != '\0'; ++p)
+    switch (*p)
+      {
+      case '?':
+      case '*':
+        return 1;
+
+      case '\\':
+        if (quote)
+          {
+            if (p[1] != '\0')
+              ++p;
+            ret |= 2;
+          }
+        break;
+
+      case '[':
+        ret |= 4;
+        break;
+
+      case ']':
+        if (ret & 4)
+          return 1;
+        break;
+      }
+
+  return ret;
+}
+
+/* Return nonzero if PATTERN contains any metacharacters.
+   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
+int
+__glob_pattern_p (const char *pattern, int quote)
+{
+  return __glob_pattern_type (pattern, quote) == 1;
+}
+# ifdef _LIBC
+weak_alias (__glob_pattern_p, glob_pattern_p)
+# endif
+#endif
+
+
+/* We put this in a separate function mainly to allow the memory
+   allocated with alloca to be recycled.  */
+static int
+__attribute_noinline__
+link_exists2_p (const char *dir, size_t dirlen, const char *fname,
+               glob_t *pglob
+# if !defined _LIBC && !HAVE_FSTATAT
+                , int flags
+# endif
+                )
+{
+  size_t fnamelen = strlen (fname);
+  char *fullname = __alloca (dirlen + 1 + fnamelen + 1);
+  struct stat st;
+
+  mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
+           fname, fnamelen + 1);
+
+# if !defined _LIBC && !HAVE_FSTATAT
+  if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1))
+    {
+      struct_stat64 st64;
+      return __stat64 (fullname, &st64) == 0;
+    }
+# endif
+  return (*pglob->gl_stat) (fullname, &st) == 0;
+}
+
+/* Return true if DIR/FNAME exists.  */
+static int
+link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname,
+               glob_t *pglob, int flags)
+{
+# if defined _LIBC || HAVE_FSTATAT
+  if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+    return link_exists2_p (dir, dirlen, fname, pglob);
+  else
+    {
+      /* dfd cannot be -1 here, because dirfd never returns -1 on
+         glibc, or on hosts that have fstatat.  */
+      struct_stat64 st64;
+      return __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0;
+    }
+# else
+  return link_exists2_p (dir, dirlen, fname, pglob, flags);
+# endif
+}
+#endif /* !defined GLOB_ONLY_P */
+
+
+/* Like 'glob', but PATTERN is a final pathname component,
+   and matches are searched for in DIRECTORY.
+   The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
+   The GLOB_APPEND flag is assumed to be set (always appends).  */
+static int
+glob_in_dir (const char *pattern, const char *directory, int flags,
+             int (*errfunc) (const char *, int),
+             glob_t *pglob, size_t alloca_used)
+{
+  size_t dirlen = strlen (directory);
+  void *stream = NULL;
+  struct globnames
+    {
+      struct globnames *next;
+      size_t count;
+      char *name[64];
+    };
+  struct globnames init_names;
+  struct globnames *names = &init_names;
+  struct globnames *names_alloca = &init_names;
+  size_t nfound = 0;
+  size_t cur = 0;
+  int meta;
+  int save;
+  int result;
+
+  alloca_used += sizeof (init_names);
+
+  init_names.next = NULL;
+  init_names.count = sizeof init_names.name / sizeof init_names.name[0];
+
+  meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
+  if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+    {
+      /* We need not do any tests.  The PATTERN contains no meta
+         characters and we must not return an error therefore the
+         result will always contain exactly one name.  */
+      flags |= GLOB_NOCHECK;
+    }
+  else if (meta == 0)
+    {
+      /* Since we use the normal file functions we can also use stat()
+         to verify the file is there.  */
+      union
+      {
+        struct stat st;
+        struct_stat64 st64;
+      } ust;
+      size_t patlen = strlen (pattern);
+      size_t fullsize;
+      bool alloca_fullname
+        = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
+           && glob_use_alloca (alloca_used, fullsize));
+      char *fullname;
+      if (alloca_fullname)
+        fullname = alloca_account (fullsize, alloca_used);
+      else
+        {
+          fullname = malloc (fullsize);
+          if (fullname == NULL)
+            return GLOB_NOSPACE;
+        }
+
+      mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
+                        "/", 1),
+               pattern, patlen + 1);
+      if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+           ? (*pglob->gl_stat) (fullname, &ust.st)
+           : __stat64 (fullname, &ust.st64)) == 0)
+        /* We found this file to be existing.  Now tell the rest
+           of the function to copy this name into the result.  */
+        flags |= GLOB_NOCHECK;
+
+      if (__glibc_unlikely (!alloca_fullname))
+        free (fullname);
+    }
+  else
+    {
+      stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+                ? (*pglob->gl_opendir) (directory)
+                : opendir (directory));
+      if (stream == NULL)
+        {
+          if (errno != ENOTDIR
+              && ((errfunc != NULL && (*errfunc) (directory, errno))
+                  || (flags & GLOB_ERR)))
+            return GLOB_ABORTED;
+        }
+      else
+        {
+          int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+                     ? -1 : dirfd ((DIR *) stream));
+          int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+                           | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+#if defined _AMIGA || defined VMS
+                           | FNM_CASEFOLD
+#endif
+                           );
+          flags |= GLOB_MAGCHAR;
+
+          while (1)
+            {
+              struct readdir_result d;
+              {
+                if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+                  d = convert_dirent (GL_READDIR (pglob, stream));
+                else
+                  {
+#ifdef COMPILE_GLOB64
+                    d = convert_dirent (__readdir (stream));
+#else
+                    d = convert_dirent64 (__readdir64 (stream));
+#endif
+                  }
+              }
+              if (d.name == NULL)
+                break;
+              if (d.skip_entry)
+                continue;
+
+              /* If we shall match only directories use the information
+                 provided by the dirent call if possible.  */
+              if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
+                continue;
+
+              if (fnmatch (pattern, d.name, fnm_flags) == 0)
+                {
+                  /* If the file we found is a symlink we have to
+                     make sure the target file exists.  */
+                  if (!readdir_result_might_be_symlink (d)
+                      || link_exists_p (dfd, directory, dirlen, d.name,
+                                        pglob, flags))
+                    {
+                      if (cur == names->count)
+                        {
+                          struct globnames *newnames;
+                          size_t count = names->count * 2;
+                          size_t nameoff = offsetof (struct globnames, name);
+                          size_t size = FLEXSIZEOF (struct globnames, name,
+                                                    count * sizeof (char *));
+                          if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
+                              < names->count)
+                            goto memory_error;
+                          if (glob_use_alloca (alloca_used, size))
+                            newnames = names_alloca
+                              = alloca_account (size, alloca_used);
+                          else if ((newnames = malloc (size))
+                                   == NULL)
+                            goto memory_error;
+                          newnames->count = count;
+                          newnames->next = names;
+                          names = newnames;
+                          cur = 0;
+                        }
+                      names->name[cur] = strdup (d.name);
+                      if (names->name[cur] == NULL)
+                        goto memory_error;
+                      ++cur;
+                      ++nfound;
+                      if (SIZE_MAX - pglob->gl_offs <= nfound)
+                        goto memory_error;
+                    }
+                }
+            }
+        }
+    }
+
+  if (nfound == 0 && (flags & GLOB_NOCHECK))
+    {
+      size_t len = strlen (pattern);
+      nfound = 1;
+      names->name[cur] = malloc (len + 1);
+      if (names->name[cur] == NULL)
+        goto memory_error;
+      *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
+    }
+
+  result = GLOB_NOMATCH;
+  if (nfound != 0)
+    {
+      char **new_gl_pathv;
+      result = 0;
+
+      if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
+          < pglob->gl_offs + nfound + 1)
+        goto memory_error;
+
+      new_gl_pathv
+        = realloc (pglob->gl_pathv,
+                   (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+                   * sizeof (char *));
+
+      if (new_gl_pathv == NULL)
+        {
+        memory_error:
+          while (1)
+            {
+              struct globnames *old = names;
+              size_t i;
+              for (i = 0; i < cur; ++i)
+                free (names->name[i]);
+              names = names->next;
+              /* NB: we will not leak memory here if we exit without
+                 freeing the current block assigned to OLD.  At least
+                 the very first block is always allocated on the stack
+                 and this is the block assigned to OLD here.  */
+              if (names == NULL)
+                {
+                  assert (old == &init_names);
+                  break;
+                }
+              cur = names->count;
+              if (old == names_alloca)
+                names_alloca = names;
+              else
+                free (old);
+            }
+          result = GLOB_NOSPACE;
+        }
+      else
+        {
+          while (1)
+            {
+              struct globnames *old = names;
+              size_t i;
+              for (i = 0; i < cur; ++i)
+                new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
+                  = names->name[i];
+              names = names->next;
+              /* NB: we will not leak memory here if we exit without
+                 freeing the current block assigned to OLD.  At least
+                 the very first block is always allocated on the stack
+                 and this is the block assigned to OLD here.  */
+              if (names == NULL)
+                {
+                  assert (old == &init_names);
+                  break;
+                }
+              cur = names->count;
+              if (old == names_alloca)
+                names_alloca = names;
+              else
+                free (old);
+            }
+
+          pglob->gl_pathv = new_gl_pathv;
+
+          pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+          pglob->gl_flags = flags;
+        }
+    }
+
+  if (stream != NULL)
+    {
+      save = errno;
+      if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
+        (*pglob->gl_closedir) (stream);
+      else
+        closedir (stream);
+      __set_errno (save);
+    }
+
+  return result;
+}
diff --git a/gdb/gnulib/import/glob.in.h b/gdb/gnulib/import/glob.in.h
new file mode 100644
index 0000000000..77816bc099
--- /dev/null
+++ b/gdb/gnulib/import/glob.in.h
@@ -0,0 +1,93 @@
+/* glob.h -- Find a path matching a pattern.
+
+   Copyright (C) 2005-2007, 2009-2016 Free Software Foundation, Inc.
+
+   Written by Derek Price <derek@ximbiot.com> & Paul Eggert <eggert@CS.UCLA.EDU>
+
+   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, 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 _GL_GLOB_H
+#define _GL_GLOB_H
+
+#if @HAVE_SYS_CDEFS_H@
+# include <sys/cdefs.h>
+#endif
+
+#include <stddef.h>
+
+/* On some systems, such as AIX 5.1, <sys/stat.h> does a "#define stat stat64".
+   Make sure this definition is seen before glob-libc.h defines types that
+   rely on 'struct stat'.  */
+#include <sys/stat.h>
+
+#ifndef __BEGIN_DECLS
+# ifdef __cplusplus
+#  define __BEGIN_DECLS  extern "C" {
+#  define __END_DECLS    }
+# else
+#  define __BEGIN_DECLS
+#  define __END_DECLS
+# endif
+#endif
+#ifndef __THROW
+# define __THROW
+#endif
+#ifndef __THROWNL
+# define __THROWNL
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+#ifndef __size_t
+# define __size_t       size_t
+#endif
+#ifndef __USE_GNU
+# define __USE_GNU    1
+#endif
+
+
+#define glob rpl_glob
+#define globfree rpl_globfree
+#define glob_pattern_p rpl_glob_pattern_p
+
+#define __GLOB_GNULIB 1
+
+/* Now the standard GNU C Library header should work.  */
+#include "glob-libc.h"
+
+__BEGIN_DECLS
+typedef int (*_gl_glob_errfunc_fn) (const char *, int);
+__END_DECLS
+
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# undef glob
+# undef globfree
+# undef glob_pattern_p
+_GL_CXXALIAS_RPL (glob, int, (const char *_Restrict_ __pattern, int __flags,
+                              _gl_glob_errfunc_fn __errfunc,
+                              glob_t *_Restrict_ __pglob));
+_GL_CXXALIAS_RPL (globfree, void, (glob_t *__pglob));
+_GL_CXXALIAS_RPL (glob_pattern_p, int, (const char *__pattern, int __quote));
+# if 0  /* The C function name is rpl_glob, not glob.  */
+_GL_CXXALIASWARN (glob);
+_GL_CXXALIASWARN (globfree);
+_GL_CXXALIASWARN (glob_pattern_p);
+# endif
+#endif
+
+#endif /* _GL_GLOB_H */
diff --git a/gdb/gnulib/import/m4/closedir.m4 b/gdb/gnulib/import/m4/closedir.m4
new file mode 100644
index 0000000000..0c9fd82de2
--- /dev/null
+++ b/gdb/gnulib/import/m4/closedir.m4
@@ -0,0 +1,30 @@
+# closedir.m4 serial 5
+dnl Copyright (C) 2011-2016 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_CLOSEDIR],
+[
+  AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
+
+  AC_CHECK_FUNCS([closedir])
+  if test $ac_cv_func_closedir = no; then
+    HAVE_CLOSEDIR=0
+  fi
+  dnl Replace closedir() for supporting the gnulib-defined fchdir() function,
+  dnl to keep fchdir's bookkeeping up-to-date.
+  m4_ifdef([gl_FUNC_FCHDIR], [
+    gl_TEST_FCHDIR
+    if test $HAVE_FCHDIR = 0; then
+      if test $HAVE_CLOSEDIR = 1; then
+        REPLACE_CLOSEDIR=1
+      fi
+    fi
+  ])
+  dnl Replace closedir() for supporting the gnulib-defined dirfd() function.
+  case $host_os,$HAVE_CLOSEDIR in
+    os2*,1)
+      REPLACE_CLOSEDIR=1;;
+  esac
+])
diff --git a/gdb/gnulib/import/m4/d-type.m4 b/gdb/gnulib/import/m4/d-type.m4
new file mode 100644
index 0000000000..eda762c47f
--- /dev/null
+++ b/gdb/gnulib/import/m4/d-type.m4
@@ -0,0 +1,32 @@
+# serial 11
+
+dnl From Jim Meyering.
+dnl
+dnl Check whether struct dirent has a member named d_type.
+dnl
+
+# Copyright (C) 1997, 1999-2004, 2006, 2009-2016 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE],
+  [AC_CACHE_CHECK([for d_type member in directory struct],
+                  gl_cv_struct_dirent_d_type,
+     [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <dirent.h>
+         ]],
+         [[struct dirent dp; dp.d_type = 0;]])],
+       [gl_cv_struct_dirent_d_type=yes],
+       [gl_cv_struct_dirent_d_type=no])
+     ]
+   )
+   if test $gl_cv_struct_dirent_d_type = yes; then
+     AC_DEFINE([HAVE_STRUCT_DIRENT_D_TYPE], [1],
+       [Define if there is a member named d_type in the struct describing
+        directory headers.])
+   fi
+  ]
+)
diff --git a/gdb/gnulib/import/m4/getlogin_r.m4 b/gdb/gnulib/import/m4/getlogin_r.m4
new file mode 100644
index 0000000000..80f82f4f92
--- /dev/null
+++ b/gdb/gnulib/import/m4/getlogin_r.m4
@@ -0,0 +1,88 @@
+#serial 11
+
+# Copyright (C) 2005-2007, 2009-2016 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+dnl From Derek Price
+dnl
+dnl Provide getlogin_r when the system lacks it.
+dnl
+
+AC_DEFUN([gl_FUNC_GETLOGIN_R],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
+  dnl Persuade glibc <unistd.h> to declare getlogin_r().
+  dnl Persuade Solaris <unistd.h> to provide the POSIX compliant declaration of
+  dnl getlogin_r().
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  AC_CHECK_DECLS_ONCE([getlogin_r])
+  if test $ac_cv_have_decl_getlogin_r = no; then
+    HAVE_DECL_GETLOGIN_R=0
+  fi
+
+  AC_CHECK_FUNCS_ONCE([getlogin_r])
+  if test $ac_cv_func_getlogin_r = no; then
+    HAVE_GETLOGIN_R=0
+  else
+    HAVE_GETLOGIN_R=1
+    dnl On OSF/1 5.1, getlogin_r returns a truncated result if the buffer is
+    dnl not large enough.
+    AC_REQUIRE([AC_CANONICAL_HOST])
+    AC_CACHE_CHECK([whether getlogin_r works with small buffers],
+      [gl_cv_func_getlogin_r_works],
+      [
+        dnl Initial guess, used when cross-compiling.
+changequote(,)dnl
+        case "$host_os" in
+                # Guess no on OSF/1.
+          osf*) gl_cv_func_getlogin_r_works="guessing no" ;;
+                # Guess yes otherwise.
+          *)    gl_cv_func_getlogin_r_works="guessing yes" ;;
+        esac
+changequote([,])dnl
+        AC_RUN_IFELSE(
+          [AC_LANG_SOURCE([[
+#include <stddef.h>
+#include <unistd.h>
+#if !HAVE_DECL_GETLOGIN_R
+extern
+# ifdef __cplusplus
+"C"
+# endif
+int getlogin_r (char *, size_t);
+#endif
+int
+main (void)
+{
+  int result = 0;
+  char buf[100];
+
+  if (getlogin_r (buf, 0) == 0)
+    result |= 16;
+  if (getlogin_r (buf, 1) == 0)
+    result |= 17;
+  return result;
+}]])],
+          [gl_cv_func_getlogin_r_works=yes],
+          [case $? in
+             16 | 17) gl_cv_func_getlogin_r_works=no ;;
+           esac
+          ],
+          [:])
+      ])
+    case "$gl_cv_func_getlogin_r_works" in
+      *yes) ;;
+      *) REPLACE_GETLOGIN_R=1 ;;
+    esac
+  fi
+])
+
+AC_DEFUN([gl_PREREQ_GETLOGIN_R],
+[
+  AC_CHECK_DECLS_ONCE([getlogin])
+])
diff --git a/gdb/gnulib/import/m4/glob.m4 b/gdb/gnulib/import/m4/glob.m4
new file mode 100644
index 0000000000..adf5fe2865
--- /dev/null
+++ b/gdb/gnulib/import/m4/glob.m4
@@ -0,0 +1,76 @@
+# glob.m4 serial 14
+dnl Copyright (C) 2005-2007, 2009-2016 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# The glob module assumes you want GNU glob, with glob_pattern_p etc,
+# rather than vanilla POSIX glob.  This means your code should
+# always include <glob.h> for the glob prototypes.
+
+AC_DEFUN([gl_GLOB],
+[ GLOB_H=
+  AC_CHECK_HEADERS([glob.h], [], [GLOB_H=glob.h])
+
+  if test -z "$GLOB_H"; then
+    AC_CACHE_CHECK([for GNU glob interface version 1],
+      [gl_cv_gnu_glob_interface_version_1],
+[     AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+[[#include <gnu-versions.h>
+char a[_GNU_GLOB_INTERFACE_VERSION == 1 ? 1 : -1];]])],
+        [gl_cv_gnu_glob_interface_version_1=yes],
+        [gl_cv_gnu_glob_interface_version_1=no])])
+
+    if test "$gl_cv_gnu_glob_interface_version_1" = "no"; then
+      GLOB_H=glob.h
+    fi
+  fi
+
+  if test -z "$GLOB_H"; then
+    AC_CACHE_CHECK([whether glob lists broken symlinks],
+                   [gl_cv_glob_lists_symlinks],
+[     if ln -s conf-doesntexist conf$$-globtest 2>/dev/null; then
+        gl_cv_glob_lists_symlinks=maybe
+      else
+        # If we can't make a symlink, then we cannot test this issue.  Be
+        # pessimistic about this.
+        gl_cv_glob_lists_symlinks=no
+      fi
+
+      if test $gl_cv_glob_lists_symlinks = maybe; then
+        AC_RUN_IFELSE([
+AC_LANG_PROGRAM(
+[[#include <stddef.h>
+#include <glob.h>]],
+[[glob_t found;
+if (glob ("conf*-globtest", 0, NULL, &found) == GLOB_NOMATCH) return 1;]])],
+          [gl_cv_glob_lists_symlinks=yes],
+          [gl_cv_glob_lists_symlinks=no], [gl_cv_glob_lists_symlinks=no])
+      fi])
+
+    if test $gl_cv_glob_lists_symlinks = no; then
+      GLOB_H=glob.h
+    fi
+  fi
+
+  rm -f conf$$-globtest
+
+  AC_SUBST([GLOB_H])
+  AM_CONDITIONAL([GL_GENERATE_GLOB_H], [test -n "$GLOB_H"])
+])
+
+# Prerequisites of lib/glob.*.
+AC_DEFUN([gl_PREREQ_GLOB],
+[
+  AC_REQUIRE([gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE])dnl
+  AC_REQUIRE([AC_C_RESTRICT])dnl
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])dnl
+  AC_CHECK_HEADERS_ONCE([sys/cdefs.h unistd.h])dnl
+  if test $ac_cv_header_sys_cdefs_h = yes; then
+    HAVE_SYS_CDEFS_H=1
+  else
+    HAVE_SYS_CDEFS_H=0
+  fi
+  AC_SUBST([HAVE_SYS_CDEFS_H])
+  AC_CHECK_FUNCS_ONCE([fstatat getlogin_r getpwnam_r])dnl
+])
diff --git a/gdb/gnulib/import/m4/gnulib-cache.m4 b/gdb/gnulib/import/m4/gnulib-cache.m4
index c4ebb73bfb..b1e6430882 100644
--- a/gdb/gnulib/import/m4/gnulib-cache.m4
+++ b/gdb/gnulib/import/m4/gnulib-cache.m4
@@ -27,7 +27,7 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --lib=libgnu --source-base=import --m4-base=import/m4 --doc-base=doc --tests-base=tests --aux-dir=import/extra --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca canonicalize-lgpl dirent dirfd errno fnmatch-gnu frexpl inttypes limits-h lstat memchr memmem pathmax rawmemchr readlink rename setenv signal-h strchrnul strstr strtok_r sys_stat unistd unsetenv update-copyright wchar wctype-h
+#   gnulib-tool --import --lib=libgnu --source-base=import --m4-base=import/m4 --doc-base=doc --tests-base=tests --aux-dir=import/extra --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca canonicalize-lgpl dirent dirfd errno fnmatch-gnu frexpl glob inttypes limits-h lstat memchr memmem pathmax rawmemchr readlink rename setenv signal-h strchrnul strstr strtok_r sys_stat unistd unsetenv update-copyright wchar wctype-h
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
@@ -39,6 +39,7 @@ gl_MODULES([
   errno
   fnmatch-gnu
   frexpl
+  glob
   inttypes
   limits-h
   lstat
diff --git a/gdb/gnulib/import/m4/gnulib-comp.m4 b/gdb/gnulib/import/m4/gnulib-comp.m4
index 5a3656713d..7f69c95145 100644
--- a/gdb/gnulib/import/m4/gnulib-comp.m4
+++ b/gdb/gnulib/import/m4/gnulib-comp.m4
@@ -47,7 +47,9 @@ AC_DEFUN([gl_EARLY],
   # Code from module alloca-opt:
   # Code from module canonicalize-lgpl:
   # Code from module chdir:
+  # Code from module closedir:
   # Code from module configmake:
+  # Code from module d-type:
   # Code from module dirent:
   # Code from module dirfd:
   # Code from module dirname-lgpl:
@@ -57,6 +59,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module errno:
   # Code from module extensions:
   # Code from module extern-inline:
+  # Code from module filename:
   # Code from module flexmember:
   # Code from module float:
   # Code from module fnmatch:
@@ -66,7 +69,9 @@ AC_DEFUN([gl_EARLY],
   # Code from module fpucw:
   # Code from module frexp:
   # Code from module frexpl:
+  # Code from module getlogin_r:
   # Code from module gettimeofday:
+  # Code from module glob:
   # Code from module hard-locale:
   # Code from module include_next:
   # Code from module inttypes:
@@ -87,10 +92,13 @@ AC_DEFUN([gl_EARLY],
   # Code from module memchr:
   # Code from module memmem:
   # Code from module memmem-simple:
+  # Code from module mempcpy:
   # Code from module multiarch:
   # Code from module nocrash:
+  # Code from module opendir:
   # Code from module pathmax:
   # Code from module rawmemchr:
+  # Code from module readdir:
   # Code from module readlink:
   # Code from module rename:
   # Code from module rmdir:
@@ -152,7 +160,13 @@ AC_DEFUN([gl_INIT],
   gl_STDLIB_MODULE_INDICATOR([canonicalize_file_name])
   gl_STDLIB_MODULE_INDICATOR([realpath])
   gl_UNISTD_MODULE_INDICATOR([chdir])
+  gl_FUNC_CLOSEDIR
+  if test $HAVE_CLOSEDIR = 0 || test $REPLACE_CLOSEDIR = 1; then
+    AC_LIBOBJ([closedir])
+  fi
+  gl_DIRENT_MODULE_INDICATOR([closedir])
   gl_CONFIGMAKE_PREP
+  gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE
   gl_DIRENT_H
   gl_FUNC_DIRFD
   if test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no \
@@ -195,12 +209,23 @@ AC_DEFUN([gl_INIT],
     AC_LIBOBJ([frexpl])
   fi
   gl_MATH_MODULE_INDICATOR([frexpl])
+  gl_FUNC_GETLOGIN_R
+  if test $HAVE_GETLOGIN_R = 0 || test $REPLACE_GETLOGIN_R = 1; then
+    AC_LIBOBJ([getlogin_r])
+    gl_PREREQ_GETLOGIN_R
+  fi
+  gl_UNISTD_MODULE_INDICATOR([getlogin_r])
   gl_FUNC_GETTIMEOFDAY
   if test $HAVE_GETTIMEOFDAY = 0 || test $REPLACE_GETTIMEOFDAY = 1; then
     AC_LIBOBJ([gettimeofday])
     gl_PREREQ_GETTIMEOFDAY
   fi
   gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
+  gl_GLOB
+  if test -n "$GLOB_H"; then
+    AC_LIBOBJ([glob])
+    gl_PREREQ_GLOB
+  fi
   gl_HARD_LOCALE
   gl_INTTYPES_H
   gl_INTTYPES_INCOMPLETE
@@ -266,7 +291,18 @@ AC_DEFUN([gl_INIT],
     AC_LIBOBJ([memmem])
   fi
   gl_STRING_MODULE_INDICATOR([memmem])
+  gl_FUNC_MEMPCPY
+  if test $HAVE_MEMPCPY = 0; then
+    AC_LIBOBJ([mempcpy])
+    gl_PREREQ_MEMPCPY
+  fi
+  gl_STRING_MODULE_INDICATOR([mempcpy])
   gl_MULTIARCH
+  gl_FUNC_OPENDIR
+  if test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1; then
+    AC_LIBOBJ([opendir])
+  fi
+  gl_DIRENT_MODULE_INDICATOR([opendir])
   gl_PATHMAX
   gl_FUNC_RAWMEMCHR
   if test $HAVE_RAWMEMCHR = 0; then
@@ -274,6 +310,11 @@ AC_DEFUN([gl_INIT],
     gl_PREREQ_RAWMEMCHR
   fi
   gl_STRING_MODULE_INDICATOR([rawmemchr])
+  gl_FUNC_READDIR
+  if test $HAVE_READDIR = 0; then
+    AC_LIBOBJ([readdir])
+  fi
+  gl_DIRENT_MODULE_INDICATOR([readdir])
   gl_FUNC_READLINK
   if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
     AC_LIBOBJ([readlink])
@@ -495,13 +536,16 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/alloca.in.h
   lib/basename-lgpl.c
   lib/canonicalize-lgpl.c
+  lib/closedir.c
   lib/config.charset
+  lib/dirent-private.h
   lib/dirent.in.h
   lib/dirfd.c
   lib/dirname-lgpl.c
   lib/dirname.h
   lib/dosname.h
   lib/errno.in.h
+  lib/filename.h
   lib/flexmember.h
   lib/float+.h
   lib/float.c
@@ -512,7 +556,11 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/fpucw.h
   lib/frexp.c
   lib/frexpl.c
+  lib/getlogin_r.c
   lib/gettimeofday.c
+  lib/glob-libc.h
+  lib/glob.c
+  lib/glob.in.h
   lib/hard-locale.c
   lib/hard-locale.h
   lib/inttypes.in.h
@@ -540,9 +588,12 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/memchr.c
   lib/memchr.valgrind
   lib/memmem.c
+  lib/mempcpy.c
+  lib/opendir.c
   lib/pathmax.h
   lib/rawmemchr.c
   lib/rawmemchr.valgrind
+  lib/readdir.c
   lib/readlink.c
   lib/ref-add.sin
   lib/ref-del.sin
@@ -582,8 +633,10 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/absolute-header.m4
   m4/alloca.m4
   m4/canonicalize.m4
+  m4/closedir.m4
   m4/codeset.m4
   m4/configmake.m4
+  m4/d-type.m4
   m4/dirent_h.m4
   m4/dirfd.m4
   m4/dirname.m4
@@ -602,8 +655,10 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/fpieee.m4
   m4/frexp.m4
   m4/frexpl.m4
+  m4/getlogin_r.m4
   m4/gettimeofday.m4
   m4/glibc21.m4
+  m4/glob.m4
   m4/gnulib-common.m4
   m4/hard-locale.m4
   m4/include_next.m4
@@ -628,12 +683,15 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/mbstate_t.m4
   m4/memchr.m4
   m4/memmem.m4
+  m4/mempcpy.m4
   m4/mmap-anon.m4
   m4/multiarch.m4
   m4/nocrash.m4
   m4/off_t.m4
+  m4/opendir.m4
   m4/pathmax.m4
   m4/rawmemchr.m4
+  m4/readdir.m4
   m4/readlink.m4
   m4/rename.m4
   m4/rmdir.m4
diff --git a/gdb/gnulib/import/m4/mempcpy.m4 b/gdb/gnulib/import/m4/mempcpy.m4
new file mode 100644
index 0000000000..6991f29f03
--- /dev/null
+++ b/gdb/gnulib/import/m4/mempcpy.m4
@@ -0,0 +1,26 @@
+# mempcpy.m4 serial 11
+dnl Copyright (C) 2003-2004, 2006-2007, 2009-2016 Free Software Foundation,
+dnl Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_MEMPCPY],
+[
+  dnl Persuade glibc <string.h> to declare mempcpy().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  dnl The mempcpy() declaration in lib/string.in.h uses 'restrict'.
+  AC_REQUIRE([AC_C_RESTRICT])
+
+  AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+  AC_CHECK_FUNCS([mempcpy])
+  if test $ac_cv_func_mempcpy = no; then
+    HAVE_MEMPCPY=0
+  fi
+])
+
+# Prerequisites of lib/mempcpy.c.
+AC_DEFUN([gl_PREREQ_MEMPCPY], [
+  :
+])
diff --git a/gdb/gnulib/import/m4/opendir.m4 b/gdb/gnulib/import/m4/opendir.m4
new file mode 100644
index 0000000000..ffaa6ae3ba
--- /dev/null
+++ b/gdb/gnulib/import/m4/opendir.m4
@@ -0,0 +1,31 @@
+# opendir.m4 serial 4
+dnl Copyright (C) 2011-2016 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_OPENDIR],
+[
+  AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
+
+  AC_CHECK_FUNCS([opendir])
+  if test $ac_cv_func_opendir = no; then
+    HAVE_OPENDIR=0
+  fi
+  dnl Replace opendir() for supporting the gnulib-defined fchdir() function,
+  dnl to keep fchdir's bookkeeping up-to-date.
+  m4_ifdef([gl_FUNC_FCHDIR], [
+    gl_TEST_FCHDIR
+    if test $HAVE_FCHDIR = 0; then
+      if test $HAVE_OPENDIR = 1; then
+        REPLACE_OPENDIR=1
+      fi
+    fi
+  ])
+  dnl Replace opendir() on OS/2 kLIBC to support dirfd() function replaced
+  dnl by gnulib.
+  case $host_os,$HAVE_OPENDIR in
+    os2*,1)
+      REPLACE_OPENDIR=1;;
+  esac
+])
diff --git a/gdb/gnulib/import/m4/readdir.m4 b/gdb/gnulib/import/m4/readdir.m4
new file mode 100644
index 0000000000..eda3acf73d
--- /dev/null
+++ b/gdb/gnulib/import/m4/readdir.m4
@@ -0,0 +1,15 @@
+# readdir.m4 serial 1
+dnl Copyright (C) 2011-2016 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_READDIR],
+[
+  AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
+
+  AC_CHECK_FUNCS([readdir])
+  if test $ac_cv_func_readdir = no; then
+    HAVE_READDIR=0
+  fi
+])
diff --git a/gdb/gnulib/import/mempcpy.c b/gdb/gnulib/import/mempcpy.c
new file mode 100644
index 0000000000..d579f64a0a
--- /dev/null
+++ b/gdb/gnulib/import/mempcpy.c
@@ -0,0 +1,28 @@
+/* Copy memory area and return pointer after last written byte.
+   Copyright (C) 2003, 2007, 2009-2016 Free Software Foundation, Inc.
+
+   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, 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 <config.h>
+
+/* Specification.  */
+#include <string.h>
+
+/* Copy N bytes of SRC to DEST, return pointer to bytes after the
+   last written byte.  */
+void *
+mempcpy (void *dest, const void *src, size_t n)
+{
+  return (char *) memcpy (dest, src, n) + n;
+}
diff --git a/gdb/gnulib/import/opendir.c b/gdb/gnulib/import/opendir.c
new file mode 100644
index 0000000000..a135fd834a
--- /dev/null
+++ b/gdb/gnulib/import/opendir.c
@@ -0,0 +1,169 @@
+/* Start reading the entries of a directory.
+   Copyright (C) 2006-2016 Free Software Foundation, Inc.
+
+   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 <config.h>
+
+/* Specification.  */
+#include <dirent.h>
+
+#include <errno.h>
+#include <stddef.h>
+
+#if HAVE_OPENDIR
+
+/* Override opendir(), to keep track of the open file descriptors.
+   Needed because there is a function dirfd().  */
+
+#else
+
+# include <stdlib.h>
+
+# include "dirent-private.h"
+# include "filename.h"
+
+#endif
+
+#if REPLACE_FCHDIR
+# include <unistd.h>
+#endif
+
+#ifdef __KLIBC__
+# include <io.h>
+# include <fcntl.h>
+#endif
+
+DIR *
+opendir (const char *dir_name)
+{
+#if HAVE_OPENDIR
+# undef opendir
+  DIR *dirp;
+
+  dirp = opendir (dir_name);
+  if (dirp == NULL)
+    return NULL;
+
+# ifdef __KLIBC__
+  {
+    int fd = open (dir_name, O_RDONLY);
+    if (fd == -1 || _gl_register_dirp_fd (fd, dirp))
+      {
+        int saved_errno = errno;
+
+        close (fd);
+        closedir (dirp);
+
+        errno = saved_errno;
+
+        return NULL;
+      }
+  }
+# endif
+#else
+
+  char dir_name_mask[MAX_PATH + 1 + 1 + 1];
+  int status;
+  HANDLE current;
+  WIN32_FIND_DATA entry;
+  struct gl_directory *dirp;
+
+  if (dir_name[0] == '\0')
+    {
+      errno = ENOENT;
+      return NULL;
+    }
+
+  /* Make the dir_name absolute, so that we continue reading the same
+     directory if the current directory changed between this opendir()
+     call and a subsequent rewinddir() call.  */
+  if (!GetFullPathName (dir_name, MAX_PATH, dir_name_mask, NULL))
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  /* Append the mask.
+     "*" and "*.*" appear to be equivalent.  */
+  {
+    char *p;
+
+    p = dir_name_mask + strlen (dir_name_mask);
+    if (p > dir_name_mask && !ISSLASH (p[-1]))
+      *p++ = '\\';
+    *p++ = '*';
+    *p = '\0';
+  }
+
+  /* Start searching the directory.  */
+  status = -1;
+  current = FindFirstFile (dir_name_mask, &entry);
+  if (current == INVALID_HANDLE_VALUE)
+    {
+      switch (GetLastError ())
+        {
+        case ERROR_FILE_NOT_FOUND:
+          status = -2;
+          break;
+        case ERROR_PATH_NOT_FOUND:
+          errno = ENOENT;
+          return NULL;
+        case ERROR_DIRECTORY:
+          errno = ENOTDIR;
+          return NULL;
+        case ERROR_ACCESS_DENIED:
+          errno = EACCES;
+          return NULL;
+        default:
+          errno = EIO;
+          return NULL;
+        }
+    }
+
+  /* Allocate the result.  */
+  dirp =
+    (struct gl_directory *)
+    malloc (offsetof (struct gl_directory, dir_name_mask[0])
+            + strlen (dir_name_mask) + 1);
+  if (dirp == NULL)
+    {
+      if (current != INVALID_HANDLE_VALUE)
+        FindClose (current);
+      errno = ENOMEM;
+      return NULL;
+    }
+  dirp->status = status;
+  dirp->current = current;
+  if (status == -1)
+    memcpy (&dirp->entry, &entry, sizeof (WIN32_FIND_DATA));
+  strcpy (dirp->dir_name_mask, dir_name_mask);
+
+#endif
+
+#if REPLACE_FCHDIR
+  {
+    int fd = dirfd (dirp);
+    if (0 <= fd && _gl_register_fd (fd, dir_name) != fd)
+      {
+        int saved_errno = errno;
+        closedir (dirp);
+        errno = saved_errno;
+        return NULL;
+      }
+  }
+#endif
+
+  return dirp;
+}
diff --git a/gdb/gnulib/import/readdir.c b/gdb/gnulib/import/readdir.c
new file mode 100644
index 0000000000..76b7e9d819
--- /dev/null
+++ b/gdb/gnulib/import/readdir.c
@@ -0,0 +1,98 @@
+/* Read the next entry of a directory.
+   Copyright (C) 2011-2016 Free Software Foundation, Inc.
+
+   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 <config.h>
+
+/* Specification.  */
+#include <dirent.h>
+
+#include <errno.h>
+#include <stddef.h>
+
+#include "dirent-private.h"
+
+struct dirent *
+readdir (DIR *dirp)
+{
+  char type;
+  struct dirent *result;
+
+  /* There is no need to add code to produce entries for "." and "..".
+     According to the POSIX:2008 section "4.12 Pathname Resolution"
+     <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html>
+     "." and ".." are syntactic entities.
+     POSIX also says:
+       "If entries for dot or dot-dot exist, one entry shall be returned
+        for dot and one entry shall be returned for dot-dot; otherwise,
+        they shall not be returned."  */
+
+  switch (dirp->status)
+    {
+    case -2:
+      /* End of directory already reached.  */
+      return NULL;
+    case -1:
+      break;
+    case 0:
+      if (!FindNextFile (dirp->current, &dirp->entry))
+        {
+          switch (GetLastError ())
+            {
+            case ERROR_NO_MORE_FILES:
+              dirp->status = -2;
+              return NULL;
+            default:
+              errno = EIO;
+              return NULL;
+            }
+        }
+      break;
+    default:
+      errno = dirp->status;
+      return NULL;
+    }
+
+  dirp->status = 0;
+
+  if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+    type = DT_DIR;
+  else if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+    type = DT_LNK;
+  else if ((dirp->entry.dwFileAttributes
+            & ~(FILE_ATTRIBUTE_READONLY
+                | FILE_ATTRIBUTE_HIDDEN
+                | FILE_ATTRIBUTE_SYSTEM
+                | FILE_ATTRIBUTE_ARCHIVE
+                | FILE_ATTRIBUTE_NORMAL
+                | FILE_ATTRIBUTE_TEMPORARY
+                | FILE_ATTRIBUTE_SPARSE_FILE
+                | FILE_ATTRIBUTE_COMPRESSED
+                | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
+                | FILE_ATTRIBUTE_ENCRYPTED)) == 0)
+    /* Devices like COM1, LPT1, NUL would also have the attributes 0x20 but
+       they cannot occur here.  */
+    type = DT_REG;
+  else
+    type = DT_UNKNOWN;
+
+  /* Reuse the memory of dirp->entry for the result.  */
+  result =
+    (struct dirent *)
+    ((char *) dirp->entry.cFileName - offsetof (struct dirent, d_name[0]));
+  result->d_type = type;
+
+  return result;
+}
diff --git a/gdb/gnulib/update-gnulib.sh b/gdb/gnulib/update-gnulib.sh
index 2775dc7338..ccf603fceb 100755
--- a/gdb/gnulib/update-gnulib.sh
+++ b/gdb/gnulib/update-gnulib.sh
@@ -37,6 +37,7 @@ IMPORTED_GNULIB_MODULES="\
     errno \
     fnmatch-gnu \
     frexpl \
+    glob \
     inttypes \
     lstat \
     limits-h \
-- 
2.13.3

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

* [PATCH 4/4] Implement "set cwd" command
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
@ 2017-09-12  4:23 ` Sergio Durigan Junior
  2017-09-12 14:50   ` Eli Zaretskii
  2017-09-12  4:23 ` [PATCH 3/4] Introduce gdb_chdir Sergio Durigan Junior
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-12  4:23 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This is the actual implementation of the "set/show cwd" commands.  The
way they work is:

- If the user sets the inferior's cwd by using "set cwd", then this
  directory is saved into current_inferior ()->cwd and is used when
  the inferior is started (see below).

- If the user doesn't set the inferior's cwd by using "set cwd", but
  rather use the "cd" command as before, the this directory is
  inherited by the inferior because GDB will have chdir'd into it.

The way the directory is changed before the inferior execution is by
calling "gdb_chdir" after the call to fork/vfork on "fork_inferior",
but before the actual execution.  This way, we'll make sure that GDB's
cwd is not affected by the user set cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (New commands): Mention "set/show cwd".
	* cli/cli-cmds.c (_initialize_cli_cmds): Mention "set cwd" on
	"cd" command's help text.
	* common/common-inferior.h (get_inferior_cwd): New prototype.
	* infcmd.c: Include "gdb_chdir.h" and "readline/tilde.h".
	(inferior_cwd_scratch): New global variable.
	(set_inferior_cwd): New function.
	(get_inferior_cwd): Likewise.
	(set_cwd_command): Likewise.
	(show_cwd_command): Likewise.
	(_initialize_infcmd): Add "set/show cwd" commands.
	* inferior.h (class inferior) <cwd>: New field.
	* nat/fork-inferior.c: Include "gdb_chdir.h".
	(fork_inferior): Change inferior's cwd before its execution.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (get_inferior_cwd): New function.
	* inferiors.h (struct process_info) <cwd>: New field.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (The working directory): Mention new "set cwd"
	command.
	(Your Program's Working Directory): Likewise.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.c: New file.
	* gdb.base/set-cwd.exp: Likewise.
---
 gdb/NEWS                           |  3 ++
 gdb/cli/cli-cmds.c                 |  6 +--
 gdb/common/common-inferior.h       |  4 ++
 gdb/doc/gdb.texinfo                | 25 +++++++++--
 gdb/gdbserver/inferiors.c          | 11 +++++
 gdb/infcmd.c                       | 75 +++++++++++++++++++++++++++++++
 gdb/inferior.h                     |  4 ++
 gdb/nat/fork-inferior.c            | 17 +++++++
 gdb/testsuite/gdb.base/set-cwd.c   | 29 ++++++++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 90 ++++++++++++++++++++++++++++++++++++++
 10 files changed, 257 insertions(+), 7 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.c
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 2e6d48c016..bf81ce0270 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -61,6 +61,9 @@ QStartupWithShell
 
 * New commands
 
+set|show cwd
+  Set and show the current working directory for the inferior.
+
 set|show compile-gcc
   Set and show compilation command used for compiling and injecting code
   with the 'compile' commands.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 64e893c784..57975fc587 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1716,9 +1716,9 @@ The commands below can be used to select other frames by number or address."),
 Print working directory.  This is used for your program as well."));
 
   c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_com ("echo", class_support, echo_command, _("\
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 87c13009ed..515a8c0f4e 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
    otherwise return 0 in that case.  */
 extern char *get_exec_file (int err);
 
+/* Return the inferior's current working directory.  If nothing has
+   been set, then return NULL.  */
+extern const char *get_inferior_cwd ();
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 8282dae7c3..14f85f97fd 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2057,10 +2057,11 @@ environment} to change parts of the environment that affect
 your program.  @xref{Environment, ,Your Program's Environment}.
 
 @item The @emph{working directory.}
-Your program inherits its working directory from @value{GDBN}.  You can set
-the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+Your program inherits its working directory from @value{GDBN}.  This
+can be changed by using the @code{set cwd} command in @value{GDBN}.
 @xref{Working Directory, ,Your Program's Working Directory}.
 
+
 @item The @emph{standard input and output.}
 Your program normally uses the same device for standard input and
 standard output as @value{GDBN} is using.  You can redirect input and output
@@ -2427,14 +2428,30 @@ variables to files that are only run when you sign on, such as
 Each time you start your program with @code{run}, it inherits its
 working directory from the current working directory of @value{GDBN}.
 The @value{GDBN} working directory is initially whatever it inherited
-from its parent process (typically the shell), but you can specify a new
-working directory in @value{GDBN} with the @code{cd} command.
+from its parent process (typically the shell), but you can specify a
+new working directory in @value{GDBN} with the @code{cd} command.  You
+can specify a working directory especifically for the inferior with
+the @code{set cwd} command.
 
 The @value{GDBN} working directory also serves as a default for the commands
 that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
 Specify Files}.
 
 @table @code
+@kindex set cwd
+@cindex change inferior's working directory
+@item set cwd @r{[}@var{directory}@r{]}
+Set the inferior's working directory to @var{directory}.  If not
+given, @var{directory} uses @file{'~'}.  This has no effect on
+@value{GDBN}'s working directory.
+
+@kindex show cwd
+@cindex show inferior's working directory
+@item show cwd
+Show the inferior's working directory.  If no directory has been
+specified by @code{set cwd}, then the default inferior's working
+directory is the same as @value{GDBN}'s working directory.
+
 @kindex cd
 @cindex change working directory
 @item cd @r{[}@var{directory}@r{]}
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 3c171a179e..47307c913e 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -29,6 +29,9 @@ struct thread_info *current_thread;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
 
+/* The current working directory used to start the inferior.  */
+static const char *current_inferior_cwd = NULL;
+
 void
 add_inferior_to_list (struct inferior_list *list,
 		      struct inferior_list_entry *new_inferior)
@@ -471,3 +474,11 @@ switch_to_thread (ptid_t ptid)
   if (!ptid_equal (ptid, minus_one_ptid))
     current_thread = find_thread_ptid (ptid);
 }
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior_cwd;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 25cf025426..804bb25101 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -59,6 +59,8 @@
 #include "top.h"
 #include "interps.h"
 #include "common/gdb_optional.h"
+#include "gdb_chdir.h"
+#include "readline/tilde.h"
 
 /* Local functions: */
 
@@ -111,6 +113,10 @@ static void run_command (char *, int);
 
 static char *inferior_args_scratch;
 
+/* Scratch area where the new cwd will be stored by 'set cwd'.  */
+
+static char *inferior_cwd_scratch;
+
 /* Scratch area where 'set inferior-tty' will store user-provided value.
    We'll immediate copy it into per-inferior storage.  */
 
@@ -246,6 +252,56 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
+/* Set the inferior current working directory.  This directory will be
+   entered by GDB before executing the inferior.  */
+
+static void
+set_inferior_cwd (const char *cwd)
+{
+  struct inferior *inf = current_inferior ();
+
+  gdb_assert (inf != NULL);
+  xfree ((void *) inf->cwd);
+  inf->cwd = tilde_expand (*cwd != '\0' ? cwd : "~");
+}
+
+/* See inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior ()->cwd;
+}
+
+/* Handle the 'set cwd' command.  */
+
+static void
+set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+{
+  set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command.  */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  const char *cwd = get_inferior_cwd ();
+
+  if (cwd == NULL)
+    {
+      /* To maintain backwards compatibility, we use
+	 'current_directory' here, which is set by the "cd"
+	 command.  */
+      cwd = current_directory;
+    }
+
+  fprintf_filtered (gdb_stdout,
+		    _("Current working directory that will be used "
+		      "when starting the inferior is \"%s\".\n"), cwd);
+}
+
 \f
 /* Compute command-line string given argument vector.  This does the
    same shell processing as fork_inferior.  */
@@ -3214,6 +3270,25 @@ Follow this command with any number of args, to be passed to the program."),
   gdb_assert (c != NULL);
   set_cmd_completer (c, filename_completer);
 
+  cmd_name = "cwd";
+  add_setshow_string_noescape_cmd (cmd_name, class_run,
+				   &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+				   _("\
+Show the current working directory that is used when the inferior is started."),
+				   _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started.  This setting does not affect GDB's current\n\
+working directory."),
+				   set_cwd_command,
+				   show_cwd_command,
+				   &setlist, &showlist);
+  c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+  gdb_assert (c != NULL);
+  set_cmd_completer (c, filename_completer);
+
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
 With an argument VAR, prints the value of environment variable VAR to\n\
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 6d020f73c4..bcd1e54a03 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -355,6 +355,10 @@ public:
      should never be freed.  */
   char **argv = NULL;
 
+  /* The current working directory that will be used when starting
+     this inferior.  */
+  const char *cwd = NULL;
+
   /* The name of terminal device to use for I/O.  */
   char *terminal = NULL;
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 0913409e6d..6ff0c2d216 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -25,6 +25,7 @@
 #include "common-inferior.h"
 #include "common-gdbthread.h"
 #include "signals-state-save-restore.h"
+#include "gdb_chdir.h"
 #include <vector>
 
 extern char **environ;
@@ -376,6 +377,22 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
 	 UIs.  */
       close_most_fds ();
 
+      const char *cwd = get_inferior_cwd ();
+
+      if (cwd != NULL)
+	{
+	  TRY
+	    {
+	      gdb_chdir (cwd);
+	    }
+	  CATCH (ex, RETURN_MASK_ERROR)
+	    {
+	      warning ("%s", ex.message);
+	      _exit (0177);
+	    }
+	  END_CATCH
+	}
+
       if (debug_fork)
 	sleep (debug_fork);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.c b/gdb/testsuite/gdb.base/set-cwd.c
new file mode 100644
index 0000000000..488fc4e4e3
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 Free Software Foundation, Inc.
+
+   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 <stdio.h>
+#include <unistd.h>
+
+int
+main (int argc, char *argv[])
+{
+  char dir[BUFSIZ];
+
+  getcwd (dir, BUFSIZ);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
new file mode 100644
index 0000000000..3a6ffd3862
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -0,0 +1,90 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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/>.
+
+if { ![isnative] || [is_remote target] || [is_remote host]
+     || [target_info gdb_protocol] == "extended-remote" } then {
+    untested "not implemented on gdbserver"
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    return -1
+}
+
+# Test that tilde expansion works fine.
+
+proc test_tilde_expansion { } {
+    if { [info exists ::env(HOME)] } {
+	with_test_prefix "test tilde expansion" {
+	    set home $::env(HOME)
+
+	    gdb_test_no_output "set cwd ~/test" "set cwd to ~/test dir"
+
+	    gdb_test "show cwd" \
+		"Current working directory that will be used when starting the inferior is \"${home}/test\"\." \
+		"show cwd shows expanded tilde"
+	}
+    }
+}
+
+# Test that when we "set cwd" the inferior will be started under the
+# correct working directory and GDB will not be affected by this.
+
+proc test_cd_into_dir { } {
+    global decimal gdb_prompt
+
+    with_test_prefix "test cd into temp dir" {
+	gdb_test_multiple "pwd" "pwd before run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_before_run $expect_out(1,string)
+	    }
+	}
+
+	set tmpdir [standard_output_file ""]
+
+	gdb_test_no_output "set cwd $tmpdir" "set cwd to temp dir"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	    "inferior cwd is correctly set"
+
+	gdb_test_multiple "pwd" "pwd after run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_after_run $expect_out(1,string)
+	    }
+	}
+
+	set test "GDB cwd is unchanged after running inferior"
+	if { [string equal $gdb_cwd_before_run $gdb_cwd_after_run] } {
+	    pass $test
+	} else {
+	    fail $test
+	}
+    }
+}
+
+test_cd_into_dir
+test_tilde_expansion
-- 
2.13.3

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

* Re: [PATCH 4/4] Implement "set cwd" command
  2017-09-12  4:23 ` [PATCH 4/4] Implement " Sergio Durigan Junior
@ 2017-09-12 14:50   ` Eli Zaretskii
  0 siblings, 0 replies; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-12 14:50 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: Pedro Alves <palves@redhat.com>,	Sergio Durigan Junior <sergiodj@redhat.com>
> Date: Tue, 12 Sep 2017 00:23:25 -0400
> 
>  Each time you start your program with @code{run}, it inherits its
>  working directory from the current working directory of @value{GDBN}.
>  The @value{GDBN} working directory is initially whatever it inherited
> -from its parent process (typically the shell), but you can specify a new
> -working directory in @value{GDBN} with the @code{cd} command.
> +from its parent process (typically the shell), but you can specify a
> +new working directory in @value{GDBN} with the @code{cd} command.  You
> +can specify a working directory especifically for the inferior with
                                   ^^^^^^^^^^^^^
A typo.

> +Set the inferior's working directory to @var{directory}.  If not
> +given, @var{directory} uses @file{'~'}.  This has no effect on

The quotes inside @file are redundant, please drop them.

Otherwise, the documentation parts are OK, thanks.

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

* Re: [PATCH 3/4] Introduce gdb_chdir
  2017-09-12  4:23 ` [PATCH 3/4] Introduce gdb_chdir Sergio Durigan Junior
@ 2017-09-12 14:53   ` Eli Zaretskii
  2017-09-13 23:00     ` Sergio Durigan Junior
  2017-09-13 16:07   ` Pedro Alves
  1 sibling, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-12 14:53 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: Pedro Alves <palves@redhat.com>,	Sergio Durigan Junior <sergiodj@redhat.com>
> Date: Tue, 12 Sep 2017 00:23:24 -0400
> 
> In order to be able to change the inferior's directory before its
> execution, it is necessary to perform a tilde expansion of the
> directory provided by the user and then chdir into the resulting dir.
> This is what gdb_chdir does.
> 
> Unfortunately it is not possible to use "tilde_expand" from readline
> because this is common code and gdbserver doesn't use readline.  For
> that reason I decided to go with "glob" and its GNU extension,
> GLOB_TILDE.  With the import of the "glob" module from gnulib, this is
> a no-brainer.

Why not simply 'getenv("HOME")'?

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
                   ` (3 preceding siblings ...)
  2017-09-12  4:23 ` [PATCH 1/4] Make gdb_dirbuf local to functions Sergio Durigan Junior
@ 2017-09-12 14:55 ` Eli Zaretskii
  2017-09-12 16:48   ` Sergio Durigan Junior
  2017-09-13 14:54 ` Pedro Alves
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-12 14:55 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: Pedro Alves <palves@redhat.com>
> Date: Tue, 12 Sep 2017 00:23:21 -0400
> 
> This patch series is a followup of the discussion that happened at:
> 
>   https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html
> 
> It implements a new GDB command, "set cwd", which is used to set the
> current working directory of the inferior that will be started.  This
> is a GDB-only command for now; its gdbserver counterpart will come
> later.

Can you summarize the idea, please?  (I didn't follow that
discussion.)  Do we chdir into that directory each time before we
run/resume the debuggee?  Or do we use the shell (in which case this
is limited to Posix hosts)?  Or something else?

Thanks.

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-12 14:55 ` [PATCH 0/4] New "set cwd" command Eli Zaretskii
@ 2017-09-12 16:48   ` Sergio Durigan Junior
  2017-09-12 16:57     ` Eli Zaretskii
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-12 16:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Tuesday, September 12 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: Pedro Alves <palves@redhat.com>
>> Date: Tue, 12 Sep 2017 00:23:21 -0400
>> 
>> This patch series is a followup of the discussion that happened at:
>> 
>>   https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html
>> 
>> It implements a new GDB command, "set cwd", which is used to set the
>> current working directory of the inferior that will be started.  This
>> is a GDB-only command for now; its gdbserver counterpart will come
>> later.
>
> Can you summarize the idea, please?  (I didn't follow that
> discussion.)  Do we chdir into that directory each time before we
> run/resume the debuggee?  Or do we use the shell (in which case this
> is limited to Posix hosts)?  Or something else?

Sure.

The idea is that there are other inferior commands already, like "set
args" or "set environment", which function per-inferior.  However, the
current "cd" command doesn't, and this is not only a discrepancy but
also gets in the way of a future feature that will implemented: the
ability to tell gdbserver to cd into another directory before starting
the remote inferior.

GDB's cd_command uses chdir, but also uses tilde_expand, from readline,
to expand the path given by the user.  It also runs right when the user
invokes "cd" from the CLI.

The new "set cwd" command also uses chdir (i.e., no shell involved), but
because it is shared code between GDB and gdbserver, and because
gdbserver doesn't link against readline, it cannot use tilde_expand.
Therefore I had to import the "glob" module from gnulib. And also, this
specific chdir is only invoked after the call to fork/vfork on
fork_inferior, but before we actually execute the binary.

I hope I could clarify this for you, but please let me know if you have
more questions.

Thanks,

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

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-12 16:48   ` Sergio Durigan Junior
@ 2017-09-12 16:57     ` Eli Zaretskii
  2017-09-12 17:51       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-12 16:57 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: gdb-patches@sourceware.org,  palves@redhat.com
> Date: Tue, 12 Sep 2017 12:48:05 -0400
> 
> The new "set cwd" command also uses chdir (i.e., no shell involved), but
> because it is shared code between GDB and gdbserver, and because
> gdbserver doesn't link against readline, it cannot use tilde_expand.
> Therefore I had to import the "glob" module from gnulib. And also, this
> specific chdir is only invoked after the call to fork/vfork on
> fork_inferior, but before we actually execute the binary.

Thanks.

The last bit means that this will only work for targets that use
fork/vfork, i.e. only for Posix targets.  Right?

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-12 16:57     ` Eli Zaretskii
@ 2017-09-12 17:51       ` Sergio Durigan Junior
  2017-09-13 15:00         ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-12 17:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Tuesday, September 12 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: gdb-patches@sourceware.org,  palves@redhat.com
>> Date: Tue, 12 Sep 2017 12:48:05 -0400
>> 
>> The new "set cwd" command also uses chdir (i.e., no shell involved), but
>> because it is shared code between GDB and gdbserver, and because
>> gdbserver doesn't link against readline, it cannot use tilde_expand.
>> Therefore I had to import the "glob" module from gnulib. And also, this
>> specific chdir is only invoked after the call to fork/vfork on
>> fork_inferior, but before we actually execute the binary.
>
> Thanks.
>
> The last bit means that this will only work for targets that use
> fork/vfork, i.e. only for Posix targets.  Right?

Well, the way it's implemented, yes.  AFAIK there's nothing preventing
this feature to be implemented in non-vfork targets like Windows, except
the fact that I don't have access to those targets to test.

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

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
                   ` (4 preceding siblings ...)
  2017-09-12 14:55 ` [PATCH 0/4] New "set cwd" command Eli Zaretskii
@ 2017-09-13 14:54 ` Pedro Alves
  2017-09-13 21:54   ` Sergio Durigan Junior
  2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-13 14:54 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:
> This patch series is a followup of the discussion that happened at:
> 
>   https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html
> 
> It implements a new GDB command, "set cwd", which is used to set the
> current working directory of the inferior that will be started.  This
> is a GDB-only command for now; its gdbserver counterpart will come
> later.

I think I'd prefer that the gdbserver counterpart was included
as part of the same series.  I.e., I'd like to see the gdbserver
side explored first before we change the native side and commit
to the commands/interface.  Also, I think that would help make
sure that the manual documentation is adjusted in a way that
naturally reads as applying to local and remote.

For example, we currently say

 "Each time you start your program with @code{run}, it inherits its 
 working directory from the current working directory of
 @value{GDBN}.", 

but you didn't change that particular sentence, which seems to leave
it a bit incorrect.  I think we should say instead say that
when you start your program with run, the inferior starts with
the directory specified by "set cwd", and then mention that
if that is not set, then the inferior inherits gdb's current
directory if native debugging, and gdbserver's if remote debugging.
Right?

Thanks,
Pedro Alves

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-12 17:51       ` Sergio Durigan Junior
@ 2017-09-13 15:00         ` Pedro Alves
  2017-09-13 15:06           ` Eli Zaretskii
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-13 15:00 UTC (permalink / raw)
  To: Sergio Durigan Junior, Eli Zaretskii; +Cc: gdb-patches


On 09/12/2017 06:51 PM, Sergio Durigan Junior wrote:
> On Tuesday, September 12 2017, Eli Zaretskii wrote:
> 
>>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>>> Cc: gdb-patches@sourceware.org,  palves@redhat.com
>>> Date: Tue, 12 Sep 2017 12:48:05 -0400
>>>
>>> The new "set cwd" command also uses chdir (i.e., no shell involved), but
>>> because it is shared code between GDB and gdbserver, and because
>>> gdbserver doesn't link against readline, it cannot use tilde_expand.
>>> Therefore I had to import the "glob" module from gnulib. And also, this
>>> specific chdir is only invoked after the call to fork/vfork on
>>> fork_inferior, but before we actually execute the binary.
>>
>> Thanks.
>>
>> The last bit means that this will only work for targets that use
>> fork/vfork, i.e. only for Posix targets.  Right?
> 
> Well, the way it's implemented, yes.  AFAIK there's nothing preventing
> this feature to be implemented in non-vfork targets like Windows, except
> the fact that I don't have access to those targets to test.

I think that to make "set cwd" work on Windows, gdb would be adjusted to
pass the desired current directory as argument to CreateProcess, here:

  https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/windows-nat.c;h=ab5582d46cf3a0873ab32d9c955e95ee75371d4e;hb=HEAD#l2570

(and the equivalent in gdbserver).

From <https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx>:

~~~     
lpCurrentDirectory [in, optional]

    The full path to the current directory for the process. The string can also specify a UNC path.

    If this parameter is NULL, the new process will have the same current drive and directory as the calling process. (This feature is provided primarily for shells that need to start an application and specify its initial drive and working directory.)
~~~     

Thanks,
Pedro Alves

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-13 15:00         ` Pedro Alves
@ 2017-09-13 15:06           ` Eli Zaretskii
  2017-09-13 21:56             ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-13 15:06 UTC (permalink / raw)
  To: Pedro Alves; +Cc: sergiodj, gdb-patches

> Cc: gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Wed, 13 Sep 2017 15:59:52 +0100
> 
> >> The last bit means that this will only work for targets that use
> >> fork/vfork, i.e. only for Posix targets.  Right?
> > 
> > Well, the way it's implemented, yes.  AFAIK there's nothing preventing
> > this feature to be implemented in non-vfork targets like Windows, except
> > the fact that I don't have access to those targets to test.
> 
> I think that to make "set cwd" work on Windows, gdb would be adjusted to
> pass the desired current directory as argument to CreateProcess, here:
> 
>   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/windows-nat.c;h=ab5582d46cf3a0873ab32d9c955e95ee75371d4e;hb=HEAD#l2570
> 
> (and the equivalent in gdbserver).

Yes.

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

* Re: [PATCH 1/4] Make gdb_dirbuf local to functions
  2017-09-12  4:23 ` [PATCH 1/4] Make gdb_dirbuf local to functions Sergio Durigan Junior
@ 2017-09-13 15:12   ` Pedro Alves
  2017-09-13 22:03     ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-13 15:12 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:
> This is not a requirement for the feature, but I think it's a good
> cleanup and is related anyway.  Currently we have "current_directory"
> and "gdb_dirbuf" globals, which means that we basically have two
> possible places to consult when we want to know GDB's current working
> directory.
> 
> This is not ideal and can lead to confusion, so my proposal is to
> "internalize" the "gdb_dirbuf" variable, because it is really just
> that: a buffer to be used when calling "getcwd".  With this, only
> "current_directory" should be used to determine the cwd.
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* cli/cli-cmds.c (quit_command): Declare "gdb_dirbuf".
> 	(cd_command): Free "current_directory" before assigning to it.
> 	* main.c (captured_main_1): Likewise.  Call "xstrdup" when
> 	storing it on "current_directory".
> 	* mi/mi-cmd-env.c (mi_cmd_env_pwd): Declare "gdb_dirbuf".
> 	* top.c (gdb_dirbuf): Remove global declaration.
> 	* top.h (gdb_dirbuf): Likewise.
> ---
>  gdb/cli/cli-cmds.c  | 7 ++++++-
>  gdb/main.c          | 4 +++-
>  gdb/mi/mi-cmd-env.c | 1 +
>  gdb/top.c           | 3 ---
>  gdb/top.h           | 1 -
>  5 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
> index 883844ee70..64e893c784 100644
> --- a/gdb/cli/cli-cmds.c
> +++ b/gdb/cli/cli-cmds.c
> @@ -380,6 +380,8 @@ quit_command (char *args, int from_tty)
>  static void
>  pwd_command (char *args, int from_tty)
>  {
> +  char gdb_dirbuf[BUFSIZ];

I don't recall offhand -- what's "BUFSIZ"?  What defines it
and is it guaranteed to be the right size for getcwd?

> +
>    if (args)
>      error (_("The \"pwd\" command does not take an argument: %s"), args);
>    if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
> @@ -434,7 +436,10 @@ cd_command (char *dir, int from_tty)
>  
>    dir_holder.reset (savestring (dir, len));
>    if (IS_ABSOLUTE_PATH (dir_holder.get ()))
> -    current_directory = dir_holder.release ();
> +    {
> +      xfree (current_directory);
> +      current_directory = dir_holder.release ();
> +    }
>    else
>      {
>        if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
> diff --git a/gdb/main.c b/gdb/main.c
> index a0646edad6..9837729966 100644
> --- a/gdb/main.c
> +++ b/gdb/main.c
> @@ -549,10 +549,12 @@ captured_main_1 (struct captured_main_args *context)
>      (xstrprintf ("%s: warning: ", gdb_program_name));
>    warning_pre_print = tmp_warn_preprint.get ();
>  
> +  char gdb_dirbuf[BUFSIZ];
> +
>    if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
>      perror_warning_with_name (_("error finding working directory"));
>  
> -  current_directory = gdb_dirbuf;
> +  current_directory = xstrdup (gdb_dirbuf);

As an extension, on GNU/Linux, you can call 'getcwd (NULL, 0)' and
that returns a heap-allocated buffer of the necessary size.  Can we
rely on gnulib to implement that behavior everywhere?  Since
it seems like we're xstrdup'ing the dir anyway, that likely would
simplify things, and remove one arbitrary hardcoded limit, while
at it.

Thanks,
Pedro Alves

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

* Re: [PATCH 3/4] Introduce gdb_chdir
  2017-09-12  4:23 ` [PATCH 3/4] Introduce gdb_chdir Sergio Durigan Junior
  2017-09-12 14:53   ` Eli Zaretskii
@ 2017-09-13 16:07   ` Pedro Alves
  2017-09-14 15:14     ` Sergio Durigan Junior
  1 sibling, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-13 16:07 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:

> +#include "common-defs.h"
> +#include <glob.h>
> +#include "gdb_chdir.h"

As per the guidelines, the module's own header should be
included first thing  right after "common-defs.h".  That
allows exposing unsatisfied dependencies (missing includes)
in the header, if any is missing.

> +/* Perform path expansion (i.e., tilde expansion) on DIR, and return
> +   the full path.  */
> +
> +static std::string
> +expand_path (const char *dir)

Since this is particularly about tilde expansion,
and a replacement for "tilde_expand", did you consider calling
it gdb_tilde_expand and using it throughout?  If this were an
extern function, I'd press for having "tilde" in its name,
to make the call sites a bit more obvious.

> +{
> +  glob_t g;
> +  std::string expanded_dir;

Move declaration further below to the initialization line,
to avoid pointlessly default-constructing the string:

  std::string expanded_dir = g.gl_pathv[0];


> +  int err = glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR,
NULL, &g);
> +
> +  if (err != 0)
> +    {
> +      if (err == GLOB_NOMATCH)
> +	error (_("No such directory '%s'.  Failure to set cwd."), dir);

The "Failure to set cwd" string doesn't seem like an error that
should be in "expand_path"?  OK, not really an issue since this
is a single-use static function...

> +
> +      error (_("Could not process directory '%s'."), dir);
> +    }
> +
> +  gdb_assert (g.gl_pathc > 0);
> +  /* "glob" may return more than one match to the path provided by the
> +     user, but we are only interested in the first match.  */
> +  expanded_dir = g.gl_pathv[0];
> +  globfree (&g);

Pedantically, this isn't strictly exception safe, since
either the gdb_assert or the expanded_dir initialization
(a string dup which can fail with out of memory) could throw.

I think I'd write a thin RAII wrapper around glob that'd have a
single "glob_t m_g;" field, that'd call glob in the ctor, and
globfree in the dtor.

> +
> +  return expanded_dir;
> +}
> +


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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-13 14:54 ` Pedro Alves
@ 2017-09-13 21:54   ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-13 21:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 13 2017, Pedro Alves wrote:

> On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:
>> This patch series is a followup of the discussion that happened at:
>> 
>>   https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html
>> 
>> It implements a new GDB command, "set cwd", which is used to set the
>> current working directory of the inferior that will be started.  This
>> is a GDB-only command for now; its gdbserver counterpart will come
>> later.
>
> I think I'd prefer that the gdbserver counterpart was included
> as part of the same series.  I.e., I'd like to see the gdbserver
> side explored first before we change the native side and commit
> to the commands/interface.  Also, I think that would help make
> sure that the manual documentation is adjusted in a way that
> naturally reads as applying to local and remote.

Fair enough.

I wasn't sure if I should submit the gdbserver part as well, of just the
GDB one.  I opted to just touch GDB because we usually choose to go
"baby steps" on things.

> For example, we currently say
>
>  "Each time you start your program with @code{run}, it inherits its 
>  working directory from the current working directory of
>  @value{GDBN}.", 
>
> but you didn't change that particular sentence, which seems to leave
> it a bit incorrect.  I think we should say instead say that
> when you start your program with run, the inferior starts with
> the directory specified by "set cwd", and then mention that
> if that is not set, then the inferior inherits gdb's current
> directory if native debugging, and gdbserver's if remote debugging.
> Right?

Yeah, maybe I should rewrite this sentence indeed.  It's not entirely
true.  Thanks for catching that.

As I said, I will prepare a patch series containing the gdbserver
modifications and will submit it, along with the other changes you
proposed in the other e-mails.

Thanks,

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

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

* Re: [PATCH 0/4] New "set cwd" command
  2017-09-13 15:06           ` Eli Zaretskii
@ 2017-09-13 21:56             ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-13 21:56 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Pedro Alves, gdb-patches

On Wednesday, September 13 2017, Eli Zaretskii wrote:

>> Cc: gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>
>> Date: Wed, 13 Sep 2017 15:59:52 +0100
>> 
>> >> The last bit means that this will only work for targets that use
>> >> fork/vfork, i.e. only for Posix targets.  Right?
>> > 
>> > Well, the way it's implemented, yes.  AFAIK there's nothing preventing
>> > this feature to be implemented in non-vfork targets like Windows, except
>> > the fact that I don't have access to those targets to test.
>> 
>> I think that to make "set cwd" work on Windows, gdb would be adjusted to
>> pass the desired current directory as argument to CreateProcess, here:
>> 
>>   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/windows-nat.c;h=ab5582d46cf3a0873ab32d9c955e95ee75371d4e;hb=HEAD#l2570
>> 
>> (and the equivalent in gdbserver).
>
> Yes.

Thanks, that makes things easier.

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

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

* Re: [PATCH 1/4] Make gdb_dirbuf local to functions
  2017-09-13 15:12   ` Pedro Alves
@ 2017-09-13 22:03     ` Sergio Durigan Junior
  2017-09-13 22:19       ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-13 22:03 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 13 2017, Pedro Alves wrote:

> On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:
>> This is not a requirement for the feature, but I think it's a good
>> cleanup and is related anyway.  Currently we have "current_directory"
>> and "gdb_dirbuf" globals, which means that we basically have two
>> possible places to consult when we want to know GDB's current working
>> directory.
>> 
>> This is not ideal and can lead to confusion, so my proposal is to
>> "internalize" the "gdb_dirbuf" variable, because it is really just
>> that: a buffer to be used when calling "getcwd".  With this, only
>> "current_directory" should be used to determine the cwd.
>> 
>> gdb/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* cli/cli-cmds.c (quit_command): Declare "gdb_dirbuf".
>> 	(cd_command): Free "current_directory" before assigning to it.
>> 	* main.c (captured_main_1): Likewise.  Call "xstrdup" when
>> 	storing it on "current_directory".
>> 	* mi/mi-cmd-env.c (mi_cmd_env_pwd): Declare "gdb_dirbuf".
>> 	* top.c (gdb_dirbuf): Remove global declaration.
>> 	* top.h (gdb_dirbuf): Likewise.
>> ---
>>  gdb/cli/cli-cmds.c  | 7 ++++++-
>>  gdb/main.c          | 4 +++-
>>  gdb/mi/mi-cmd-env.c | 1 +
>>  gdb/top.c           | 3 ---
>>  gdb/top.h           | 1 -
>>  5 files changed, 10 insertions(+), 6 deletions(-)
>> 
>> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
>> index 883844ee70..64e893c784 100644
>> --- a/gdb/cli/cli-cmds.c
>> +++ b/gdb/cli/cli-cmds.c
>> @@ -380,6 +380,8 @@ quit_command (char *args, int from_tty)
>>  static void
>>  pwd_command (char *args, int from_tty)
>>  {
>> +  char gdb_dirbuf[BUFSIZ];
>
> I don't recall offhand -- what's "BUFSIZ"?  What defines it
> and is it guaranteed to be the right size for getcwd?

BUFSIZ is defined by stdio.h, and is 8192 on my Fedora 25.  This is much
greater than the previous "1024" that was being used before.  For
reproducibility reasons I didn't want to use PATH_MAX.

>> +
>>    if (args)
>>      error (_("The \"pwd\" command does not take an argument: %s"), args);
>>    if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
>> @@ -434,7 +436,10 @@ cd_command (char *dir, int from_tty)
>>  
>>    dir_holder.reset (savestring (dir, len));
>>    if (IS_ABSOLUTE_PATH (dir_holder.get ()))
>> -    current_directory = dir_holder.release ();
>> +    {
>> +      xfree (current_directory);
>> +      current_directory = dir_holder.release ();
>> +    }
>>    else
>>      {
>>        if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
>> diff --git a/gdb/main.c b/gdb/main.c
>> index a0646edad6..9837729966 100644
>> --- a/gdb/main.c
>> +++ b/gdb/main.c
>> @@ -549,10 +549,12 @@ captured_main_1 (struct captured_main_args *context)
>>      (xstrprintf ("%s: warning: ", gdb_program_name));
>>    warning_pre_print = tmp_warn_preprint.get ();
>>  
>> +  char gdb_dirbuf[BUFSIZ];
>> +
>>    if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
>>      perror_warning_with_name (_("error finding working directory"));
>>  
>> -  current_directory = gdb_dirbuf;
>> +  current_directory = xstrdup (gdb_dirbuf);
>
> As an extension, on GNU/Linux, you can call 'getcwd (NULL, 0)' and
> that returns a heap-allocated buffer of the necessary size.  Can we
> rely on gnulib to implement that behavior everywhere?  Since
> it seems like we're xstrdup'ing the dir anyway, that likely would
> simplify things, and remove one arbitrary hardcoded limit, while
> at it.

That's true, and it's better when you consider reproducible builds as
well.

According to gnulib:

  https://www.gnu.org/software/gnulib/manual/html_node/getcwd.html

It is better to rely on this better version of getcwd.

Thanks,

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

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

* Re: [PATCH 1/4] Make gdb_dirbuf local to functions
  2017-09-13 22:03     ` Sergio Durigan Junior
@ 2017-09-13 22:19       ` Pedro Alves
  2017-09-13 22:46         ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-13 22:19 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/13/2017 11:03 PM, Sergio Durigan Junior wrote:
> On Wednesday, September 13 2017, Pedro Alves wrote:

>>> --- a/gdb/cli/cli-cmds.c
>>> +++ b/gdb/cli/cli-cmds.c
>>> @@ -380,6 +380,8 @@ quit_command (char *args, int from_tty)
>>>  static void
>>>  pwd_command (char *args, int from_tty)
>>>  {
>>> +  char gdb_dirbuf[BUFSIZ];
>>
>> I don't recall offhand -- what's "BUFSIZ"?  What defines it
>> and is it guaranteed to be the right size for getcwd?
> 
> BUFSIZ is defined by stdio.h, and is 8192 on my Fedora 25.  This is much
> greater than the previous "1024" that was being used before.  

Ah, that BUFSIZ.  That's the FILE* stream buffer size [1], so I don't
see it makes sense to use it for paths over PATH_MAX.  It happens to be
greater that 1024 on your system, but that's not guaranteed, no?

[1] - http://pubs.opengroup.org/onlinepubs/9699919799/functions/setbuf.html
      http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html

> For reproducibility reasons I didn't want to use PATH_MAX.

I don't understand this.  Can you expand?  What's not reproducible
about PATH_MAX?  How's that different from BUFSIZ?

>> As an extension, on GNU/Linux, you can call 'getcwd (NULL, 0)' and
>> that returns a heap-allocated buffer of the necessary size.  Can we
>> rely on gnulib to implement that behavior everywhere?  Since
>> it seems like we're xstrdup'ing the dir anyway, that likely would
>> simplify things, and remove one arbitrary hardcoded limit, while
>> at it.
> 
> That's true, and it's better when you consider reproducible builds as
> well.

/me confused about that.

> 
> According to gnulib:
> 
>   https://www.gnu.org/software/gnulib/manual/html_node/getcwd.html
> 
> It is better to rely on this better version of getcwd.

Alright.  This makes the above moot, though I'd still like to
understand the reproducibility argument, since I suspect that
may come back in other cases.

Thanks,
Pedro Alves

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

* Re: [PATCH 1/4] Make gdb_dirbuf local to functions
  2017-09-13 22:19       ` Pedro Alves
@ 2017-09-13 22:46         ` Sergio Durigan Junior
  2017-09-13 23:47           ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-13 22:46 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 13 2017, Pedro Alves wrote:

> On 09/13/2017 11:03 PM, Sergio Durigan Junior wrote:
>> On Wednesday, September 13 2017, Pedro Alves wrote:
>
>>>> --- a/gdb/cli/cli-cmds.c
>>>> +++ b/gdb/cli/cli-cmds.c
>>>> @@ -380,6 +380,8 @@ quit_command (char *args, int from_tty)
>>>>  static void
>>>>  pwd_command (char *args, int from_tty)
>>>>  {
>>>> +  char gdb_dirbuf[BUFSIZ];
>>>
>>> I don't recall offhand -- what's "BUFSIZ"?  What defines it
>>> and is it guaranteed to be the right size for getcwd?
>> 
>> BUFSIZ is defined by stdio.h, and is 8192 on my Fedora 25.  This is much
>> greater than the previous "1024" that was being used before.  
>
> Ah, that BUFSIZ.  That's the FILE* stream buffer size [1], so I don't
> see it makes sense to use it for paths over PATH_MAX.  It happens to be
> greater that 1024 on your system, but that's not guaranteed, no?
>
> [1] - http://pubs.opengroup.org/onlinepubs/9699919799/functions/setbuf.html
>       http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html

AFAIK that's not a guarantee, indeed.  Although "1024" is also a very
low value for path names on some systems (for example, here PATH_MAX is
defined as 4096), we already had this problem before.

>> For reproducibility reasons I didn't want to use PATH_MAX.
>
> I don't understand this.  Can you expand?  What's not reproducible
> about PATH_MAX?  How's that different from BUFSIZ?
>
>>> As an extension, on GNU/Linux, you can call 'getcwd (NULL, 0)' and
>>> that returns a heap-allocated buffer of the necessary size.  Can we
>>> rely on gnulib to implement that behavior everywhere?  Since
>>> it seems like we're xstrdup'ing the dir anyway, that likely would
>>> simplify things, and remove one arbitrary hardcoded limit, while
>>> at it.
>> 
>> That's true, and it's better when you consider reproducible builds as
>> well.
>
> /me confused about that.
>
>> 
>> According to gnulib:
>> 
>>   https://www.gnu.org/software/gnulib/manual/html_node/getcwd.html
>> 
>> It is better to rely on this better version of getcwd.
>
> Alright.  This makes the above moot, though I'd still like to
> understand the reproducibility argument, since I suspect that
> may come back in other cases.

Well, maybe this is more a question of portability than reproducibility,
but I mentioned the latter because I remember doing some fixes in some
Debian packages that were failing the reproducible tests due to the
presence of PATH_MAX.  They were actually failing to build on certain
targets, but that can be seen as non-reproducibility as well.

PATH_MAX is defined by POSIX but is not used by every system.  GNU/Hurd,
for example, doesn't define it.  As usual with GNU programs the
"correct" thing to do is not to rely on some hard-coded limit imposed by
a header file, but rather to make use of the fact that glibc's getcwd
offers the possibility to allocate the variable that holds the path
according to its actual size.

There are some other problems with PATH_MAX, e.g., the fact that the
maximum length of a pathname is really defined by the underlying
filesystem you're using, so just using "4096" doesn't really reflect the
reality.

Again, maybe I should have said "portability issues", but I consider
them reproducibility issues as well.

Thanks,

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

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

* Re: [PATCH 3/4] Introduce gdb_chdir
  2017-09-12 14:53   ` Eli Zaretskii
@ 2017-09-13 23:00     ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-13 23:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Tuesday, September 12 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: Pedro Alves <palves@redhat.com>,	Sergio Durigan Junior <sergiodj@redhat.com>
>> Date: Tue, 12 Sep 2017 00:23:24 -0400
>> 
>> In order to be able to change the inferior's directory before its
>> execution, it is necessary to perform a tilde expansion of the
>> directory provided by the user and then chdir into the resulting dir.
>> This is what gdb_chdir does.
>> 
>> Unfortunately it is not possible to use "tilde_expand" from readline
>> because this is common code and gdbserver doesn't use readline.  For
>> that reason I decided to go with "glob" and its GNU extension,
>> GLOB_TILDE.  With the import of the "glob" module from gnulib, this is
>> a no-brainer.
>
> Why not simply 'getenv("HOME")'?

Tilde expansion can be more complicated than that.  If you're just using
"~/test", then yeah, you can use $HOME.  However, the user can specify a
directory like "~someone/test", and in that case you have to where is
"someone's $HOME" before you can expand the tilde.  glob takes care of
that for us.

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

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

* Re: [PATCH 1/4] Make gdb_dirbuf local to functions
  2017-09-13 22:46         ` Sergio Durigan Junior
@ 2017-09-13 23:47           ` Pedro Alves
  0 siblings, 0 replies; 131+ messages in thread
From: Pedro Alves @ 2017-09-13 23:47 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/13/2017 11:46 PM, Sergio Durigan Junior wrote:
>> > Ah, that BUFSIZ.  That's the FILE* stream buffer size [1], so I don't
>> > see it makes sense to use it for paths over PATH_MAX.  It happens to be
>> > greater that 1024 on your system, but that's not guaranteed, no?
>> >
>> > [1] - http://pubs.opengroup.org/onlinepubs/9699919799/functions/setbuf.html
>> >       http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html
> AFAIK that's not a guarantee, indeed.  Although "1024" is also a very
> low value for path names on some systems (for example, here PATH_MAX is
> defined as 4096), we already had this problem before.

Yes, but at least 1024 was stable and usually good enough.

>>> For reproducibility reasons I didn't want to use PATH_MAX.
>>
>> I don't understand this.  Can you expand?  What's not reproducible
>> about PATH_MAX?  How's that different from BUFSIZ?
>>
>>>> As an extension, on GNU/Linux, you can call 'getcwd (NULL, 0)' and
>>>> that returns a heap-allocated buffer of the necessary size.  Can we
>>>> rely on gnulib to implement that behavior everywhere?  Since
>>>> it seems like we're xstrdup'ing the dir anyway, that likely would
>>>> simplify things, and remove one arbitrary hardcoded limit, while
>>>> at it.
>>>
>>> That's true, and it's better when you consider reproducible builds as
>>> well.
>>
>> /me confused about that.
>>
>>>
>>> According to gnulib:
>>>
>>>   https://www.gnu.org/software/gnulib/manual/html_node/getcwd.html
>>>
>>> It is better to rely on this better version of getcwd.
>>
>> Alright.  This makes the above moot, though I'd still like to
>> understand the reproducibility argument, since I suspect that
>> may come back in other cases.
> 
> Well, maybe this is more a question of portability than reproducibility,
> but I mentioned the latter because I remember doing some fixes in some
> Debian packages that were failing the reproducible tests due to the
> presence of PATH_MAX.  They were actually failing to build on certain
> targets, but that can be seen as non-reproducibility as well.

I think that's stretching what reproducibility means too far,
and ends up being confusing.  AFAICT, it'd be like saying that a program
isn't reproducible because it uses "ptrace", because "ptrace" isn't portable.
Well, that "ptrace" call may be the whole point of the program.
If you can always build the program on environment A and end up with
the same binary, then the program is reproducible on environment A.
That does not mean that you should expect to build the program under some
environment B [e.g., different compiler version or different system
libraries, or different kernel, or different architecture, or ...] and
get the same binary as in environment A.

> 
> PATH_MAX is defined by POSIX but is not used by every system.  GNU/Hurd,
> for example, doesn't define it.  As usual with GNU programs the
> "correct" thing to do is not to rely on some hard-coded limit imposed by
> a header file, but rather to make use of the fact that glibc's getcwd
> offers the possibility to allocate the variable that holds the path
> according to its actual size.

Correct.  That's exactly why I thought of suggesting getcwd's extension.

> 
> There are some other problems with PATH_MAX, e.g., the fact that the
> maximum length of a pathname is really defined by the underlying
> filesystem you're using, so just using "4096" doesn't really reflect the
> reality.

Right, on GNU/Linux we can certainly have paths longer than that.

> 
> Again, maybe I should have said "portability issues", but I consider
> them reproducibility issues as well.

Alright, glad we cleared this up, and glad that it's all moot now.  :-)

Thanks,
Pedro Alves

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

* Re: [PATCH 3/4] Introduce gdb_chdir
  2017-09-13 16:07   ` Pedro Alves
@ 2017-09-14 15:14     ` Sergio Durigan Junior
  2017-09-14 15:23       ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-14 15:14 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 13 2017, Pedro Alves wrote:

> On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:
>
>> +#include "common-defs.h"
>> +#include <glob.h>
>> +#include "gdb_chdir.h"
>
> As per the guidelines, the module's own header should be
> included first thing  right after "common-defs.h".  That
> allows exposing unsatisfied dependencies (missing includes)
> in the header, if any is missing.

Done.

>> +/* Perform path expansion (i.e., tilde expansion) on DIR, and return
>> +   the full path.  */
>> +
>> +static std::string
>> +expand_path (const char *dir)
>
> Since this is particularly about tilde expansion,
> and a replacement for "tilde_expand", did you consider calling
> it gdb_tilde_expand and using it throughout?  If this were an
> extern function, I'd press for having "tilde" in its name,
> to make the call sites a bit more obvious.

Sure, no problem in renaming it.  Just to clarify: when you mean "use it
throughout", are saying that this should be used to replace readline's
"tilde_expand" elsewhere on GDB?

>> +{
>> +  glob_t g;
>> +  std::string expanded_dir;
>
> Move declaration further below to the initialization line,
> to avoid pointlessly default-constructing the string:
>
>   std::string expanded_dir = g.gl_pathv[0];

Done.

>> +  int err = glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR,
> NULL, &g);
>> +
>> +  if (err != 0)
>> +    {
>> +      if (err == GLOB_NOMATCH)
>> +	error (_("No such directory '%s'.  Failure to set cwd."), dir);
>
> The "Failure to set cwd" string doesn't seem like an error that
> should be in "expand_path"?  OK, not really an issue since this
> is a single-use static function...

You're right.  I'll make sure to display this error on "gdb_chdir"
instead.

>> +
>> +      error (_("Could not process directory '%s'."), dir);
>> +    }
>> +
>> +  gdb_assert (g.gl_pathc > 0);
>> +  /* "glob" may return more than one match to the path provided by the
>> +     user, but we are only interested in the first match.  */
>> +  expanded_dir = g.gl_pathv[0];
>> +  globfree (&g);
>
> Pedantically, this isn't strictly exception safe, since
> either the gdb_assert or the expanded_dir initialization
> (a string dup which can fail with out of memory) could throw.
>
> I think I'd write a thin RAII wrapper around glob that'd have a
> single "glob_t m_g;" field, that'd call glob in the ctor, and
> globfree in the dtor.

OK, I can do that, no problem.

Thanks,

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

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

* Re: [PATCH 3/4] Introduce gdb_chdir
  2017-09-14 15:14     ` Sergio Durigan Junior
@ 2017-09-14 15:23       ` Pedro Alves
  2017-09-14 15:33         ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-14 15:23 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/14/2017 04:14 PM, Sergio Durigan Junior wrote:
> On Wednesday, September 13 2017, Pedro Alves wrote:
> 
>> On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:

>>> +/* Perform path expansion (i.e., tilde expansion) on DIR, and return
>>> +   the full path.  */
>>> +
>>> +static std::string
>>> +expand_path (const char *dir)
>>
>> Since this is particularly about tilde expansion,
>> and a replacement for "tilde_expand", did you consider calling
>> it gdb_tilde_expand and using it throughout?  If this were an
>> extern function, I'd press for having "tilde" in its name,
>> to make the call sites a bit more obvious.
> 
> Sure, no problem in renaming it.  Just to clarify: when you mean "use it
> throughout", are saying that this should be used to replace readline's
> "tilde_expand" elsewhere on GDB?

Yes, and no.  Yes, by 'throughout' I meant elsewhere in GDB.
But no, I'm not _saying_ it should.  I'm really asking if you
considered/thought about that.

I think what I'm really wondering is whether tilde_expand
and this new function behave exactly the same, or whether
glob behaves a little different in some cases.  If it behaves
differently [and the differences are benign), then I get to
wonder whether we should use it throughout so that different
commands don't behave differently.

E.g., does "cd *" behave the same before/after ?  Or does
'glob' expand '*' while tilde_expand didn't?

Thanks,
Pedro Alves

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

* Re: [PATCH 3/4] Introduce gdb_chdir
  2017-09-14 15:23       ` Pedro Alves
@ 2017-09-14 15:33         ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-14 15:33 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Thursday, September 14 2017, Pedro Alves wrote:

> On 09/14/2017 04:14 PM, Sergio Durigan Junior wrote:
>> On Wednesday, September 13 2017, Pedro Alves wrote:
>> 
>>> On 09/12/2017 05:23 AM, Sergio Durigan Junior wrote:
>
>>>> +/* Perform path expansion (i.e., tilde expansion) on DIR, and return
>>>> +   the full path.  */
>>>> +
>>>> +static std::string
>>>> +expand_path (const char *dir)
>>>
>>> Since this is particularly about tilde expansion,
>>> and a replacement for "tilde_expand", did you consider calling
>>> it gdb_tilde_expand and using it throughout?  If this were an
>>> extern function, I'd press for having "tilde" in its name,
>>> to make the call sites a bit more obvious.
>> 
>> Sure, no problem in renaming it.  Just to clarify: when you mean "use it
>> throughout", are saying that this should be used to replace readline's
>> "tilde_expand" elsewhere on GDB?
>
> Yes, and no.  Yes, by 'throughout' I meant elsewhere in GDB.
> But no, I'm not _saying_ it should.  I'm really asking if you
> considered/thought about that.

I thought about that while I was making the patch.

My very initial plan was to actually use 'wordexp', but I gave up on
that when I noticed that the function is not implemented in many targets
and gnulib doesn't provide a module for it.  So I went ahead and decided
to use glob, but left the "cd_command" untouched just because it is
"already working" (TM).

> I think what I'm really wondering is whether tilde_expand
> and this new function behave exactly the same, or whether
> glob behaves a little different in some cases.  If it behaves
> differently [and the differences are benign), then I get to
> wonder whether we should use it throughout so that different
> commands don't behave differently.
>
> E.g., does "cd *" behave the same before/after ?  Or does
> 'glob' expand '*' while tilde_expand didn't?

From my initial tests I can see that "glob" and "tilde_expand" behave
the same, but I'll try to test more corner cases and see the results.
Apparently it'll be fine to just replace "tilde_expand".

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

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

* [PATCH v2 4/5] Implement "set cwd" command
  2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
@ 2017-09-19  4:28   ` Sergio Durigan Junior
  2017-09-20 14:01     ` Pedro Alves
  2017-09-19  4:28   ` [PATCH v2 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-19  4:28 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This is the actual implementation of the "set/show cwd" commands.  The
way they work is:

- If the user sets the inferior's cwd by using "set cwd", then this
  directory is saved into current_inferior ()->cwd and is used when
  the inferior is started (see below).

- If the user doesn't set the inferior's cwd by using "set cwd", but
  rather use the "cd" command as before, the this directory is
  inherited by the inferior because GDB will have chdir'd into it.

The way the directory is changed before the inferior execution is by
calling "gdb_chdir" after the call to fork/vfork on "fork_inferior",
but before the actual execution.  This way, we'll make sure that GDB's
cwd is not affected by the user set cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (New commands): Mention "set/show cwd".
	* cli/cli-cmds.c (_initialize_cli_cmds): Mention "set cwd" on
	"cd" command's help text.
	* common/common-inferior.h (get_inferior_cwd): New prototype.
	* infcmd.c: Include "gdb_chdir.h" and "readline/tilde.h".
	(inferior_cwd_scratch): New global variable.
	(set_inferior_cwd): New function.
	(get_inferior_cwd): Likewise.
	(set_cwd_command): Likewise.
	(show_cwd_command): Likewise.
	(_initialize_infcmd): Add "set/show cwd" commands.
	* inferior.h (class inferior) <cwd>: New field.
	* nat/fork-inferior.c: Include "gdb_chdir.h".
	(fork_inferior): Change inferior's cwd before its execution.
	* windows-nat.c (windows_create_inferior): Pass inferior's cwd
	to CreateProcess.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (get_inferior_cwd): New function.
	* inferiors.h (struct process_info) <cwd>: New field.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention new "set cwd" command.
	(Working Directory) <Your Program's Working Directory>:
	Rephrase to explain that "set cwd" exists and is the default
	way to change the inferior's cwd.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.c: New file.
	* gdb.base/set-cwd.exp: Likewise.
---
 gdb/NEWS                           |  3 ++
 gdb/cli/cli-cmds.c                 |  6 +--
 gdb/common/common-inferior.h       |  4 ++
 gdb/doc/gdb.texinfo                | 34 ++++++++++----
 gdb/gdbserver/inferiors.c          | 11 +++++
 gdb/infcmd.c                       | 75 +++++++++++++++++++++++++++++++
 gdb/inferior.h                     |  4 ++
 gdb/nat/fork-inferior.c            | 17 +++++++
 gdb/testsuite/gdb.base/set-cwd.c   | 29 ++++++++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 90 ++++++++++++++++++++++++++++++++++++++
 gdb/windows-nat.c                  |  5 ++-
 11 files changed, 265 insertions(+), 13 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.c
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 3244f7effe..0dcfcc98af 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -64,6 +64,9 @@ QStartupWithShell
 
 * New commands
 
+set|show cwd
+  Set and show the current working directory for the inferior.
+
 set|show compile-gcc
   Set and show compilation command used for compiling and injecting code
   with the 'compile' commands.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 653dd56a64..f086f10aea 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1716,9 +1716,9 @@ The commands below can be used to select other frames by number or address."),
 Print working directory.  This is used for your program as well."));
 
   c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_com ("echo", class_support, echo_command, _("\
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 87c13009ed..515a8c0f4e 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
    otherwise return 0 in that case.  */
 extern char *get_exec_file (int err);
 
+/* Return the inferior's current working directory.  If nothing has
+   been set, then return NULL.  */
+extern const char *get_inferior_cwd ();
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index af5fe6f46c..c513a49c26 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
 your program.  @xref{Environment, ,Your Program's Environment}.
 
 @item The @emph{working directory.}
-Your program inherits its working directory from @value{GDBN}.  You can set
-the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+You can set your program's working directory with the command
+@code{set cwd}.  If you do not set any working directory with this
+command, your program will inherit @value{GDBN}'s working directory.
 @xref{Working Directory, ,Your Program's Working Directory}.
 
 @item The @emph{standard input and output.}
@@ -2424,19 +2425,36 @@ variables to files that are only run when you sign on, such as
 @section Your Program's Working Directory
 
 @cindex working directory (of your program)
-Each time you start your program with @code{run}, it inherits its
-working directory from the current working directory of @value{GDBN}.
-The @value{GDBN} working directory is initially whatever it inherited
-from its parent process (typically the shell), but you can specify a new
-working directory in @value{GDBN} with the @code{cd} command.
+Each time you start your program with @code{run}, the inferior will be
+initialized with the current working directory specified by the
+@code{set cwd} command.  If no directory has been specified by this
+command, then the inferior will inherit @value{GDBN}'s current working
+directory as its working directory.
+
+You can also change @value{GDBN}'s current working directory by using
+the @code{cd} command.
 
 The @value{GDBN} working directory also serves as a default for the commands
 that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
 Specify Files}.
 
 @table @code
+@kindex set cwd
+@cindex change inferior's working directory
+@item set cwd @r{[}@var{directory}@r{]}
+Set the inferior's working directory to @var{directory}.  If not
+given, @var{directory} uses @file{'~'}.  This has no effect on
+@value{GDBN}'s working directory.
+
+@kindex show cwd
+@cindex show inferior's working directory
+@item show cwd
+Show the inferior's working directory.  If no directory has been
+specified by @code{set cwd}, then the default inferior's working
+directory is the same as @value{GDBN}'s working directory.
+
 @kindex cd
-@cindex change working directory
+@cindex change @value{GDBN}'s working directory
 @item cd @r{[}@var{directory}@r{]}
 Set the @value{GDBN} working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 72f0412757..e78ad4faf1 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -29,6 +29,9 @@ struct thread_info *current_thread;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
 
+/* The current working directory used to start the inferior.  */
+static const char *current_inferior_cwd = NULL;
+
 void
 add_inferior_to_list (struct inferior_list *list,
 		      struct inferior_list_entry *new_inferior)
@@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
   if (!ptid_equal (ptid, minus_one_ptid))
     current_thread = find_thread_ptid (ptid);
 }
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior_cwd;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 25cf025426..178a3ca15f 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -59,6 +59,8 @@
 #include "top.h"
 #include "interps.h"
 #include "common/gdb_optional.h"
+#include "gdb_chdir.h"
+#include "readline/tilde.h"
 
 /* Local functions: */
 
@@ -111,6 +113,10 @@ static void run_command (char *, int);
 
 static char *inferior_args_scratch;
 
+/* Scratch area where the new cwd will be stored by 'set cwd'.  */
+
+static char *inferior_cwd_scratch;
+
 /* Scratch area where 'set inferior-tty' will store user-provided value.
    We'll immediate copy it into per-inferior storage.  */
 
@@ -246,6 +252,56 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
+/* Set the inferior current working directory.  This directory will be
+   entered by GDB before executing the inferior.  */
+
+static void
+set_inferior_cwd (const char *cwd)
+{
+  struct inferior *inf = current_inferior ();
+
+  gdb_assert (inf != NULL);
+  xfree ((void *) inf->cwd);
+  inf->cwd = tilde_expand (*cwd != '\0' ? cwd : "~");
+}
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior ()->cwd;
+}
+
+/* Handle the 'set cwd' command.  */
+
+static void
+set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+{
+  set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command.  */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  const char *cwd = get_inferior_cwd ();
+
+  if (cwd == NULL)
+    {
+      /* To maintain backwards compatibility, we use
+	 'current_directory' here, which is set by the "cd"
+	 command.  */
+      cwd = current_directory;
+    }
+
+  fprintf_filtered (gdb_stdout,
+		    _("Current working directory that will be used "
+		      "when starting the inferior is \"%s\".\n"), cwd);
+}
+
 \f
 /* Compute command-line string given argument vector.  This does the
    same shell processing as fork_inferior.  */
@@ -3214,6 +3270,25 @@ Follow this command with any number of args, to be passed to the program."),
   gdb_assert (c != NULL);
   set_cmd_completer (c, filename_completer);
 
+  cmd_name = "cwd";
+  add_setshow_string_noescape_cmd (cmd_name, class_run,
+				   &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+				   _("\
+Show the current working directory that is used when the inferior is started."),
+				   _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started.  This setting does not affect GDB's current\n\
+working directory."),
+				   set_cwd_command,
+				   show_cwd_command,
+				   &setlist, &showlist);
+  c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+  gdb_assert (c != NULL);
+  set_cmd_completer (c, filename_completer);
+
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
 With an argument VAR, prints the value of environment variable VAR to\n\
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 6d020f73c4..bcd1e54a03 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -355,6 +355,10 @@ public:
      should never be freed.  */
   char **argv = NULL;
 
+  /* The current working directory that will be used when starting
+     this inferior.  */
+  const char *cwd = NULL;
+
   /* The name of terminal device to use for I/O.  */
   char *terminal = NULL;
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 0913409e6d..6ff0c2d216 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -25,6 +25,7 @@
 #include "common-inferior.h"
 #include "common-gdbthread.h"
 #include "signals-state-save-restore.h"
+#include "gdb_chdir.h"
 #include <vector>
 
 extern char **environ;
@@ -376,6 +377,22 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
 	 UIs.  */
       close_most_fds ();
 
+      const char *cwd = get_inferior_cwd ();
+
+      if (cwd != NULL)
+	{
+	  TRY
+	    {
+	      gdb_chdir (cwd);
+	    }
+	  CATCH (ex, RETURN_MASK_ERROR)
+	    {
+	      warning ("%s", ex.message);
+	      _exit (0177);
+	    }
+	  END_CATCH
+	}
+
       if (debug_fork)
 	sleep (debug_fork);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.c b/gdb/testsuite/gdb.base/set-cwd.c
new file mode 100644
index 0000000000..488fc4e4e3
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 Free Software Foundation, Inc.
+
+   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 <stdio.h>
+#include <unistd.h>
+
+int
+main (int argc, char *argv[])
+{
+  char dir[BUFSIZ];
+
+  getcwd (dir, BUFSIZ);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
new file mode 100644
index 0000000000..3a6ffd3862
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -0,0 +1,90 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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/>.
+
+if { ![isnative] || [is_remote target] || [is_remote host]
+     || [target_info gdb_protocol] == "extended-remote" } then {
+    untested "not implemented on gdbserver"
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    return -1
+}
+
+# Test that tilde expansion works fine.
+
+proc test_tilde_expansion { } {
+    if { [info exists ::env(HOME)] } {
+	with_test_prefix "test tilde expansion" {
+	    set home $::env(HOME)
+
+	    gdb_test_no_output "set cwd ~/test" "set cwd to ~/test dir"
+
+	    gdb_test "show cwd" \
+		"Current working directory that will be used when starting the inferior is \"${home}/test\"\." \
+		"show cwd shows expanded tilde"
+	}
+    }
+}
+
+# Test that when we "set cwd" the inferior will be started under the
+# correct working directory and GDB will not be affected by this.
+
+proc test_cd_into_dir { } {
+    global decimal gdb_prompt
+
+    with_test_prefix "test cd into temp dir" {
+	gdb_test_multiple "pwd" "pwd before run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_before_run $expect_out(1,string)
+	    }
+	}
+
+	set tmpdir [standard_output_file ""]
+
+	gdb_test_no_output "set cwd $tmpdir" "set cwd to temp dir"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	    "inferior cwd is correctly set"
+
+	gdb_test_multiple "pwd" "pwd after run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_after_run $expect_out(1,string)
+	    }
+	}
+
+	set test "GDB cwd is unchanged after running inferior"
+	if { [string equal $gdb_cwd_before_run $gdb_cwd_after_run] } {
+	    pass $test
+	} else {
+	    fail $test
+	}
+    }
+}
+
+test_cd_into_dir
+test_tilde_expansion
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index ab5582d46c..9732a2d175 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2461,6 +2461,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   BOOL ret;
   DWORD flags = 0;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
+  const char *inferior_cwd = get_inferior_cwd ();
 
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
@@ -2574,7 +2575,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 		       TRUE,	/* inherit handles */
 		       flags,	/* start flags */
 		       w32_env,	/* environment */
-		       NULL,	/* current directory */
+		       inferior_cwd,	/* current directory */
 		       &si,
 		       &pi);
   if (w32_env)
@@ -2697,7 +2698,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 			TRUE,	/* inherit handles */
 			flags,	/* start flags */
 			w32env,	/* environment */
-			NULL,	/* current directory */
+			inferior_cwd,	/* current directory */
 			&si,
 			&pi);
   if (tty != INVALID_HANDLE_VALUE)
-- 
2.13.3

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

* [PATCH v2 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)"
  2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
  2017-09-19  4:28   ` [PATCH v2 4/5] Implement " Sergio Durigan Junior
@ 2017-09-19  4:28   ` Sergio Durigan Junior
  2017-09-20 12:24     ` Pedro Alves
  2017-09-19  4:28   ` [PATCH v2 3/5] Introduce gdb_chdir Sergio Durigan Junior
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-19  4:28 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

Currently we have "current_directory" and "gdb_dirbuf" globals, which
means that we basically have two possible places to consult when we
want to know GDB's current working directory.

This is not ideal and can lead to confusion.  Moreover, the way we're
using "gdb_difbuf" along with "getcwd" is problematic because we
declare the buffer with "1024" elements hardcoded, which does not take
into account longer pathnames that are possible in many filesystems.
Using "PATH_MAX" would also not be a solution because of portability
problems.  Therefore, the best solution is to rely on the fact that
"getcwd (NULL, 0)" will "do the right thing" and return a
heap-allocated string containing the full path.  With the new "getcwd"
module from gnulib, it is now possible to do that without worrying
about breaking some target.

With this patch "current_directory" is now the only place to check for
GDB's cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* cli/cli-cmds.c (pwd_command): Use "getcwd (NULL, 0)".
	(cd_command): Likewise.  Free "current_directory" before
	assigning to it.
	* main.c (captured_main_1): Use "getcwd (NULL, 0)".
	* mi/mi-cmd-env.c (mi_cmd_env_pwd): Likewise.
	* top.c (gdb_dirbuf): Remove global declaration.
	* top.h (gdb_dirbuf): Likewise.
---
 gdb/cli/cli-cmds.c  | 17 ++++++++++++-----
 gdb/main.c          |  5 ++---
 gdb/mi/mi-cmd-env.c |  8 ++++----
 gdb/top.c           |  3 ---
 gdb/top.h           |  1 -
 5 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 883844ee70..85d6d21113 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -382,13 +382,16 @@ pwd_command (char *args, int from_tty)
 {
   if (args)
     error (_("The \"pwd\" command does not take an argument: %s"), args);
-  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+
+  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+
+  if (cwd.get () == NULL)
     error (_("Error finding name of working directory: %s"),
            safe_strerror (errno));
 
-  if (strcmp (gdb_dirbuf, current_directory) != 0)
+  if (strcmp (cwd.get (), current_directory) != 0)
     printf_unfiltered (_("Working directory %s\n (canonically %s).\n"),
-		       current_directory, gdb_dirbuf);
+		       current_directory, cwd.get ());
   else
     printf_unfiltered (_("Working directory %s.\n"), current_directory);
 }
@@ -416,7 +419,8 @@ cd_command (char *dir, int from_tty)
   /* There's too much mess with DOSish names like "d:", "d:.",
      "d:./foo" etc.  Instead of having lots of special #ifdef'ed code,
      simply get the canonicalized name of the current directory.  */
-  dir = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
+  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+  dir = cwd.get ();
 #endif
 
   len = strlen (dir);
@@ -434,7 +438,10 @@ cd_command (char *dir, int from_tty)
 
   dir_holder.reset (savestring (dir, len));
   if (IS_ABSOLUTE_PATH (dir_holder.get ()))
-    current_directory = dir_holder.release ();
+    {
+      xfree (current_directory);
+      current_directory = dir_holder.release ();
+    }
   else
     {
       if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
diff --git a/gdb/main.c b/gdb/main.c
index a0646edad6..8693781825 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -549,11 +549,10 @@ captured_main_1 (struct captured_main_args *context)
     (xstrprintf ("%s: warning: ", gdb_program_name));
   warning_pre_print = tmp_warn_preprint.get ();
 
-  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+  current_directory = getcwd (NULL, 0);
+  if (current_directory == NULL)
     perror_warning_with_name (_("error finding working directory"));
 
-  current_directory = gdb_dirbuf;
-
   /* Set the sysroot path.  */
   gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT,
 					TARGET_SYSTEM_ROOT_RELOCATABLE);
diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
index 977b6e274d..1e4c09352f 100644
--- a/gdb/mi/mi-cmd-env.c
+++ b/gdb/mi/mi-cmd-env.c
@@ -73,12 +73,12 @@ mi_cmd_env_pwd (const char *command, char **argv, int argc)
     }
      
   /* Otherwise the mi level is 2 or higher.  */
-
-  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+  if (cwd.get () == NULL)
     error (_("-environment-pwd: error finding name of working directory: %s"),
            safe_strerror (errno));
-    
-  uiout->field_string ("cwd", gdb_dirbuf);
+
+  uiout->field_string ("cwd", cwd.get ());
 }
 
 /* Change working directory.  */
diff --git a/gdb/top.c b/gdb/top.c
index 742c1e7a07..0f36dce760 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -133,9 +133,6 @@ show_confirm (struct ui_file *file, int from_tty,
 
 char *current_directory;
 
-/* The directory name is actually stored here (usually).  */
-char gdb_dirbuf[1024];
-
 /* The last command line executed on the console.  Used for command
    repetitions.  */
 char *saved_command_line;
diff --git a/gdb/top.h b/gdb/top.h
index 45798897f6..6b66083995 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -219,7 +219,6 @@ extern void ui_unregister_input_event_handler (struct ui *ui);
 /* From top.c.  */
 extern char *saved_command_line;
 extern int confirm;
-extern char gdb_dirbuf[1024];
 extern int inhibit_gdbinit;
 extern const char gdbinit[];
 
-- 
2.13.3

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

* [PATCH v2 0/5] New "set cwd" command
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
                   ` (5 preceding siblings ...)
  2017-09-13 14:54 ` Pedro Alves
@ 2017-09-19  4:28 ` Sergio Durigan Junior
  2017-09-19  4:28   ` [PATCH v2 4/5] Implement " Sergio Durigan Junior
                     ` (4 more replies)
  2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
                   ` (2 subsequent siblings)
  9 siblings, 5 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-19  4:28 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves

Changes from v1:

- The patch is now importing the "getcwd" module from gnulib as well
  as the "glob" one.

- Improved the "gdb_dirbuf removal" patch (patch #2) by making use of
  "getcwd (NULL, 0)" instead of a fixed-length buffer to be passed to
  "getcwd".

- Fixed and improved a few things on the "gdb_chdir patch" (patch #3),
  mainly the "expand_path" function name (which is now named
  "gdb_tilde_expand"), and the lack of a RAII wrapper around "glob" to
  make things exception-safe.  I decided not to use "gdb_tilde_expand"
  globally on GDB for now; there are just too many places that use it
  and I prefer to make this conversion later.

- Added gdbserver changes (patch #5), which hopefully makes it easier
  to see the feature in the "bigger picture".


This patch series is a followup of the discussion that happened at:

  https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html

It implements a new GDB command, "set cwd", which is used to set the
current working directory of the inferior that will be started.  This
command works for both native and remote debugging scenarios.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.


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

* [PATCH v2 3/5] Introduce gdb_chdir
  2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
  2017-09-19  4:28   ` [PATCH v2 4/5] Implement " Sergio Durigan Junior
  2017-09-19  4:28   ` [PATCH v2 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
@ 2017-09-19  4:28   ` Sergio Durigan Junior
  2017-09-20 13:14     ` Pedro Alves
  2017-09-19  4:33   ` [PATCH v2 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
  2017-09-19  4:37   ` [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-19  4:28 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

In order to be able to change the inferior's directory before its
execution, it is necessary to perform a tilde expansion of the
directory provided by the user and then chdir into the resulting dir.
This is what gdb_chdir does.

Unfortunately it is not possible to use "tilde_expand" from readline
because this is common code and gdbserver doesn't use readline.  For
that reason I decided to go with "glob" and its GNU extension,
GLOB_TILDE.  With the import of the "glob" module from gnulib, this is
a no-brainer.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add gdb_chdir.c.
	(HFILES_NO_SRCDIR): Add gdb_chdir.h.
	(COMMON_OBS): Add gdb_chdir.o.
	* cli/cli-cmds.c: Include "gdb_chdir.h".
	(cd_command): Use "gdb_chdir" instead of "tilde_expand
	plus chdir".
	* common/gdb_chdir.c: New file.
	* common/gdb_chdir.h: Likewise.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add $(srcdir)/common/gdb_chdir.c.
	(OBS): Add gdb_chdir.o.
---
 gdb/Makefile.in           |  3 ++
 gdb/cli/cli-cmds.c        | 20 +++++-----
 gdb/common/gdb_chdir.c    | 96 +++++++++++++++++++++++++++++++++++++++++++++++
 gdb/common/gdb_chdir.h    | 26 +++++++++++++
 gdb/gdbserver/Makefile.in |  2 +
 5 files changed, 136 insertions(+), 11 deletions(-)
 create mode 100644 gdb/common/gdb_chdir.c
 create mode 100644 gdb/common/gdb_chdir.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9dfc117b2f..1f093e6c0f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1245,6 +1245,7 @@ SFILES = \
 	common/filestuff.c \
 	common/format.c \
 	common/job-control.c \
+	common/gdb_chdir.c \
 	common/gdb_vecs.c \
 	common/new-op.c \
 	common/print-utils.c \
@@ -1529,6 +1530,7 @@ HFILES_NO_SRCDIR = \
 	common/fileio.h \
 	common/format.h \
 	common/gdb_assert.h \
+	common/gdb_chdir.h \
 	common/gdb_locale.h \
 	common/gdb_setjmp.h \
 	common/gdb_signals.h \
@@ -1734,6 +1736,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	frame-unwind.o \
 	gcore.o \
 	gdb_bfd.o \
+	gdb_chdir.o \
 	gdb-dlfcn.o \
 	gdb_obstack.o \
 	gdb_regex.o \
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 85d6d21113..653dd56a64 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -54,6 +54,8 @@
 #include "tui/tui.h"	/* For tui_active et.al.  */
 #endif
 
+#include "gdb_chdir.h"
+
 #include <fcntl.h>
 #include <algorithm>
 #include <string>
@@ -408,12 +410,7 @@ cd_command (char *dir, int from_tty)
      repeat might be useful but is more likely to be a mistake.  */
   dont_repeat ();
 
-  gdb::unique_xmalloc_ptr<char> dir_holder
-    (tilde_expand (dir != NULL ? dir : "~"));
-  dir = dir_holder.get ();
-
-  if (chdir (dir) < 0)
-    perror_with_name (dir);
+  gdb_chdir (dir != NULL ? dir : "~");
 
 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
   /* There's too much mess with DOSish names like "d:", "d:.",
@@ -436,20 +433,21 @@ cd_command (char *dir, int from_tty)
 	len--;
     }
 
-  dir_holder.reset (savestring (dir, len));
-  if (IS_ABSOLUTE_PATH (dir_holder.get ()))
+  std::string newdir = std::string (dir, len);
+  const char *newdir_str = newdir.c_str ();
+  if (IS_ABSOLUTE_PATH (newdir_str))
     {
       xfree (current_directory);
-      current_directory = dir_holder.release ();
+      current_directory = xstrdup (newdir_str);
     }
   else
     {
       if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
-	current_directory = concat (current_directory, dir_holder.get (),
+	current_directory = concat (current_directory, newdir_str,
 				    (char *) NULL);
       else
 	current_directory = concat (current_directory, SLASH_STRING,
-				    dir_holder.get (), (char *) NULL);
+				    newdir_str, (char *) NULL);
     }
 
   /* Now simplify any occurrences of `.' and `..' in the pathname.  */
diff --git a/gdb/common/gdb_chdir.c b/gdb/common/gdb_chdir.c
new file mode 100644
index 0000000000..6eebeb2d02
--- /dev/null
+++ b/gdb/common/gdb_chdir.c
@@ -0,0 +1,96 @@
+/* chdir(2) wrapper for GDB and gdbserver.
+
+   Copyright (C) 2017 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 "gdb_chdir.h"
+#include <glob.h>
+
+/* RAII-style class wrapping "glob".  */
+
+class gdb_glob
+{
+public:
+  /* Construct a "gdb_glob" object by calling "glob" with the provided
+     parameters.  This function can throw if "glob" fails.  */
+  gdb_glob (const char *pattern, int flags,
+	    int (*errfunc) (const char *epath, int eerrno))
+  {
+    int ret = glob (pattern, flags, errfunc, &m_glob);
+
+    if (ret != 0)
+      {
+	if (ret == GLOB_NOMATCH)
+	  error (_("Could not find a match for '%s'."), pattern);
+	else
+	  error (_("glob could not process pattern '%s'."),
+		 pattern);
+      }
+  }
+
+  /* Destroy the object and free M_GLOB.  */
+  ~gdb_glob ()
+  {
+    globfree (&m_glob);
+  }
+
+  /* Return the GL_PATHC component of M_GLOB.  */
+  int
+  pathc () const
+  {
+    return m_glob.gl_pathc;
+  }
+
+  /* Return the GL_PATHV component of M_GLOB.  */
+  char **
+  pathv () const
+  {
+    return m_glob.gl_pathv;
+  }
+
+private:
+  /* The actual glob object we're dealing with.  */
+  glob_t m_glob;
+};
+
+/* Perform path expansion (i.e., tilde expansion) on DIR, and return
+   the full path.  */
+
+static std::string
+gdb_tilde_expand (const char *dir)
+{
+  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);
+
+  gdb_assert (glob.pathc () > 0);
+  /* "glob" may return more than one match to the path provided by the
+     user, but we are only interested in the first match.  */
+  std::string expanded_dir = glob.pathv ()[0];
+
+  return expanded_dir;
+}
+
+/* See gdb_chdir.h.  */
+
+void
+gdb_chdir (const char *dir)
+{
+  std::string expanded_dir = gdb_tilde_expand (dir);
+
+  if (chdir (expanded_dir.c_str ()) < 0)
+    perror_with_name (expanded_dir.c_str ());
+}
diff --git a/gdb/common/gdb_chdir.h b/gdb/common/gdb_chdir.h
new file mode 100644
index 0000000000..5e6253e3b5
--- /dev/null
+++ b/gdb/common/gdb_chdir.h
@@ -0,0 +1,26 @@
+/* chdir(2) wrapper for GDB and gdbserver.
+
+   Copyright (C) 2017 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 HAVE_GDB_CHDIR_H
+#define HAVE_GDB_CHDIR_H
+
+/* Perform a "chdir" to DIR, doing the proper tilde expansion before.  */
+extern void gdb_chdir (const char *dir);
+
+#endif /* ! HAVE_GDB_CHDIR_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 1bbe515629..ecd12a7dcc 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -205,6 +205,7 @@ SFILES = \
 	$(srcdir)/common/fileio.c \
 	$(srcdir)/common/filestuff.c \
 	$(srcdir)/common/job-control.c \
+	$(srcdir)/common/gdb_chdir.c \
 	$(srcdir)/common/gdb_vecs.c \
 	$(srcdir)/common/new-op.c \
 	$(srcdir)/common/print-utils.c \
@@ -247,6 +248,7 @@ OBS = \
 	fileio.o \
 	filestuff.o \
 	format.o \
+	gdb_chdir.o \
 	gdb_vecs.o \
 	hostio.o \
 	inferiors.o \
-- 
2.13.3

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

* [PATCH v2 5/5] Extend "set cwd" to work on gdbserver
  2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
                     ` (2 preceding siblings ...)
  2017-09-19  4:28   ` [PATCH v2 3/5] Introduce gdb_chdir Sergio Durigan Junior
@ 2017-09-19  4:33   ` Sergio Durigan Junior
  2017-09-20 14:34     ` Pedro Alves
  2017-09-19  4:37   ` [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-19  4:33 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This is the "natural" extension necessary for the "set cwd" command
(and the whole "set the inferior's cwd" logic) to work on gdbserver.

The idea here is to have a new remote packet, QSetWorkingDir (name
adopted from LLDB's extension to the RSP, as can be seen at
<https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
which sends an hex-encoded string representing the working directory
that gdbserver is supposed to cd into before executing the inferior.
The good thing is that since this feature is already implemented on
nat/fork-inferior.c, all gdbserver has to do is to basically implement
"set_inferior_cwd" and call it whenever such packet arrives.

Aside from that, the patch consists basically of updates to the
testcase (making it available on remote targets) the documentation.

No regressions found.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (Changes since GDB 8.0): Add entry about new
	'set-cwd-on-gdbserver' feature.
	(New remote packets): Add entry for QSetWorkingDir.
	* common/common-inferior.h (set_inferior_cwd): New prototype.
	* infcmd.c (set_inferior_cwd): Remove "static".
	* remote.c: Add PACKET_QSetWorkingDir.
	(remote_protocol_features) <QSetWorkingDir>: New entry for
	PACKET_QSetWorkingDir.
	(extended_remote_handle_inferior_cwd): New function.
	(extended_remote_create_inferior): Call
	"extended_remote_handle_inferior_cwd".
	(_initialize_remote): Call "add_packet_config_cmd" for
	QSetWorkingDir.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (set_inferior_cwd): New function.
	* server.c (handle_general_set): Handle QSetWorkingDir packet.
	(handle_query): Inform that QSetWorkingDir is supported.
	* win32-low.c (create_process): Pass "inferior_cwd" to
	CreateProcess.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.exp: Make it available on gdbserver.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention remote debugging.
	(Working Directory) <Your Program's Working Directory>:
	Likewise.
	(Connecting) <Remote Packet>: Add "set-working-dir"
	and "QSetWorkingDir" to the table.
	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
	packet.
---
 gdb/NEWS                           | 11 ++++++++++
 gdb/common/common-inferior.h       |  4 ++++
 gdb/doc/gdb.texinfo                | 44 ++++++++++++++++++++++++++++++++++----
 gdb/gdbserver/inferiors.c          |  9 ++++++++
 gdb/gdbserver/server.c             | 18 +++++++++++++++-
 gdb/gdbserver/win32-low.c          |  5 +++--
 gdb/infcmd.c                       |  5 ++---
 gdb/remote.c                       | 35 ++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 14 ++++++++----
 9 files changed, 131 insertions(+), 14 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 0dcfcc98af..a0f78e4c35 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -39,6 +39,14 @@
      variables that are to be set or unset from GDB.  These variables
      will affect the environment to be passed to the inferior.
 
+  ** On Unix systems, GDBserver is now able to enter a directory
+     before starting an inferior.
+
+     This is done by using the "cd" command in GDB, which instructs it
+     to tell GDBserver about this directory change the next time an
+     inferior is run.  If you want to make GDBserver enter the
+     directory your GDB is currently in, you can do a "cd ." in GDB.
+
 * New remote packets
 
 QEnvironmentHexEncoded
@@ -56,6 +64,9 @@ QEnvironmentReset
 QStartupWithShell
   Indicates whether the inferior must be started with a shell or not.
 
+QSetWorkingDir
+  Tell GDBserver to enter another directory before starting the inferior.
+
 * The "maintenance print c-tdesc" command now takes an optional
   argument which is the file name of XML target description.
 
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 515a8c0f4e..65c23a936b 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -34,4 +34,8 @@ extern char *get_exec_file (int err);
    been set, then return NULL.  */
 extern const char *get_inferior_cwd ();
 
+/* Set the inferior current working directory.  This directory will be
+   entered by the debugger before executing the inferior.  */
+extern void set_inferior_cwd (const char *cwd);
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c513a49c26..fc20a74bce 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
 @item The @emph{working directory.}
 You can set your program's working directory with the command
 @code{set cwd}.  If you do not set any working directory with this
-command, your program will inherit @value{GDBN}'s working directory.
-@xref{Working Directory, ,Your Program's Working Directory}.
+command, your program will inherit @value{GDBN}'s working directory if
+native debugging, or @code{gdbserver}'s working directory if remote
+debugging.  @xref{Working Directory, ,Your Program's Working
+Directory}.
 
 @item The @emph{standard input and output.}
 Your program normally uses the same device for standard input and
@@ -2429,7 +2431,9 @@ Each time you start your program with @code{run}, the inferior will be
 initialized with the current working directory specified by the
 @code{set cwd} command.  If no directory has been specified by this
 command, then the inferior will inherit @value{GDBN}'s current working
-directory as its working directory.
+directory as its working directory if native debugging, or it will
+inherit @code{gdbserver}'s current working directory if remote
+debugging.
 
 You can also change @value{GDBN}'s current working directory by using
 the @code{cd} command.
@@ -2444,7 +2448,8 @@ Specify Files}.
 @item set cwd @r{[}@var{directory}@r{]}
 Set the inferior's working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.  This has no effect on
-@value{GDBN}'s working directory.
+@value{GDBN}'s working directory.  This setting works for both native
+and remote debugging.
 
 @kindex show cwd
 @cindex show inferior's working directory
@@ -20982,6 +20987,10 @@ are:
 @tab @code{QEnvironmentReset}
 @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
 
+@item @code{set-working-dir}
+@tab @code{QSetWorkingDir}
+@tab @code{cd}
+
 @item @code{conditional-breakpoints-packet}
 @tab @code{Z0 and Z1}
 @tab @code{Support for target-side breakpoint condition evaluation}
@@ -36770,6 +36779,30 @@ Reply:
 @table @samp
 @item OK
 The request succeeded.
+
+@item QSetWorkingDir:@var{hex-value}
+@anchor{QSetWorkingDir packet}
+@cindex set working directory, remote request
+@cindex @samp{QSetWorkingDir} packet
+On UNIX-like targets, it is possible to set the current working
+directory that @command{gdbserver} will enter before starting the
+inferior.  This packet is used to inform @command{gdbserver} of a
+directory into which it should enter during the startup process.
+
+The packet is composed by @var{hex-value}, an hex encoded
+representation of the directory to be entered by @command{gdbserver}.
+
+This packet is only transmitted when the user issues a @code{cd}
+command in @value{GDBN} (@pxref{Working Directory, ,Your Program's
+Working Directory}).
+
+This packet is only available in extended mode (@pxref{extended
+mode}).
+
+Reply:
+@table @samp
+@item OK
+The request succeeded.
 @end table
 
 This packet is not probed by default; the remote stub must request it,
@@ -36800,6 +36833,9 @@ Reply:
 @table @samp
 @item OK
 The request succeeded.
+
+@item E @var{nn}
+An error occurred.  The error number @var{nn} is given as hex digits.
 @end table
 
 This packet is not probed by default; the remote stub must request it,
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index e78ad4faf1..326d01f4d9 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -456,3 +456,12 @@ get_inferior_cwd ()
 {
   return current_inferior_cwd;
 }
+
+/* See common/common-inferior.h.  */
+
+void
+set_inferior_cwd (const char *cwd)
+{
+  xfree ((void *) current_inferior_cwd);
+  current_inferior_cwd = xstrdup (cwd);
+}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index f4faff9d77..a159708632 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -869,6 +869,21 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QSetWorkingDir:"))
+    {
+      const char *p = own_buf + strlen ("QSetWorkingDir:");
+      std::string path = hex2str (p);
+
+      set_inferior_cwd (path.c_str ());
+
+      if (remote_debug)
+	debug_printf (_("[Changed current directory to %s]\n"),
+		      path.c_str ());
+      write_ok (own_buf);
+
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -2345,7 +2360,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       sprintf (own_buf,
 	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
 	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
-	       "QEnvironmentReset+;QEnvironmentUnset+",
+	       "QEnvironmentReset+;QEnvironmentUnset+;"
+	       "QSetWorkingDir+",
 	       PBUFSIZ - 1);
 
       if (target_supports_catch_syscall ())
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index cc84d15c2f..b9fff29d74 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -562,6 +562,7 @@ static BOOL
 create_process (const char *program, char *args,
 		DWORD flags, PROCESS_INFORMATION *pi)
 {
+  const char *inferior_cwd = get_inferior_cwd ();
   BOOL ret;
 
 #ifdef _WIN32_WCE
@@ -586,7 +587,7 @@ create_process (const char *program, char *args,
 			FALSE,    /* inherit handles, not supported */
 			flags,    /* start flags */
 			NULL,     /* environment, not supported */
-			NULL,     /* current directory, not supported */
+			inferior_cwd,     /* current directory */
 			NULL,     /* start info, not supported */
 			pi);      /* proc info */
 #else
@@ -599,7 +600,7 @@ create_process (const char *program, char *args,
 			TRUE,     /* inherit handles */
 			flags,    /* start flags */
 			NULL,     /* environment */
-			NULL,     /* current directory */
+			inferior_cwd,     /* current directory */
 			&si,      /* start info */
 			pi);      /* proc info */
 #endif
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 178a3ca15f..a51a3d4e40 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -252,10 +252,9 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
-/* Set the inferior current working directory.  This directory will be
-   entered by GDB before executing the inferior.  */
+/* See common/common-inferior.h.  */
 
-static void
+void
 set_inferior_cwd (const char *cwd)
 {
   struct inferior *inf = current_inferior ();
diff --git a/gdb/remote.c b/gdb/remote.c
index 0963693a22..d900157ca9 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1428,6 +1428,7 @@ enum {
   PACKET_QPassSignals,
   PACKET_QCatchSyscalls,
   PACKET_QProgramSignals,
+  PACKET_QSetWorkingDir,
   PACKET_QStartupWithShell,
   PACKET_QEnvironmentHexEncoded,
   PACKET_QEnvironmentReset,
@@ -4637,6 +4638,8 @@ static const struct protocol_feature remote_protocol_features[] = {
     PACKET_QCatchSyscalls },
   { "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
     PACKET_QProgramSignals },
+  { "QSetWorkingDir", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QSetWorkingDir },
   { "QStartupWithShell", PACKET_DISABLE, remote_supported_packet,
     PACKET_QStartupWithShell },
   { "QEnvironmentHexEncoded", PACKET_DISABLE, remote_supported_packet,
@@ -9616,6 +9619,33 @@ extended_remote_environment_support (struct remote_state *rs)
       send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
 }
 
+/* Helper function to handle the change of the current working
+   directory in the remote.  */
+
+static void
+extended_remote_handle_inferior_cwd (struct remote_state *rs)
+{
+  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
+    {
+      const char *inferior_cwd = get_inferior_cwd ();
+
+      if (inferior_cwd != NULL)
+	{
+	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
+					 strlen (inferior_cwd));
+
+	  xsnprintf (rs->buf, get_remote_packet_size (),
+		     "QSetWorkingDir:%s", hexpath.c_str ());
+	  putpkt (rs->buf);
+	  getpkt (&rs->buf, &rs->buf_size, 0);
+	  if (strcmp (rs->buf, "OK") != 0)
+	    error (_("\
+Remote replied unexpectedly while changing working directory: %s"),
+		   rs->buf);
+	}
+    }
+}
+
 /* In the extended protocol we want to be able to do things like
    "run" and have them basically work as expected.  So we need
    a special create_inferior function.  We support changing the
@@ -9658,6 +9688,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
 
   extended_remote_environment_support (rs);
 
+  extended_remote_handle_inferior_cwd (rs);
+
   /* Now restart the remote server.  */
   run_worked = extended_remote_run (args) != -1;
   if (!run_worked)
@@ -14126,6 +14158,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
 			 "QProgramSignals", "program-signals", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
+			 "QSetWorkingDir", "set-working-dir", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
 			 "QStartupWithShell", "startup-with-shell", 0);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
index 3a6ffd3862..d3104287a0 100644
--- a/gdb/testsuite/gdb.base/set-cwd.exp
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -15,10 +15,16 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if { ![isnative] || [is_remote target] || [is_remote host]
-     || [target_info gdb_protocol] == "extended-remote" } then {
-    untested "not implemented on gdbserver"
-    return
+if { [target_info exists gdb_protocol] } {
+    if { [target_info gdb_protocol] == "remote" } {
+	untested "not implemented on native-gdbserver"
+	return
+    }
+
+    load_lib gdbserver-support.exp
+    if { [skip_gdbserver_tests] } {
+	return
+    }
 }
 
 standard_testfile
-- 
2.13.3

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

* [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
                     ` (3 preceding siblings ...)
  2017-09-19  4:33   ` [PATCH v2 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
@ 2017-09-19  4:37   ` Sergio Durigan Junior
  2017-09-20 12:17     ` Pedro Alves
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-19  4:37 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

[ Resending as the original e-mail got bounced because it is too long to
  be posted here. ]

The full patch can be seen here:

  https://git.sergiodj.net/binutils-gdb.git/commit/?h=sergiodj/set-cwd-command&id=acf35a31bac3951f81d0446564b7f910a0fee21c

These two modules are necessary because of the rework that will be
done in the "change directory" logic on GDB/gdbserver in the next
commits.

First, we will get rid of the "gdb_dirbuf" global variable and instead
rely on the fact that "getcwd (NULL, 0)" returns a heap-allocated
string with the necessary bytes to hold the full path.  This is a good
practice not only because globals are not ideal but also because there
is no good way to know beforehand the size of the full pathname
allowed in the filesystem ("PATH_MAX" is not portable and does not
reflect all the possible filesystems out there).

We will also have a way to "cd" to a directory also on gdbserver, but
in order to do that uniformly, there must be a way to do tilde
expansion on directories provided by the user.  Currently, GDB uses
"tilde_expand" from readline to do that, but gdbserver doesn't link
against readline and therefore cannot use this function.  The solution
is to use "glob" instead, which can perform tilde expansion as a GNU
extension.  Therefore, we need gnulib's version of "glob".

As a side note, we no longer need to define "close" on gdb/ser-tcp.c,
so the patch removes that.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gnulib/aclocal.m4: Regenerate.
	* gnulib/config.in: Likewise.
	* gnulib/configure: Likewise.
	* gnulib/import/Makefile.am: Likewise.
	* gnulib/import/Makefile.in: Likewise.
	* gnulib/import/assure.h: New file.
	* gnulib/import/at-func.c: Likewise
	* gnulib/import/chdir-long.c: Likewise.
	* gnulib/import/chdir-long.h: Likewise.
	* gnulib/import/cloexec.c: Likewise.
	* gnulib/import/cloexec.h: Likewise.
	* gnulib/import/close.c: Likewise.
	* gnulib/import/closedir.c: Likewise.
	* gnulib/import/dirent-private.h: Likewise.
	* gnulib/import/dup-safer.c: Likewise.
	* gnulib/import/dup.c: Likewise.
	* gnulib/import/dup2.c: Likewise.
	* gnulib/import/error.c: Likewise.
	* gnulib/import/error.h: Likewise.
	* gnulib/import/exitfail.c: Likewise.
	* gnulib/import/exitfail.h: Likewise.
	* gnulib/import/fchdir.c: Likewise.
	* gnulib/import/fcntl.c: Likewise.
	* gnulib/import/fcntl.in.h: Likewise.
	* gnulib/import/fd-hook.c: Likewise.
	* gnulib/import/fd-hook.h: Likewise.
	* gnulib/import/fd-safer.c: Likewise.
	* gnulib/import/fdopendir.c: Likewise.
	* gnulib/import/filename.h: Likewise.
	* gnulib/import/filenamecat-lgpl.c: Likewise.
	* gnulib/import/filenamecat.h: Likewise.
	* gnulib/import/fstat.c: Likewise.
	* gnulib/import/fstatat.c: Likewise.
	* gnulib/import/getcwd-lgpl.c: Likewise.
	* gnulib/import/getcwd.c: Likewise.
	* gnulib/import/getdtablesize.c: Likewise.
	* gnulib/import/getlogin_r.c: Likewise.
	* gnulib/import/getprogname.c: Likewise.
	* gnulib/import/getprogname.h: Likewise.
	* gnulib/import/gettext.h: Likewise.
	* gnulib/import/glob-libc.h: Likewise.
	* gnulib/import/glob.c: Likewise.
	* gnulib/import/glob.in.h: Likewise.
	* gnulib/import/intprops.h: Likewise.
	* gnulib/import/m4/chdir-long.m4: Likewise.
	* gnulib/import/m4/close.m4: Likewise.
	* gnulib/import/m4/closedir.m4: Likewise.
	* gnulib/import/m4/d-ino.m4: Likewise.
	* gnulib/import/m4/d-type.m4: Likewise.
	* gnulib/import/m4/dup.m4: Likewise.
	* gnulib/import/m4/dup2.m4: Likewise.
	* gnulib/import/m4/error.m4: Likewise.
	* gnulib/import/m4/fchdir.m4: Likewise.
	* gnulib/import/m4/fcntl.m4: Likewise.
	* gnulib/import/m4/fcntl_h.m4: Likewise.
	* gnulib/import/m4/fdopendir.m4: Likewise.
	* gnulib/import/m4/filenamecat.m4: Likewise.
	* gnulib/import/m4/fstat.m4: Likewise.
	* gnulib/import/m4/fstatat.m4: Likewise.
	* gnulib/import/m4/getcwd-abort-bug.m4: Likewise.
	* gnulib/import/m4/getcwd-path-max.m4: Likewise.
	* gnulib/import/m4/getcwd.m4: Likewise.
	* gnulib/import/m4/getdtablesize.m4: Likewise.
	* gnulib/import/m4/getlogin_r.m4: Likewise.
	* gnulib/import/m4/getprogname.m4: Likewise.
	* gnulib/import/m4/glob.m4: Likewise.
	* gnulib/import/m4/gnulib-cache.m4: Regenerate
	* gnulib/import/m4/gnulib-comp.m4: Likewise.
	* gnulib/import/m4/mempcpy.m4: New file.
	* gnulib/import/m4/memrchr.m4: Likewise.
	* gnulib/import/m4/mode_t.m4: Likewise.
	* gnulib/import/m4/msvc-inval.m4: Likewise.
	* gnulib/import/m4/msvc-nothrow.m4: Likewise.
	* gnulib/import/m4/open.m4: Likewise.
	* gnulib/import/m4/openat.m4: Likewise.
	* gnulib/import/m4/opendir.m4: Likewise.
	* gnulib/import/m4/readdir.m4: Likewise.
	* gnulib/import/m4/realloc.m4: Likewise.
	* gnulib/import/m4/rewinddir.m4: Likewise.
	* gnulib/import/m4/save-cwd.m4: Likewise.
	* gnulib/import/m4/strdup.m4: Likewise.
	* gnulib/import/m4/strerror.m4: Likewise.
	* gnulib/import/m4/unistd-safer.m4: Likewise.
	* gnulib/import/mempcpy.c: Likewise.
	* gnulib/import/memrchr.c: Likewise.
	* gnulib/import/msvc-inval.c: Likewise.
	* gnulib/import/msvc-inval.h: Likewise.
	* gnulib/import/msvc-nothrow.c: Likewise.
	* gnulib/import/msvc-nothrow.h: Likewise.
	* gnulib/import/open.c: Likewise.
	* gnulib/import/openat-die.c: Likewise.
	* gnulib/import/openat-priv.h: Likewise.
	* gnulib/import/openat-proc.c: Likewise.
	* gnulib/import/openat.c: Likewise.
	* gnulib/import/openat.h: Likewise.
	* gnulib/import/opendir.c: Likewise.
	* gnulib/import/pipe-safer.c: Likewise.
	* gnulib/import/readdir.c: Likewise.
	* gnulib/import/realloc.c: Likewise.
	* gnulib/import/rewinddir.c: Likewise.
	* gnulib/import/save-cwd.c: Likewise.
	* gnulib/import/save-cwd.h: Likewise.
	* gnulib/import/strdup.c: Likewise.
	* gnulib/import/strerror-override.c: Likewise.
	* gnulib/import/strerror-override.h: Likewise.
	* gnulib/import/strerror.c: Likewise.
	* gnulib/import/unistd--.h: Likewise.
	* gnulib/import/unistd-safer.h: Likewise.
	* gnulib/update-gnulib.sh (IMPORTED_GNULIB_MODULES): Add
	"getcwd" and "glob".
	* ser-tcp.c: Do not (re)define "close".


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

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-19  4:37   ` [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
@ 2017-09-20 12:17     ` Pedro Alves
  2017-09-20 17:17       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 12:17 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/19/2017 05:37 AM, Sergio Durigan Junior wrote:
> [ Resending as the original e-mail got bounced because it is too long to
>   be posted here. ]
> 
> The full patch can be seen here:
> 
>   https://git.sergiodj.net/binutils-gdb.git/commit/?h=sergiodj/set-cwd-command&id=acf35a31bac3951f81d0446564b7f910a0fee21c
> 
> These two modules are necessary because of the rework that will be
> done in the "change directory" logic on GDB/gdbserver in the next
> commits.
> 
> First, we will get rid of the "gdb_dirbuf" global variable and instead
> rely on the fact that "getcwd (NULL, 0)" returns a heap-allocated
> string with the necessary bytes to hold the full path.  

Should mention that that's a GNU extension here.

> As a side note, we no longer need to define "close" on gdb/ser-tcp.c,
> so the patch removes that.
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* gnulib/aclocal.m4: Regenerate.
> 	* gnulib/config.in: Likewise.
...

> 	* gnulib/import/unistd-safer.h: Likewise.

Please say "New file." for new files above, not Likewise->Regenerate.

> 	* ser-tcp.c: Do not (re)define "close".
> 

This is:

--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -42,7 +42,6 @@
 #ifndef ETIMEDOUT
 #define ETIMEDOUT WSAETIMEDOUT
 #endif
-#define close(fd) closesocket (fd)

Are you sure that the gnulib code that makes close work
for sockets is enabled?  I guess it will if WINDOWS_SOCKETS
is defined, but it wasn't obvious to me whether it'll end
up defined with the current set of modules.

Boy, these modules sure bring in a lot of stuff.
I noticed that this is bringing in the strerror module, which was
problematic in the past on mingw [1].  Could you please try
cross building gdb for mingw (should be easy since Fedora has
cross compilers handy), to confirm that it's alright now?
It it works, we could get rid of safe_strerror in a follow up
patch.

[1] https://sourceware.org/ml/gdb-patches/2013-11/msg00597.html
I don't recall whether that's been fixed meanwhile.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)"
  2017-09-19  4:28   ` [PATCH v2 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
@ 2017-09-20 12:24     ` Pedro Alves
  2017-09-20 17:02       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 12:24 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
> Currently we have "current_directory" and "gdb_dirbuf" globals, which
> means that we basically have two possible places to consult when we
> want to know GDB's current working directory.
> 
> This is not ideal and can lead to confusion.  Moreover, the way we're
> using "gdb_difbuf" along with "getcwd" is problematic because we
> declare the buffer with "1024" elements hardcoded, which does not take
> into account longer pathnames that are possible in many filesystems.
> Using "PATH_MAX" would also not be a solution because of portability
> problems.  Therefore, the best solution is to rely on the fact that
> "getcwd (NULL, 0)" will "do the right thing" and return a
> heap-allocated string containing the full path.  With the new "getcwd"
> module from gnulib, it is now possible to do that without worrying
> about breaking some target.

s/target/host/

> --- a/gdb/cli/cli-cmds.c
> +++ b/gdb/cli/cli-cmds.c
> @@ -382,13 +382,16 @@ pwd_command (char *args, int from_tty)
>  {
>    if (args)
>      error (_("The \"pwd\" command does not take an argument: %s"), args);
> -  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
> +
> +  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
> +
> +  if (cwd.get () == NULL)

No need for get() here:

  if (cwd == NULL)

> diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
> index 977b6e274d..1e4c09352f 100644
> --- a/gdb/mi/mi-cmd-env.c
> +++ b/gdb/mi/mi-cmd-env.c
> @@ -73,12 +73,12 @@ mi_cmd_env_pwd (const char *command, char **argv, int argc)
>      }
>       
>    /* Otherwise the mi level is 2 or higher.  */
> -
> -  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
> +  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
> +  if (cwd.get () == NULL)

Ditto.

Otherwise OK.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 3/5] Introduce gdb_chdir
  2017-09-19  4:28   ` [PATCH v2 3/5] Introduce gdb_chdir Sergio Durigan Junior
@ 2017-09-20 13:14     ` Pedro Alves
  2017-09-20 17:25       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 13:14 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
> In order to be able to change the inferior's directory before its
> execution, it is necessary to perform a tilde expansion of the
> directory provided by the user and then chdir into the resulting dir.
> This is what gdb_chdir does.
> 
> Unfortunately it is not possible to use "tilde_expand" from readline
> because this is common code and gdbserver doesn't use readline.  For
> that reason I decided to go with "glob" and its GNU extension,
> GLOB_TILDE.  With the import of the "glob" module from gnulib, this is
> a no-brainer.
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* Makefile.in (SFILES): Add gdb_chdir.c.
> 	(HFILES_NO_SRCDIR): Add gdb_chdir.h.
> 	(COMMON_OBS): Add gdb_chdir.o.
> 	* cli/cli-cmds.c: Include "gdb_chdir.h".
> 	(cd_command): Use "gdb_chdir" instead of "tilde_expand
> 	plus chdir".
> 	* common/gdb_chdir.c: New file.
> 	* common/gdb_chdir.h: Likewise.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* Makefile.in (SFILES): Add $(srcdir)/common/gdb_chdir.c.
> 	(OBS): Add gdb_chdir.o.
> ---
>  gdb/Makefile.in           |  3 ++
>  gdb/cli/cli-cmds.c        | 20 +++++-----
>  gdb/common/gdb_chdir.c    | 96 +++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/common/gdb_chdir.h    | 26 +++++++++++++
>  gdb/gdbserver/Makefile.in |  2 +
>  5 files changed, 136 insertions(+), 11 deletions(-)
>  create mode 100644 gdb/common/gdb_chdir.c
>  create mode 100644 gdb/common/gdb_chdir.h
> 
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 9dfc117b2f..1f093e6c0f 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -1245,6 +1245,7 @@ SFILES = \
>  	common/filestuff.c \
>  	common/format.c \
>  	common/job-control.c \
> +	common/gdb_chdir.c \
>  	common/gdb_vecs.c \
>  	common/new-op.c \
>  	common/print-utils.c \
> @@ -1529,6 +1530,7 @@ HFILES_NO_SRCDIR = \
>  	common/fileio.h \
>  	common/format.h \
>  	common/gdb_assert.h \
> +	common/gdb_chdir.h \
>  	common/gdb_locale.h \
>  	common/gdb_setjmp.h \
>  	common/gdb_signals.h \
> @@ -1734,6 +1736,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
>  	frame-unwind.o \
>  	gcore.o \
>  	gdb_bfd.o \
> +	gdb_chdir.o \
>  	gdb-dlfcn.o \
>  	gdb_obstack.o \
>  	gdb_regex.o \
> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
> index 85d6d21113..653dd56a64 100644
> --- a/gdb/cli/cli-cmds.c
> +++ b/gdb/cli/cli-cmds.c
> @@ -54,6 +54,8 @@
>  #include "tui/tui.h"	/* For tui_active et.al.  */
>  #endif
>  
> +#include "gdb_chdir.h"
> +
>  #include <fcntl.h>
>  #include <algorithm>
>  #include <string>
> @@ -408,12 +410,7 @@ cd_command (char *dir, int from_tty)
>       repeat might be useful but is more likely to be a mistake.  */
>    dont_repeat ();
>  
> -  gdb::unique_xmalloc_ptr<char> dir_holder
> -    (tilde_expand (dir != NULL ? dir : "~"));
> -  dir = dir_holder.get ();
> -
> -  if (chdir (dir) < 0)
> -    perror_with_name (dir);
> +  gdb_chdir (dir != NULL ? dir : "~");
>  
>  #ifdef HAVE_DOS_BASED_FILE_SYSTEM
>    /* There's too much mess with DOSish names like "d:", "d:.",
> @@ -436,20 +433,21 @@ cd_command (char *dir, int from_tty)
>  	len--;
>      }
>  
> -  dir_holder.reset (savestring (dir, len));
> -  if (IS_ABSOLUTE_PATH (dir_holder.get ()))
> +  std::string newdir = std::string (dir, len);
> +  const char *newdir_str = newdir.c_str ();
> +  if (IS_ABSOLUTE_PATH (newdir_str))
>      {
>        xfree (current_directory);
> -      current_directory = dir_holder.release ();
> +      current_directory = xstrdup (newdir_str);

This introduces one extra deep string dup.  One to
construct the std::string, and another here in this xstrdup.

How about simply, above:

 -  dir_holder.reset (savestring (dir, len));
 +  gdb::unique_xmalloc_ptr<char> dir_holder (savestring (dir, len))


But more importantly, isn't there a behavior change here?
Before, current_directory would be a copy of the the expand
path, while after the patch, it's a copy of the input string,
before expansion.  Right?


>      }
>    else
>      {
>        if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
> -	current_directory = concat (current_directory, dir_holder.get (),
> +	current_directory = concat (current_directory, newdir_str,
>  				    (char *) NULL);
>        else
>  	current_directory = concat (current_directory, SLASH_STRING,
> -				    dir_holder.get (), (char *) NULL);
> +				    newdir_str, (char *) NULL);
>      }


> +  /* Destroy the object and free M_GLOB.  */
> +  ~gdb_glob ()
> +  {
> +    globfree (&m_glob);
> +  }
> +
> +  /* Return the GL_PATHC component of M_GLOB.  */
> +  int
> +  pathc () const
> +  {
> +    return m_glob.gl_pathc;
> +  }

We've been putting type and function name in the
same line in inline member functions.  That's the
de facto standard in GCC as well, AFAICS.

> +
> +  /* Return the GL_PATHV component of M_GLOB.  */
> +  char **
> +  pathv () const
> +  {
> +    return m_glob.gl_pathv;
> +  }

Ditto.

> +#ifndef HAVE_GDB_CHDIR_H
> +#define HAVE_GDB_CHDIR_H
> +
> +/* Perform a "chdir" to DIR, doing the proper tilde expansion before.  */
> +extern void gdb_chdir (const char *dir);

Nit, I'd drop "the proper", as it doesn't see to add value.
I.e., what's proper and what's not proper?

Thanks,
Pedro Alves

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

* Re: [PATCH v2 4/5] Implement "set cwd" command
  2017-09-19  4:28   ` [PATCH v2 4/5] Implement " Sergio Durigan Junior
@ 2017-09-20 14:01     ` Pedro Alves
  2017-09-20 23:08       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 14:01 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:

> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
> index 653dd56a64..f086f10aea 100644
> --- a/gdb/cli/cli-cmds.c
> +++ b/gdb/cli/cli-cmds.c
> @@ -1716,9 +1716,9 @@ The commands below can be used to select other frames by number or address."),
>  Print working directory.  This is used for your program as well."));
>  
>    c = add_cmd ("cd", class_files, cd_command, _("\
> -Set working directory to DIR for debugger and program being debugged.\n\
> -The change does not take effect for the program being debugged\n\
> -until the next time it is started."), &cmdlist);
> +Set working directory to DIR for debugger.\n\


I think it'd be nice to add a sentence here suggesting what the
current working directory affects.

> +In order to change the inferior's current working directory, the recommended\n\
> +way is to use the \"set cwd\" command."), &cmdlist);
>    set_cmd_completer (c, filename_completer);
>  
>    add_com ("echo", class_support, echo_command, _("\
> diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
> index 87c13009ed..515a8c0f4e 100644
> --- a/gdb/common/common-inferior.h
> +++ b/gdb/common/common-inferior.h
> @@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
>     otherwise return 0 in that case.  */
>  extern char *get_exec_file (int err);
>  
> +/* Return the inferior's current working directory.  If nothing has
> +   been set, then return NULL.  */
> +extern const char *get_inferior_cwd ();
> +
>  #endif /* ! COMMON_INFERIOR_H */
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index af5fe6f46c..c513a49c26 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
>  your program.  @xref{Environment, ,Your Program's Environment}.
>  
>  @item The @emph{working directory.}
> -Your program inherits its working directory from @value{GDBN}.  You can set
> -the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
> +You can set your program's working directory with the command
> +@code{set cwd}.  If you do not set any working directory with this
> +command, your program will inherit @value{GDBN}'s working directory.
>  @xref{Working Directory, ,Your Program's Working Directory}.
>  
>  @item The @emph{standard input and output.}
> @@ -2424,19 +2425,36 @@ variables to files that are only run when you sign on, such as
>  @section Your Program's Working Directory
>  
>  @cindex working directory (of your program)
> -Each time you start your program with @code{run}, it inherits its
> -working directory from the current working directory of @value{GDBN}.
> -The @value{GDBN} working directory is initially whatever it inherited
> -from its parent process (typically the shell), but you can specify a new
> -working directory in @value{GDBN} with the @code{cd} command.
> +Each time you start your program with @code{run}, the inferior will be
> +initialized with the current working directory specified by the
> +@code{set cwd} command.  If no directory has been specified by this
> +command, then the inferior will inherit @value{GDBN}'s current working
> +directory as its working directory.
> +
> +You can also change @value{GDBN}'s current working directory by using
> +the @code{cd} command.
>  
>  The @value{GDBN} working directory also serves as a default for the commands
>  that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
>  Specify Files}.
>  
>  @table @code
> +@kindex set cwd
> +@cindex change inferior's working directory
> +@item set cwd @r{[}@var{directory}@r{]}
> +Set the inferior's working directory to @var{directory}.  If not
> +given, @var{directory} uses @file{'~'}.  This has no effect on
> +@value{GDBN}'s working directory.


I think we're missing a sentence somewhere in the manual saying that 
this setting only takes effect the next time you start the program, 
like it is said in "help cd" currently.

> +
> +@kindex show cwd
> +@cindex show inferior's working directory
> +@item show cwd
> +Show the inferior's working directory.  If no directory has been
> +specified by @code{set cwd}, then the default inferior's working
> +directory is the same as @value{GDBN}'s working directory.
> +
>  @kindex cd
> -@cindex change working directory
> +@cindex change @value{GDBN}'s working directory
>  @item cd @r{[}@var{directory}@r{]}
>  Set the @value{GDBN} working directory to @var{directory}.  If not
>  given, @var{directory} uses @file{'~'}.
> diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
> index 72f0412757..e78ad4faf1 100644
> --- a/gdb/gdbserver/inferiors.c
> +++ b/gdb/gdbserver/inferiors.c
> @@ -29,6 +29,9 @@ struct thread_info *current_thread;
>  
>  #define get_thread(inf) ((struct thread_info *)(inf))
>  
> +/* The current working directory used to start the inferior.  */
> +static const char *current_inferior_cwd = NULL;
> +
>  void
>  add_inferior_to_list (struct inferior_list *list,
>  		      struct inferior_list_entry *new_inferior)
> @@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
>    if (!ptid_equal (ptid, minus_one_ptid))
>      current_thread = find_thread_ptid (ptid);
>  }
> +
> +/* See common/common-inferior.h.  */
> +
> +const char *
> +get_inferior_cwd ()
> +{
> +  return current_inferior_cwd;
> +}
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 25cf025426..178a3ca15f 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -59,6 +59,8 @@
>  #include "top.h"
>  #include "interps.h"
>  #include "common/gdb_optional.h"
> +#include "gdb_chdir.h"
> +#include "readline/tilde.h"
>  
>  /* Local functions: */
>  
> @@ -111,6 +113,10 @@ static void run_command (char *, int);
>  
>  static char *inferior_args_scratch;
>  
> +/* Scratch area where the new cwd will be stored by 'set cwd'.  */
> +
> +static char *inferior_cwd_scratch;
> +
>  /* Scratch area where 'set inferior-tty' will store user-provided value.
>     We'll immediate copy it into per-inferior storage.  */
>  
> @@ -246,6 +252,56 @@ show_args_command (struct ui_file *file, int from_tty,
>    deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
>  }
>  
> +/* Set the inferior current working directory.  This directory will be
> +   entered by GDB before executing the inferior.  */

The second sentence is talking about implementation details of Unix-like
targets, which doesn't really belong here.

> +
> +static void
> +set_inferior_cwd (const char *cwd)
> +{
> +  struct inferior *inf = current_inferior ();
> +
> +  gdb_assert (inf != NULL);
> +  xfree ((void *) inf->cwd);
> +  inf->cwd = tilde_expand (*cwd != '\0' ? cwd : "~");

So the inferior owns the string?  Wouldn't it be better if
inf->cwd were a unique_ptr?  I don't see anywhere releasing
the cwd string when an inferior is deleted.

> +
> +/* Handle the 'show cwd' command.  */
> +
> +static void
> +show_cwd_command (struct ui_file *file, int from_tty,
> +		  struct cmd_list_element *c, const char *value)
> +{
> +  const char *cwd = get_inferior_cwd ();
> +
> +  if (cwd == NULL)
> +    {
> +      /* To maintain backwards compatibility, we use
> +	 'current_directory' here, which is set by the "cd"
> +	 command.  */
> +      cwd = current_directory;
> +    }

This doesn't look like the right thing to show, to me.
It'll only make sense for native debugging, not remote debugging,
right?  I mean, when remote debugging, the inferior won't inherit
gdb's cwd.  Right?

> +
> +  fprintf_filtered (gdb_stdout,
> +		    _("Current working directory that will be used "
> +		      "when starting the inferior is \"%s\".\n"), cwd);
> +}
> +
>  \f

> index 6d020f73c4..bcd1e54a03 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -355,6 +355,10 @@ public:
>       should never be freed.  */
>    char **argv = NULL;
>  
> +  /* The current working directory that will be used when starting
> +     this inferior.  */
> +  const char *cwd = NULL;

See comment above in set_inferior_cwd.  Who owns this string?
Looks like removing the inferior leaks this?
Can this be a unique_xmalloc_ptr ?

> @@ -376,6 +377,22 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>  	 UIs.  */
>        close_most_fds ();
>  
> +      const char *cwd = get_inferior_cwd ();
> +
> +      if (cwd != NULL)
> +	{
> +	  TRY
> +	    {
> +	      gdb_chdir (cwd);
> +	    }
> +	  CATCH (ex, RETURN_MASK_ERROR)
> +	    {
> +	      warning ("%s", ex.message);
> +	      _exit (0177);
> +	    }
> +	  END_CATCH
> +	}

This is the fork-child path, and as such we should only be calling
async-signal-safe code.  And throwing C++ exceptions is not async-signal-safe.
I think an easy solution is to call gdb_tilde_expand _before_ forking, and
then call plain old chdir in the child, and then call
trace_start_error_with_name instead of perror_with_name on failure:

  if (chdir (expanded_dir.c_str ()) < 0)
    trace_start_error_with_name (expanded_dir.c_str ());

With that, I'm not sure whether gdb_chdir is still very useful
compared to using gdb_tilde_expand + chdir in the "cd" command too.

> +++ b/gdb/testsuite/gdb.base/set-cwd.c
> @@ -0,0 +1,29 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2017 Free Software Foundation, Inc.
> +
> +   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 <stdio.h>
> +#include <unistd.h>
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  char dir[BUFSIZ];
> +
> +  getcwd (dir, BUFSIZ);

Hmm, BUFSIZ came back?  :-)  Please use something like PATH_MAX
with a fallback to 1024 or some such.

> +
> +  return 0; /* break-here */
> +}
> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
> new file mode 100644
> index 0000000000..3a6ffd3862
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
> @@ -0,0 +1,90 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 2017 Free Software Foundation, Inc.
> +
> +# 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/>.
> +
> +if { ![isnative] || [is_remote target] || [is_remote host]
> +     || [target_info gdb_protocol] == "extended-remote" } then {
> +    untested "not implemented on gdbserver"

The skip on [is_remote host] surely has nothing to do with gdbserver, right?
Please split that up to a separate untested call with a meaningful gdb.sum
output message.  The rest of the checks don't look exactly right,
but I'll ignore that because surely you'll be changing it in the following
patch.

> +    return


> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
> +    return -1
> +}
> +
> +# Test that tilde expansion works fine.
> +
> +proc test_tilde_expansion { } {
> +    if { [info exists ::env(HOME)] } {
> +	with_test_prefix "test tilde expansion" {
> +	    set home $::env(HOME)
> +
> +	    gdb_test_no_output "set cwd ~/test" "set cwd to ~/test dir"
> +
> +	    gdb_test "show cwd" \
> +		"Current working directory that will be used when starting the inferior is \"${home}/test\"\." \
> +		"show cwd shows expanded tilde"
> +	}
> +    }
> +}
> +
> +# Test that when we "set cwd" the inferior will be started under the
> +# correct working directory and GDB will not be affected by this.
> +
> +proc test_cd_into_dir { } {
> +    global decimal gdb_prompt
> +
> +    with_test_prefix "test cd into temp dir" {
> +	gdb_test_multiple "pwd" "pwd before run" {
> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
> +		set gdb_cwd_before_run $expect_out(1,string)
> +	    }
> +	}

Is the above fails, then gdb_cwd_before_run is left unset,
and the next reference causes a TCL error.

> +
> +	set tmpdir [standard_output_file ""]
> +
> +	gdb_test_no_output "set cwd $tmpdir" "set cwd to temp dir"
> +
> +	if { ![runto_main] } {
> +	    untested "could not run to main"
> +	    return -1
> +	}
> +
> +	gdb_breakpoint [gdb_get_line_number "break-here"]
> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
> +
> +	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
> +	    "inferior cwd is correctly set"
> +
> +	gdb_test_multiple "pwd" "pwd after run" {
> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
> +		set gdb_cwd_after_run $expect_out(1,string)
> +	    }
> +	}

Likewise.


> +
> +	set test "GDB cwd is unchanged after running inferior"
> +	if { [string equal $gdb_cwd_before_run $gdb_cwd_after_run] } {
> +	    pass $test
> +	} else {
> +	    fail $test
> +	}

You can use gdb_assert instead of this if/else pass/fail.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 5/5] Extend "set cwd" to work on gdbserver
  2017-09-19  4:33   ` [PATCH v2 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
@ 2017-09-20 14:34     ` Pedro Alves
  2017-09-20 23:49       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 14:34 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
> This is the "natural" extension necessary for the "set cwd" command
> (and the whole "set the inferior's cwd" logic) to work on gdbserver.
> 
> The idea here is to have a new remote packet, QSetWorkingDir (name
> adopted from LLDB's extension to the RSP, as can be seen at
> <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
> which sends an hex-encoded string representing the working directory
> that gdbserver is supposed to cd into before executing the inferior.
> The good thing is that since this feature is already implemented on
> nat/fork-inferior.c, all gdbserver has to do is to basically implement
> "set_inferior_cwd" and call it whenever such packet arrives.
> 
> Aside from that, the patch consists basically of updates to the
> testcase (making it available on remote targets) the documentation.
> 
> No regressions found.
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* NEWS (Changes since GDB 8.0): Add entry about new
> 	'set-cwd-on-gdbserver' feature.
> 	(New remote packets): Add entry for QSetWorkingDir.
> 	* common/common-inferior.h (set_inferior_cwd): New prototype.
> 	* infcmd.c (set_inferior_cwd): Remove "static".
> 	* remote.c: Add PACKET_QSetWorkingDir.
> 	(remote_protocol_features) <QSetWorkingDir>: New entry for
> 	PACKET_QSetWorkingDir.
> 	(extended_remote_handle_inferior_cwd): New function.
> 	(extended_remote_create_inferior): Call
> 	"extended_remote_handle_inferior_cwd".
> 	(_initialize_remote): Call "add_packet_config_cmd" for
> 	QSetWorkingDir.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* inferiors.c (set_inferior_cwd): New function.
> 	* server.c (handle_general_set): Handle QSetWorkingDir packet.
> 	(handle_query): Inform that QSetWorkingDir is supported.
> 	* win32-low.c (create_process): Pass "inferior_cwd" to
> 	CreateProcess.
> 
> gdb/testsuite/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* gdb.base/set-cwd.exp: Make it available on gdbserver.
> 
> gdb/doc/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* gdb.texinfo (Starting your Program) <The working directory.>:
> 	Mention remote debugging.
> 	(Working Directory) <Your Program's Working Directory>:
> 	Likewise.
> 	(Connecting) <Remote Packet>: Add "set-working-dir"
> 	and "QSetWorkingDir" to the table.
> 	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
> 	packet.
> ---
>  gdb/NEWS                           | 11 ++++++++++
>  gdb/common/common-inferior.h       |  4 ++++
>  gdb/doc/gdb.texinfo                | 44 ++++++++++++++++++++++++++++++++++----
>  gdb/gdbserver/inferiors.c          |  9 ++++++++
>  gdb/gdbserver/server.c             | 18 +++++++++++++++-
>  gdb/gdbserver/win32-low.c          |  5 +++--
>  gdb/infcmd.c                       |  5 ++---
>  gdb/remote.c                       | 35 ++++++++++++++++++++++++++++++
>  gdb/testsuite/gdb.base/set-cwd.exp | 14 ++++++++----
>  9 files changed, 131 insertions(+), 14 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 0dcfcc98af..a0f78e4c35 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -39,6 +39,14 @@
>       variables that are to be set or unset from GDB.  These variables
>       will affect the environment to be passed to the inferior.
>  
> +  ** On Unix systems, GDBserver is now able to enter a directory
> +     before starting an inferior.
> +
> +     This is done by using the "cd" command in GDB, which instructs it
> +     to tell GDBserver about this directory change the next time an
> +     inferior is run.  If you want to make GDBserver enter the
> +     directory your GDB is currently in, you can do a "cd ." in GDB.

This all looks stale to me.

> +
>  * New remote packets
>  
>  QEnvironmentHexEncoded
> @@ -56,6 +64,9 @@ QEnvironmentReset
>  QStartupWithShell
>    Indicates whether the inferior must be started with a shell or not.
>  
> +QSetWorkingDir
> +  Tell GDBserver to enter another directory before starting the inferior.

Should this really be described in terms of gdbserver entering a
directory?  That seems like fork-child implementation detail.
Do we really want this to affect gdbserver's current directory
as well, maybe in future use cases, or just the inferior's cwd?

> --- a/gdb/common/common-inferior.h
> +++ b/gdb/common/common-inferior.h
> @@ -34,4 +34,8 @@ extern char *get_exec_file (int err);
>     been set, then return NULL.  */
>  extern const char *get_inferior_cwd ();
>  
> +/* Set the inferior current working directory.  This directory will be
> +   entered by the debugger before executing the inferior.  */
> +extern void set_inferior_cwd (const char *cwd);

Again described in terms of target implementation detail.

> +
>  #endif /* ! COMMON_INFERIOR_H */
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index c513a49c26..fc20a74bce 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
>  @item The @emph{working directory.}
>  You can set your program's working directory with the command
>  @code{set cwd}.  If you do not set any working directory with this
> -command, your program will inherit @value{GDBN}'s working directory.
> -@xref{Working Directory, ,Your Program's Working Directory}.
> +command, your program will inherit @value{GDBN}'s working directory if
> +native debugging, or @code{gdbserver}'s working directory if remote
> +debugging.  @xref{Working Directory, ,Your Program's Working
> +Directory}.
>  
>  @item The @emph{standard input and output.}
>  Your program normally uses the same device for standard input and
> @@ -2429,7 +2431,9 @@ Each time you start your program with @code{run}, the inferior will be
>  initialized with the current working directory specified by the
>  @code{set cwd} command.  If no directory has been specified by this
>  command, then the inferior will inherit @value{GDBN}'s current working
> -directory as its working directory.
> +directory as its working directory if native debugging, or it will
> +inherit @code{gdbserver}'s current working directory if remote
> +debugging.
>  
>  You can also change @value{GDBN}'s current working directory by using
>  the @code{cd} command.
> @@ -2444,7 +2448,8 @@ Specify Files}.
>  @item set cwd @r{[}@var{directory}@r{]}
>  Set the inferior's working directory to @var{directory}.  If not
>  given, @var{directory} uses @file{'~'}.  This has no effect on
> -@value{GDBN}'s working directory.
> +@value{GDBN}'s working directory.  This setting works for both native
> +and remote debugging.

Not sure we should add such a sentence for a particular command alone;
If I read the resulting manual without context of this patch, I wonder
whether this means that the other settings described above (like e.g.,
set args/environment) don't work with remote debugging.

>  
>  @kindex show cwd
>  @cindex show inferior's working directory
> @@ -20982,6 +20987,10 @@ are:
>  @tab @code{QEnvironmentReset}
>  @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
>  
> +@item @code{set-working-dir}
> +@tab @code{QSetWorkingDir}
> +@tab @code{cd}

This reference to "cd" is probably incorrect in this version and should
be "set cwd", right?

> +
>  @item @code{conditional-breakpoints-packet}
>  @tab @code{Z0 and Z1}
>  @tab @code{Support for target-side breakpoint condition evaluation}
> @@ -36770,6 +36779,30 @@ Reply:
>  @table @samp
>  @item OK
>  The request succeeded.
> +
> +@item QSetWorkingDir:@var{hex-value}
> +@anchor{QSetWorkingDir packet}
> +@cindex set working directory, remote request
> +@cindex @samp{QSetWorkingDir} packet
> +On UNIX-like targets, it is possible to set the current working
> +directory that @command{gdbserver} will enter before starting the
> +inferior.  This packet is used to inform @command{gdbserver} of a
> +directory into which it should enter during the startup process.

I don't see why this is talking about Unix-like targets in particular.
You're making it work on Windows too, right?  I don't think we should
talk in terms of gdbserver, for the matter.  I think the first sentence
could all go away.  We should instead say that this packet is used to
inform the remote server of the intended current directory for programs
that are next run.

> +
> +The packet is composed by @var{hex-value}, an hex encoded
> +representation of the directory to be entered by @command{gdbserver}.
> +
> +This packet is only transmitted when the user issues a @code{cd}
> +command in @value{GDBN} (@pxref{Working Directory, ,Your Program's
> +Working Directory}).

Reference to "cd" is stale.

> +
> +This packet is only available in extended mode (@pxref{extended
> +mode}).
> +
> +Reply:
> +@table @samp
> +@item OK
> +The request succeeded.
>  @end table
>  
>  This packet is not probed by default; the remote stub must request it,
> @@ -36800,6 +36833,9 @@ Reply:
>  @table @samp
>  @item OK
>  The request succeeded.
> +
> +@item E @var{nn}
> +An error occurred.  The error number @var{nn} is given as hex digits.
>  @end table
>  
>  This packet is not probed by default; the remote stub must request it,
> diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
> index e78ad4faf1..326d01f4d9 100644
> --- a/gdb/gdbserver/inferiors.c
> +++ b/gdb/gdbserver/inferiors.c
> @@ -456,3 +456,12 @@ get_inferior_cwd ()
>  {
>    return current_inferior_cwd;
>  }
> +
> +/* See common/common-inferior.h.  */
> +
> +void
> +set_inferior_cwd (const char *cwd)
> +{
> +  xfree ((void *) current_inferior_cwd);
> +  current_inferior_cwd = xstrdup (cwd);
> +}
> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
> index f4faff9d77..a159708632 100644
> --- a/gdb/gdbserver/server.c
> +++ b/gdb/gdbserver/server.c
> @@ -869,6 +869,21 @@ handle_general_set (char *own_buf)
>        return;
>      }
>  
> +  if (startswith (own_buf, "QSetWorkingDir:"))
> +    {
> +      const char *p = own_buf + strlen ("QSetWorkingDir:");
> +      std::string path = hex2str (p);
> +
> +      set_inferior_cwd (path.c_str ());
> +
> +      if (remote_debug)
> +	debug_printf (_("[Changed current directory to %s]\n"),
> +		      path.c_str ());
> +      write_ok (own_buf);
> +
> +      return;
> +    }
> +
>    /* Otherwise we didn't know what packet it was.  Say we didn't
>       understand it.  */
>    own_buf[0] = 0;
> @@ -2345,7 +2360,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
>        sprintf (own_buf,
>  	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
>  	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
> -	       "QEnvironmentReset+;QEnvironmentUnset+",
> +	       "QEnvironmentReset+;QEnvironmentUnset+;"
> +	       "QSetWorkingDir+",
>  	       PBUFSIZ - 1);
>  
>        if (target_supports_catch_syscall ())
> diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
> index cc84d15c2f..b9fff29d74 100644
> --- a/gdb/gdbserver/win32-low.c
> +++ b/gdb/gdbserver/win32-low.c
> @@ -562,6 +562,7 @@ static BOOL
>  create_process (const char *program, char *args,
>  		DWORD flags, PROCESS_INFORMATION *pi)
>  {
> +  const char *inferior_cwd = get_inferior_cwd ();
>    BOOL ret;
>  
>  #ifdef _WIN32_WCE
> @@ -586,7 +587,7 @@ create_process (const char *program, char *args,
>  			FALSE,    /* inherit handles, not supported */
>  			flags,    /* start flags */
>  			NULL,     /* environment, not supported */
> -			NULL,     /* current directory, not supported */
> +			inferior_cwd,     /* current directory */
>  			NULL,     /* start info, not supported */
>  			pi);      /* proc info */

This path takes a wide string, so you'd need to 
do the alloca + mbstowcs above, like done with wprogram.

>  #else
> @@ -599,7 +600,7 @@ create_process (const char *program, char *args,
>  			TRUE,     /* inherit handles */
>  			flags,    /* start flags */
>  			NULL,     /* environment */
> -			NULL,     /* current directory */
> +			inferior_cwd,     /* current directory */
>  			&si,      /* start info */
>  			pi);      /* proc info */
>  #endif
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 178a3ca15f..a51a3d4e40 100644

>  
> +/* Helper function to handle the change of the current working
> +   directory in the remote.  */
> +
> +static void
> +extended_remote_handle_inferior_cwd (struct remote_state *rs)

I'd call "set", not "handle" (ditto comments).  "handle" to me
indicates that you're handling a command that you received.  But
here we're sending the command.

> +{
> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
> +    {
> +      const char *inferior_cwd = get_inferior_cwd ();
> +
> +      if (inferior_cwd != NULL)
> +	{
> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
> +					 strlen (inferior_cwd));
> +
> +	  xsnprintf (rs->buf, get_remote_packet_size (),
> +		     "QSetWorkingDir:%s", hexpath.c_str ());
> +	  putpkt (rs->buf);
> +	  getpkt (&rs->buf, &rs->buf_size, 0);
> +	  if (strcmp (rs->buf, "OK") != 0)
> +	    error (_("\
> +Remote replied unexpectedly while changing working directory: %s"),
> +		   rs->buf);

Please use packet_ok.

> +	}
> +    }
> +}
> +
>  /* In the extended protocol we want to be able to do things like
>     "run" and have them basically work as expected.  So we need
>     a special create_inferior function.  We support changing the
> @@ -9658,6 +9688,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
>  
>    extended_remote_environment_support (rs);
>  
> +  extended_remote_handle_inferior_cwd (rs);
> +
>    /* Now restart the remote server.  */
>    run_worked = extended_remote_run (args) != -1;
>    if (!run_worked)
> @@ -14126,6 +14158,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
>  			 "QProgramSignals", "program-signals", 0);
>  
> +  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
> +			 "QSetWorkingDir", "set-working-dir", 0);
> +
>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
>  			 "QStartupWithShell", "startup-with-shell", 0);
>  
> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
> index 3a6ffd3862..d3104287a0 100644
> --- a/gdb/testsuite/gdb.base/set-cwd.exp
> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
> @@ -15,10 +15,16 @@
>  # You should have received a copy of the GNU General Public License
>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>  
> -if { ![isnative] || [is_remote target] || [is_remote host]
> -     || [target_info gdb_protocol] == "extended-remote" } then {
> -    untested "not implemented on gdbserver"
> -    return
> +if { [target_info exists gdb_protocol] } {
> +    if { [target_info gdb_protocol] == "remote" } {
> +	untested "not implemented on native-gdbserver"
> +	return
> +    }
> +
> +    load_lib gdbserver-support.exp
> +    if { [skip_gdbserver_tests] } {
> +	return
> +    }
>  }

This drops the is_remote host and target checks, but the test is
using  "$::env(HOME)", so it really can't work when
remote-host/target testing, because that is accessing HOME in the
build machine (where dejagnu runs) not of the host machine
(where gdb runs) or the target machine (where gdbserver runs):

proc test_tilde_expansion { } {
    if { [info exists ::env(HOME)] } {
	with_test_prefix "test tilde expansion" {
	    set home $::env(HOME)


I don't understand the explicit check for gdbserver in
skip_gdbserver_tests.

Seems to me that instead of that, and the "remote" check we should skip
the test if use_gdb_stub, because that's what indicates that when you
connect to a target, you're already debugging something, like with
plain remote debugging.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)"
  2017-09-20 12:24     ` Pedro Alves
@ 2017-09-20 17:02       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 17:02 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, Pedro Alves wrote:

> On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
>> Currently we have "current_directory" and "gdb_dirbuf" globals, which
>> means that we basically have two possible places to consult when we
>> want to know GDB's current working directory.
>> 
>> This is not ideal and can lead to confusion.  Moreover, the way we're
>> using "gdb_difbuf" along with "getcwd" is problematic because we
>> declare the buffer with "1024" elements hardcoded, which does not take
>> into account longer pathnames that are possible in many filesystems.
>> Using "PATH_MAX" would also not be a solution because of portability
>> problems.  Therefore, the best solution is to rely on the fact that
>> "getcwd (NULL, 0)" will "do the right thing" and return a
>> heap-allocated string containing the full path.  With the new "getcwd"
>> module from gnulib, it is now possible to do that without worrying
>> about breaking some target.
>
> s/target/host/

Fixed.

>> --- a/gdb/cli/cli-cmds.c
>> +++ b/gdb/cli/cli-cmds.c
>> @@ -382,13 +382,16 @@ pwd_command (char *args, int from_tty)
>>  {
>>    if (args)
>>      error (_("The \"pwd\" command does not take an argument: %s"), args);
>> -  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
>> +
>> +  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
>> +
>> +  if (cwd.get () == NULL)
>
> No need for get() here:
>
>   if (cwd == NULL)

Fixed.

>> diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
>> index 977b6e274d..1e4c09352f 100644
>> --- a/gdb/mi/mi-cmd-env.c
>> +++ b/gdb/mi/mi-cmd-env.c
>> @@ -73,12 +73,12 @@ mi_cmd_env_pwd (const char *command, char **argv, int argc)
>>      }
>>       
>>    /* Otherwise the mi level is 2 or higher.  */
>> -
>> -  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
>> +  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
>> +  if (cwd.get () == NULL)
>
> Ditto.

Fixed.

> Otherwise OK.
>
> Thanks,
> Pedro Alves

I'll wait until the other patches are approved to push this one, since
it depends on gnulib's getcwd.

Thanks,

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

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-20 12:17     ` Pedro Alves
@ 2017-09-20 17:17       ` Sergio Durigan Junior
  2017-09-20 17:33         ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 17:17 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, Pedro Alves wrote:

> On 09/19/2017 05:37 AM, Sergio Durigan Junior wrote:
>> [ Resending as the original e-mail got bounced because it is too long to
>>   be posted here. ]
>> 
>> The full patch can be seen here:
>> 
>>   https://git.sergiodj.net/binutils-gdb.git/commit/?h=sergiodj/set-cwd-command&id=acf35a31bac3951f81d0446564b7f910a0fee21c
>> 
>> These two modules are necessary because of the rework that will be
>> done in the "change directory" logic on GDB/gdbserver in the next
>> commits.
>> 
>> First, we will get rid of the "gdb_dirbuf" global variable and instead
>> rely on the fact that "getcwd (NULL, 0)" returns a heap-allocated
>> string with the necessary bytes to hold the full path.  
>
> Should mention that that's a GNU extension here.

Done.

>> As a side note, we no longer need to define "close" on gdb/ser-tcp.c,
>> so the patch removes that.
>> 
>> gdb/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* gnulib/aclocal.m4: Regenerate.
>> 	* gnulib/config.in: Likewise.
> ...
>
>> 	* gnulib/import/unistd-safer.h: Likewise.
>
> Please say "New file." for new files above, not Likewise->Regenerate.

There's actually a "New file." in the middle, and there's also another
"Regenerate." (and yet another "New file.") also.

But I agree that specifying what happened explicitly is better for such
long ChangeLogs.  Done.

>> 	* ser-tcp.c: Do not (re)define "close".
>> 
>
> This is:
>
> --- a/gdb/ser-tcp.c
> +++ b/gdb/ser-tcp.c
> @@ -42,7 +42,6 @@
>  #ifndef ETIMEDOUT
>  #define ETIMEDOUT WSAETIMEDOUT
>  #endif
> -#define close(fd) closesocket (fd)
>
> Are you sure that the gnulib code that makes close work
> for sockets is enabled?  I guess it will if WINDOWS_SOCKETS
> is defined, but it wasn't obvious to me whether it'll end
> up defined with the current set of modules.

One of the dependencies of "getcwd" is the "close" module, and whenever
I tried to compile this patch with mingw it would fail because of this
re-definition of close made by ser-tcp.c.  My first approach was to
#undef close before ser-tcp.c redefined it, but then I decided to just
use "close" from gnulib.  I didn't know about this WINDOWS_SOCKETS
requirement; maybe we can define it before the inclusion of <stdlib.h>?
Or maybe choose the safe side and let ser-tcp.c redefine close as
needed.

> Boy, these modules sure bring in a lot of stuff.

Yeah, "getcwd" did.

> I noticed that this is bringing in the strerror module, which was
> problematic in the past on mingw [1].  Could you please try
> cross building gdb for mingw (should be easy since Fedora has
> cross compilers handy), to confirm that it's alright now?
> It it works, we could get rid of safe_strerror in a follow up
> patch.
>
> [1] https://sourceware.org/ml/gdb-patches/2013-11/msg00597.html
> I don't recall whether that's been fixed meanwhile.

Before submitting the patch I had compiled it for mingw, and everything
worked OK.  I did it again just in case, and it's still working.  So I
believe the issue is fixed.

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

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

* Re: [PATCH v2 3/5] Introduce gdb_chdir
  2017-09-20 13:14     ` Pedro Alves
@ 2017-09-20 17:25       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 17:25 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, Pedro Alves wrote:

> On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
>> In order to be able to change the inferior's directory before its
>> execution, it is necessary to perform a tilde expansion of the
>> directory provided by the user and then chdir into the resulting dir.
>> This is what gdb_chdir does.
>> 
>> Unfortunately it is not possible to use "tilde_expand" from readline
>> because this is common code and gdbserver doesn't use readline.  For
>> that reason I decided to go with "glob" and its GNU extension,
>> GLOB_TILDE.  With the import of the "glob" module from gnulib, this is
>> a no-brainer.
>> 
>> gdb/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* Makefile.in (SFILES): Add gdb_chdir.c.
>> 	(HFILES_NO_SRCDIR): Add gdb_chdir.h.
>> 	(COMMON_OBS): Add gdb_chdir.o.
>> 	* cli/cli-cmds.c: Include "gdb_chdir.h".
>> 	(cd_command): Use "gdb_chdir" instead of "tilde_expand
>> 	plus chdir".
>> 	* common/gdb_chdir.c: New file.
>> 	* common/gdb_chdir.h: Likewise.
>> 
>> gdb/gdbserver/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* Makefile.in (SFILES): Add $(srcdir)/common/gdb_chdir.c.
>> 	(OBS): Add gdb_chdir.o.
>> ---
>>  gdb/Makefile.in           |  3 ++
>>  gdb/cli/cli-cmds.c        | 20 +++++-----
>>  gdb/common/gdb_chdir.c    | 96 +++++++++++++++++++++++++++++++++++++++++++++++
>>  gdb/common/gdb_chdir.h    | 26 +++++++++++++
>>  gdb/gdbserver/Makefile.in |  2 +
>>  5 files changed, 136 insertions(+), 11 deletions(-)
>>  create mode 100644 gdb/common/gdb_chdir.c
>>  create mode 100644 gdb/common/gdb_chdir.h
>> 
>> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
>> index 9dfc117b2f..1f093e6c0f 100644
>> --- a/gdb/Makefile.in
>> +++ b/gdb/Makefile.in
>> @@ -1245,6 +1245,7 @@ SFILES = \
>>  	common/filestuff.c \
>>  	common/format.c \
>>  	common/job-control.c \
>> +	common/gdb_chdir.c \
>>  	common/gdb_vecs.c \
>>  	common/new-op.c \
>>  	common/print-utils.c \
>> @@ -1529,6 +1530,7 @@ HFILES_NO_SRCDIR = \
>>  	common/fileio.h \
>>  	common/format.h \
>>  	common/gdb_assert.h \
>> +	common/gdb_chdir.h \
>>  	common/gdb_locale.h \
>>  	common/gdb_setjmp.h \
>>  	common/gdb_signals.h \
>> @@ -1734,6 +1736,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
>>  	frame-unwind.o \
>>  	gcore.o \
>>  	gdb_bfd.o \
>> +	gdb_chdir.o \
>>  	gdb-dlfcn.o \
>>  	gdb_obstack.o \
>>  	gdb_regex.o \
>> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
>> index 85d6d21113..653dd56a64 100644
>> --- a/gdb/cli/cli-cmds.c
>> +++ b/gdb/cli/cli-cmds.c
>> @@ -54,6 +54,8 @@
>>  #include "tui/tui.h"	/* For tui_active et.al.  */
>>  #endif
>>  
>> +#include "gdb_chdir.h"
>> +
>>  #include <fcntl.h>
>>  #include <algorithm>
>>  #include <string>
>> @@ -408,12 +410,7 @@ cd_command (char *dir, int from_tty)
>>       repeat might be useful but is more likely to be a mistake.  */
>>    dont_repeat ();
>>  
>> -  gdb::unique_xmalloc_ptr<char> dir_holder
>> -    (tilde_expand (dir != NULL ? dir : "~"));
>> -  dir = dir_holder.get ();
>> -
>> -  if (chdir (dir) < 0)
>> -    perror_with_name (dir);
>> +  gdb_chdir (dir != NULL ? dir : "~");
>>  
>>  #ifdef HAVE_DOS_BASED_FILE_SYSTEM
>>    /* There's too much mess with DOSish names like "d:", "d:.",
>> @@ -436,20 +433,21 @@ cd_command (char *dir, int from_tty)
>>  	len--;
>>      }
>>  
>> -  dir_holder.reset (savestring (dir, len));
>> -  if (IS_ABSOLUTE_PATH (dir_holder.get ()))
>> +  std::string newdir = std::string (dir, len);
>> +  const char *newdir_str = newdir.c_str ();
>> +  if (IS_ABSOLUTE_PATH (newdir_str))
>>      {
>>        xfree (current_directory);
>> -      current_directory = dir_holder.release ();
>> +      current_directory = xstrdup (newdir_str);
>
> This introduces one extra deep string dup.  One to
> construct the std::string, and another here in this xstrdup.
>
> How about simply, above:
>
>  -  dir_holder.reset (savestring (dir, len));
>  +  gdb::unique_xmalloc_ptr<char> dir_holder (savestring (dir, len))
>
>
> But more importantly, isn't there a behavior change here?
> Before, current_directory would be a copy of the the expand
> path, while after the patch, it's a copy of the input string,
> before expansion.  Right?

Wow, you're right.  I am sorry about letting this slip.  I guess I made
so many modifications to this code that in the end I forgot that "dir"
wasn't being updated to hold the expanded path anymore.  I will fix
this.

And with your review of patch #4, it is clear that we don't need
a gdb_chdir; we need a gdb_tilde_expand.  Therefore I will make the
necessary modifications to export that function instead.

>
>>      }
>>    else
>>      {
>>        if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
>> -	current_directory = concat (current_directory, dir_holder.get (),
>> +	current_directory = concat (current_directory, newdir_str,
>>  				    (char *) NULL);
>>        else
>>  	current_directory = concat (current_directory, SLASH_STRING,
>> -				    dir_holder.get (), (char *) NULL);
>> +				    newdir_str, (char *) NULL);
>>      }
>
>
>> +  /* Destroy the object and free M_GLOB.  */
>> +  ~gdb_glob ()
>> +  {
>> +    globfree (&m_glob);
>> +  }
>> +
>> +  /* Return the GL_PATHC component of M_GLOB.  */
>> +  int
>> +  pathc () const
>> +  {
>> +    return m_glob.gl_pathc;
>> +  }
>
> We've been putting type and function name in the
> same line in inline member functions.  That's the
> de facto standard in GCC as well, AFAICS.

Done.

>
>> +
>> +  /* Return the GL_PATHV component of M_GLOB.  */
>> +  char **
>> +  pathv () const
>> +  {
>> +    return m_glob.gl_pathv;
>> +  }
>
> Ditto.

Done.

>
>> +#ifndef HAVE_GDB_CHDIR_H
>> +#define HAVE_GDB_CHDIR_H
>> +
>> +/* Perform a "chdir" to DIR, doing the proper tilde expansion before.  */
>> +extern void gdb_chdir (const char *dir);
>
> Nit, I'd drop "the proper", as it doesn't see to add value.
> I.e., what's proper and what's not proper?

Done.

Thanks,

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

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-20 17:17       ` Sergio Durigan Junior
@ 2017-09-20 17:33         ` Pedro Alves
  2017-09-20 18:31           ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 17:33 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/20/2017 06:17 PM, Sergio Durigan Junior wrote:
> On Wednesday, September 20 2017, Pedro Alves wrote:

>> --- a/gdb/ser-tcp.c
>> +++ b/gdb/ser-tcp.c
>> @@ -42,7 +42,6 @@
>>  #ifndef ETIMEDOUT
>>  #define ETIMEDOUT WSAETIMEDOUT
>>  #endif
>> -#define close(fd) closesocket (fd)
>>
>> Are you sure that the gnulib code that makes close work
>> for sockets is enabled?  I guess it will if WINDOWS_SOCKETS
>> is defined, but it wasn't obvious to me whether it'll end
>> up defined with the current set of modules.
> 
> One of the dependencies of "getcwd" is the "close" module, and whenever
> I tried to compile this patch with mingw it would fail because of this
> re-definition of close made by ser-tcp.c.  My first approach was to
> #undef close before ser-tcp.c redefined it, but then I decided to just
> use "close" from gnulib.  I didn't know about this WINDOWS_SOCKETS
> requirement; maybe we can define it before the inclusion of <stdlib.h>?
> Or maybe choose the safe side and let ser-tcp.c redefine close as
> needed.

I don't know much about WINDOWS_SOCKETS either.  I just looked
at gnulib/lib/close.c, and found:

~~~
/* Override close() to call into other gnulib modules.  */

int
rpl_close (int fd)
{
#if WINDOWS_SOCKETS
  int retval = execute_all_close_hooks (close_nothrow, fd);
#else
  int retval = close_nothrow (fd);
#endif

#if REPLACE_FCHDIR
  if (retval >= 0)
    _gl_unregister_fd (fd);
#endif

  return retval;
}
~~~


and then figured out that there's a close_fd_maybe_socket
close hook implemented in lib/sockets.c.

static int
close_fd_maybe_socket (const struct fd_hook *remaining_list,
                       gl_close_fn primary,
                       int fd)
{

This is all wrapped in #ifdef WINDOWS_SOCKETS, hence the question.

It should be easy for you to determine whether WINDOWS_SOCKETS
is defined in your mingw build, and thus whether all this code
is part of the build or not.

> 
>> Boy, these modules sure bring in a lot of stuff.
> 
> Yeah, "getcwd" did.
> 
>> I noticed that this is bringing in the strerror module, which was
>> problematic in the past on mingw [1].  Could you please try
>> cross building gdb for mingw (should be easy since Fedora has
>> cross compilers handy), to confirm that it's alright now?
>> It it works, we could get rid of safe_strerror in a follow up
>> patch.
>>
>> [1] https://sourceware.org/ml/gdb-patches/2013-11/msg00597.html
>> I don't recall whether that's been fixed meanwhile.
> 
> Before submitting the patch I had compiled it for mingw, and everything
> worked OK.  I did it again just in case, and it's still working.  So I
> believe the issue is fixed.

Alright, that's great.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-20 17:33         ` Pedro Alves
@ 2017-09-20 18:31           ` Sergio Durigan Junior
  2017-09-20 20:30             ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 18:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, Pedro Alves wrote:

> On 09/20/2017 06:17 PM, Sergio Durigan Junior wrote:
>> On Wednesday, September 20 2017, Pedro Alves wrote:
>
>>> --- a/gdb/ser-tcp.c
>>> +++ b/gdb/ser-tcp.c
>>> @@ -42,7 +42,6 @@
>>>  #ifndef ETIMEDOUT
>>>  #define ETIMEDOUT WSAETIMEDOUT
>>>  #endif
>>> -#define close(fd) closesocket (fd)
>>>
>>> Are you sure that the gnulib code that makes close work
>>> for sockets is enabled?  I guess it will if WINDOWS_SOCKETS
>>> is defined, but it wasn't obvious to me whether it'll end
>>> up defined with the current set of modules.
>> 
>> One of the dependencies of "getcwd" is the "close" module, and whenever
>> I tried to compile this patch with mingw it would fail because of this
>> re-definition of close made by ser-tcp.c.  My first approach was to
>> #undef close before ser-tcp.c redefined it, but then I decided to just
>> use "close" from gnulib.  I didn't know about this WINDOWS_SOCKETS
>> requirement; maybe we can define it before the inclusion of <stdlib.h>?
>> Or maybe choose the safe side and let ser-tcp.c redefine close as
>> needed.
>
> I don't know much about WINDOWS_SOCKETS either.  I just looked
> at gnulib/lib/close.c, and found:
>
> ~~~
> /* Override close() to call into other gnulib modules.  */
>
> int
> rpl_close (int fd)
> {
> #if WINDOWS_SOCKETS
>   int retval = execute_all_close_hooks (close_nothrow, fd);
> #else
>   int retval = close_nothrow (fd);
> #endif
>
> #if REPLACE_FCHDIR
>   if (retval >= 0)
>     _gl_unregister_fd (fd);
> #endif
>
>   return retval;
> }
> ~~~
>
>
> and then figured out that there's a close_fd_maybe_socket
> close hook implemented in lib/sockets.c.
>
> static int
> close_fd_maybe_socket (const struct fd_hook *remaining_list,
>                        gl_close_fn primary,
>                        int fd)
> {
>
> This is all wrapped in #ifdef WINDOWS_SOCKETS, hence the question.
>
> It should be easy for you to determine whether WINDOWS_SOCKETS
> is defined in your mingw build, and thus whether all this code
> is part of the build or not.

I will do that and report back.  Thanks,

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

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-20 18:31           ` Sergio Durigan Junior
@ 2017-09-20 20:30             ` Sergio Durigan Junior
  2017-09-20 22:44               ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 20:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, I wrote:

> On Wednesday, September 20 2017, Pedro Alves wrote:
>
>> On 09/20/2017 06:17 PM, Sergio Durigan Junior wrote:
>>> On Wednesday, September 20 2017, Pedro Alves wrote:
>>
>>>> --- a/gdb/ser-tcp.c
>>>> +++ b/gdb/ser-tcp.c
>>>> @@ -42,7 +42,6 @@
>>>>  #ifndef ETIMEDOUT
>>>>  #define ETIMEDOUT WSAETIMEDOUT
>>>>  #endif
>>>> -#define close(fd) closesocket (fd)
>>>>
>>>> Are you sure that the gnulib code that makes close work
>>>> for sockets is enabled?  I guess it will if WINDOWS_SOCKETS
>>>> is defined, but it wasn't obvious to me whether it'll end
>>>> up defined with the current set of modules.
>>> 
>>> One of the dependencies of "getcwd" is the "close" module, and whenever
>>> I tried to compile this patch with mingw it would fail because of this
>>> re-definition of close made by ser-tcp.c.  My first approach was to
>>> #undef close before ser-tcp.c redefined it, but then I decided to just
>>> use "close" from gnulib.  I didn't know about this WINDOWS_SOCKETS
>>> requirement; maybe we can define it before the inclusion of <stdlib.h>?
>>> Or maybe choose the safe side and let ser-tcp.c redefine close as
>>> needed.
>>
>> I don't know much about WINDOWS_SOCKETS either.  I just looked
>> at gnulib/lib/close.c, and found:
>>
>> ~~~
>> /* Override close() to call into other gnulib modules.  */
>>
>> int
>> rpl_close (int fd)
>> {
>> #if WINDOWS_SOCKETS
>>   int retval = execute_all_close_hooks (close_nothrow, fd);
>> #else
>>   int retval = close_nothrow (fd);
>> #endif
>>
>> #if REPLACE_FCHDIR
>>   if (retval >= 0)
>>     _gl_unregister_fd (fd);
>> #endif
>>
>>   return retval;
>> }
>> ~~~
>>
>>
>> and then figured out that there's a close_fd_maybe_socket
>> close hook implemented in lib/sockets.c.
>>
>> static int
>> close_fd_maybe_socket (const struct fd_hook *remaining_list,
>>                        gl_close_fn primary,
>>                        int fd)
>> {
>>
>> This is all wrapped in #ifdef WINDOWS_SOCKETS, hence the question.
>>
>> It should be easy for you to determine whether WINDOWS_SOCKETS
>> is defined in your mingw build, and thus whether all this code
>> is part of the build or not.
>
> I will do that and report back.  Thanks,

WINDOWS_SOCKETS is not defined when building with the mingw compiler
from Fedora.  This means that removing that "#define" was actually not
correct, because "close" will not work as expected even with gnulib.

My proposal is to define "close" as it was being defined before, but
actually "#undef" it if it's already defined by other headers, like:

  #ifdef close
  #undef close
  #endif
  #define close(fd) closesocket (fd)

Does that work for you?

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

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-20 20:30             ` Sergio Durigan Junior
@ 2017-09-20 22:44               ` Pedro Alves
  2017-09-20 23:12                 ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 22:44 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/20/2017 09:30 PM, Sergio Durigan Junior wrote:
> On Wednesday, September 20 2017, I wrote:
> 
>> On Wednesday, September 20 2017, Pedro Alves wrote:
>>
>>> This is all wrapped in #ifdef WINDOWS_SOCKETS, hence the question.
>>>
>>> It should be easy for you to determine whether WINDOWS_SOCKETS
>>> is defined in your mingw build, and thus whether all this code
>>> is part of the build or not.
>>
>> I will do that and report back.  Thanks,
> 
> WINDOWS_SOCKETS is not defined when building with the mingw compiler
> from Fedora.  This means that removing that "#define" was actually not
> correct, because "close" will not work as expected even with gnulib.

Looks like it's defined by gnulib/m4/socketlib.m4, and seemingly
we're not pulling in that module.

> 
> My proposal is to define "close" as it was being defined before, but
> actually "#undef" it if it's already defined by other headers, like:
> 
>   #ifdef close
>   #undef close
>   #endif
>   #define close(fd) closesocket (fd)
> 
> Does that work for you?
> 

(There's no need of wrap #undef with #ifdef/#endif.  That's redundant.)

That'd #undef 'close' on all hosts, even if gnulib decides to
replace it for some reason.  E.g., REPLACE_FCHDIR
check in rpl_close (see my previous email).

How about we switch close/closesocket around:

#ifndef USE_WIN32API
# define closesocket close
#endif

And then use closesocket instead of close?

Thanks,
Pedro Alves

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

* Re: [PATCH v2 4/5] Implement "set cwd" command
  2017-09-20 14:01     ` Pedro Alves
@ 2017-09-20 23:08       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 23:08 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, Pedro Alves wrote:

> On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
>
>> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
>> index 653dd56a64..f086f10aea 100644
>> --- a/gdb/cli/cli-cmds.c
>> +++ b/gdb/cli/cli-cmds.c
>> @@ -1716,9 +1716,9 @@ The commands below can be used to select other frames by number or address."),
>>  Print working directory.  This is used for your program as well."));
>>  
>>    c = add_cmd ("cd", class_files, cd_command, _("\
>> -Set working directory to DIR for debugger and program being debugged.\n\
>> -The change does not take effect for the program being debugged\n\
>> -until the next time it is started."), &cmdlist);
>> +Set working directory to DIR for debugger.\n\
>
>
> I think it'd be nice to add a sentence here suggesting what the
> current working directory affects.

Done.  Here's the new text:

  c = add_cmd ("cd", class_files, cd_command, _("\
Set working directory to DIR for debugger.\n\
The debugger's current working directory specifies where scripts and other\n\
files that can be loaded by GDB are located.\n\
In order to change the inferior's current working directory, the recommended\n\
way is to use the \"set cwd\" command."), &cmdlist);

>> +In order to change the inferior's current working directory, the recommended\n\
>> +way is to use the \"set cwd\" command."), &cmdlist);
>>    set_cmd_completer (c, filename_completer);
>>  
>>    add_com ("echo", class_support, echo_command, _("\
>> diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
>> index 87c13009ed..515a8c0f4e 100644
>> --- a/gdb/common/common-inferior.h
>> +++ b/gdb/common/common-inferior.h
>> @@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
>>     otherwise return 0 in that case.  */
>>  extern char *get_exec_file (int err);
>>  
>> +/* Return the inferior's current working directory.  If nothing has
>> +   been set, then return NULL.  */
>> +extern const char *get_inferior_cwd ();
>> +
>>  #endif /* ! COMMON_INFERIOR_H */
>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
>> index af5fe6f46c..c513a49c26 100644
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
>>  your program.  @xref{Environment, ,Your Program's Environment}.
>>  
>>  @item The @emph{working directory.}
>> -Your program inherits its working directory from @value{GDBN}.  You can set
>> -the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
>> +You can set your program's working directory with the command
>> +@code{set cwd}.  If you do not set any working directory with this
>> +command, your program will inherit @value{GDBN}'s working directory.
>>  @xref{Working Directory, ,Your Program's Working Directory}.
>>  
>>  @item The @emph{standard input and output.}
>> @@ -2424,19 +2425,36 @@ variables to files that are only run when you sign on, such as
>>  @section Your Program's Working Directory
>>  
>>  @cindex working directory (of your program)
>> -Each time you start your program with @code{run}, it inherits its
>> -working directory from the current working directory of @value{GDBN}.
>> -The @value{GDBN} working directory is initially whatever it inherited
>> -from its parent process (typically the shell), but you can specify a new
>> -working directory in @value{GDBN} with the @code{cd} command.
>> +Each time you start your program with @code{run}, the inferior will be
>> +initialized with the current working directory specified by the
>> +@code{set cwd} command.  If no directory has been specified by this
>> +command, then the inferior will inherit @value{GDBN}'s current working
>> +directory as its working directory.
>> +
>> +You can also change @value{GDBN}'s current working directory by using
>> +the @code{cd} command.
>>  
>>  The @value{GDBN} working directory also serves as a default for the commands
>>  that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
>>  Specify Files}.
>>  
>>  @table @code
>> +@kindex set cwd
>> +@cindex change inferior's working directory
>> +@item set cwd @r{[}@var{directory}@r{]}
>> +Set the inferior's working directory to @var{directory}.  If not
>> +given, @var{directory} uses @file{'~'}.  This has no effect on
>> +@value{GDBN}'s working directory.
>
>
> I think we're missing a sentence somewhere in the manual saying that 
> this setting only takes effect the next time you start the program, 
> like it is said in "help cd" currently.

Here's what the new text looks like:

@table @code
@kindex set cwd
@cindex change inferior's working directory
@item set cwd @r{[}@var{directory}@r{]}
Set the inferior's working directory to @var{directory}.  If not
given, @var{directory} uses @file{'~'}.  This has no effect on
@value{GDBN}'s working directory.  This setting only takes effect the
next time you start the inferior.

>> +
>> +@kindex show cwd
>> +@cindex show inferior's working directory
>> +@item show cwd
>> +Show the inferior's working directory.  If no directory has been
>> +specified by @code{set cwd}, then the default inferior's working
>> +directory is the same as @value{GDBN}'s working directory.
>> +
>>  @kindex cd
>> -@cindex change working directory
>> +@cindex change @value{GDBN}'s working directory
>>  @item cd @r{[}@var{directory}@r{]}
>>  Set the @value{GDBN} working directory to @var{directory}.  If not
>>  given, @var{directory} uses @file{'~'}.
>> diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
>> index 72f0412757..e78ad4faf1 100644
>> --- a/gdb/gdbserver/inferiors.c
>> +++ b/gdb/gdbserver/inferiors.c
>> @@ -29,6 +29,9 @@ struct thread_info *current_thread;
>>  
>>  #define get_thread(inf) ((struct thread_info *)(inf))
>>  
>> +/* The current working directory used to start the inferior.  */
>> +static const char *current_inferior_cwd = NULL;
>> +
>>  void
>>  add_inferior_to_list (struct inferior_list *list,
>>  		      struct inferior_list_entry *new_inferior)
>> @@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
>>    if (!ptid_equal (ptid, minus_one_ptid))
>>      current_thread = find_thread_ptid (ptid);
>>  }
>> +
>> +/* See common/common-inferior.h.  */
>> +
>> +const char *
>> +get_inferior_cwd ()
>> +{
>> +  return current_inferior_cwd;
>> +}
>> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
>> index 25cf025426..178a3ca15f 100644
>> --- a/gdb/infcmd.c
>> +++ b/gdb/infcmd.c
>> @@ -59,6 +59,8 @@
>>  #include "top.h"
>>  #include "interps.h"
>>  #include "common/gdb_optional.h"
>> +#include "gdb_chdir.h"
>> +#include "readline/tilde.h"
>>  
>>  /* Local functions: */
>>  
>> @@ -111,6 +113,10 @@ static void run_command (char *, int);
>>  
>>  static char *inferior_args_scratch;
>>  
>> +/* Scratch area where the new cwd will be stored by 'set cwd'.  */
>> +
>> +static char *inferior_cwd_scratch;
>> +
>>  /* Scratch area where 'set inferior-tty' will store user-provided value.
>>     We'll immediate copy it into per-inferior storage.  */
>>  
>> @@ -246,6 +252,56 @@ show_args_command (struct ui_file *file, int from_tty,
>>    deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
>>  }
>>  
>> +/* Set the inferior current working directory.  This directory will be
>> +   entered by GDB before executing the inferior.  */
>
> The second sentence is talking about implementation details of Unix-like
> targets, which doesn't really belong here.

True.  I will remove it.

>> +
>> +static void
>> +set_inferior_cwd (const char *cwd)
>> +{
>> +  struct inferior *inf = current_inferior ();
>> +
>> +  gdb_assert (inf != NULL);
>> +  xfree ((void *) inf->cwd);
>> +  inf->cwd = tilde_expand (*cwd != '\0' ? cwd : "~");
>
> So the inferior owns the string?  Wouldn't it be better if
> inf->cwd were a unique_ptr?  I don't see anywhere releasing
> the cwd string when an inferior is deleted.

Right, the inferior owns the string.  And indeed, there's no place
free'ing the string when the inferior goes away.  I think the unique_ptr
idea is good, I'll implement it.

>> +
>> +/* Handle the 'show cwd' command.  */
>> +
>> +static void
>> +show_cwd_command (struct ui_file *file, int from_tty,
>> +		  struct cmd_list_element *c, const char *value)
>> +{
>> +  const char *cwd = get_inferior_cwd ();
>> +
>> +  if (cwd == NULL)
>> +    {
>> +      /* To maintain backwards compatibility, we use
>> +	 'current_directory' here, which is set by the "cd"
>> +	 command.  */
>> +      cwd = current_directory;
>> +    }
>
> This doesn't look like the right thing to show, to me.
> It'll only make sense for native debugging, not remote debugging,
> right?  I mean, when remote debugging, the inferior won't inherit
> gdb's cwd.  Right?

That's right.  Maybe a better text for when cwd == NULL would be:

  You have not set the inferior's current working directory.  The
  inferior will inherit GDB's cwd if native debugging, or gdbserver's
  cwd if remote debugging.

WDYT?

>> +
>> +  fprintf_filtered (gdb_stdout,
>> +		    _("Current working directory that will be used "
>> +		      "when starting the inferior is \"%s\".\n"), cwd);
>> +}
>> +
>>  \f
>
>> index 6d020f73c4..bcd1e54a03 100644
>> --- a/gdb/inferior.h
>> +++ b/gdb/inferior.h
>> @@ -355,6 +355,10 @@ public:
>>       should never be freed.  */
>>    char **argv = NULL;
>>  
>> +  /* The current working directory that will be used when starting
>> +     this inferior.  */
>> +  const char *cwd = NULL;
>
> See comment above in set_inferior_cwd.  Who owns this string?
> Looks like removing the inferior leaks this?
> Can this be a unique_xmalloc_ptr ?

As explained above, I'll implement it as a unique_ptr.

>
>> @@ -376,6 +377,22 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>>  	 UIs.  */
>>        close_most_fds ();
>>  
>> +      const char *cwd = get_inferior_cwd ();
>> +
>> +      if (cwd != NULL)
>> +	{
>> +	  TRY
>> +	    {
>> +	      gdb_chdir (cwd);
>> +	    }
>> +	  CATCH (ex, RETURN_MASK_ERROR)
>> +	    {
>> +	      warning ("%s", ex.message);
>> +	      _exit (0177);
>> +	    }
>> +	  END_CATCH
>> +	}
>
> This is the fork-child path, and as such we should only be calling
> async-signal-safe code.  And throwing C++ exceptions is not async-signal-safe.
> I think an easy solution is to call gdb_tilde_expand _before_ forking, and
> then call plain old chdir in the child, and then call
> trace_start_error_with_name instead of perror_with_name on failure:
>
>   if (chdir (expanded_dir.c_str ()) < 0)
>     trace_start_error_with_name (expanded_dir.c_str ());
>
> With that, I'm not sure whether gdb_chdir is still very useful
> compared to using gdb_tilde_expand + chdir in the "cd" command too.

Done.

>> +++ b/gdb/testsuite/gdb.base/set-cwd.c
>> @@ -0,0 +1,29 @@
>> +/* This testcase is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2017 Free Software Foundation, Inc.
>> +
>> +   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 <stdio.h>
>> +#include <unistd.h>
>> +
>> +int
>> +main (int argc, char *argv[])
>> +{
>> +  char dir[BUFSIZ];
>> +
>> +  getcwd (dir, BUFSIZ);
>
> Hmm, BUFSIZ came back?  :-)  Please use something like PATH_MAX
> with a fallback to 1024 or some such.

Hm, right, I forgot to remove it from the testcase.  I'll use 4096 (the
default for PATH_MAX), it should be enough.

>> +
>> +  return 0; /* break-here */
>> +}
>> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
>> new file mode 100644
>> index 0000000000..3a6ffd3862
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
>> @@ -0,0 +1,90 @@
>> +# This testcase is part of GDB, the GNU debugger.
>> +
>> +# Copyright 2017 Free Software Foundation, Inc.
>> +
>> +# 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/>.
>> +
>> +if { ![isnative] || [is_remote target] || [is_remote host]
>> +     || [target_info gdb_protocol] == "extended-remote" } then {
>> +    untested "not implemented on gdbserver"
>
> The skip on [is_remote host] surely has nothing to do with gdbserver, right?

I think I was trying to be "overzealous" here, but "[is_remote host]"
would only make sense if this test was being run on gdbserver, right?
Having said that, I don't think it's correct to check for that here.

> Please split that up to a separate untested call with a meaningful gdb.sum
> output message.  The rest of the checks don't look exactly right,
> but I'll ignore that because surely you'll be changing it in the following
> patch.

What I really want to do here is to disable this test on remote
debugging.  Sometimes I get the whole "target/host/native/remote" thing
right, sometimes I get confused about it.

Given your comment on patch #5, I guess I should be checking only for
[use_gdb_stub] and go from that.  I'll make a few tests here to see what
works for my case.

>
>> +    return
>
>
>> +}
>> +
>> +standard_testfile
>> +
>> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
>> +    return -1
>> +}
>> +
>> +# Test that tilde expansion works fine.
>> +
>> +proc test_tilde_expansion { } {
>> +    if { [info exists ::env(HOME)] } {
>> +	with_test_prefix "test tilde expansion" {
>> +	    set home $::env(HOME)
>> +
>> +	    gdb_test_no_output "set cwd ~/test" "set cwd to ~/test dir"
>> +
>> +	    gdb_test "show cwd" \
>> +		"Current working directory that will be used when starting the inferior is \"${home}/test\"\." \
>> +		"show cwd shows expanded tilde"
>> +	}
>> +    }
>> +}
>> +
>> +# Test that when we "set cwd" the inferior will be started under the
>> +# correct working directory and GDB will not be affected by this.
>> +
>> +proc test_cd_into_dir { } {
>> +    global decimal gdb_prompt
>> +
>> +    with_test_prefix "test cd into temp dir" {
>> +	gdb_test_multiple "pwd" "pwd before run" {
>> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
>> +		set gdb_cwd_before_run $expect_out(1,string)
>> +	    }
>> +	}
>
> Is the above fails, then gdb_cwd_before_run is left unset,
> and the next reference causes a TCL error.

I've added a catch-all case after the first one, which fails and returns
-1.

>> +
>> +	set tmpdir [standard_output_file ""]
>> +
>> +	gdb_test_no_output "set cwd $tmpdir" "set cwd to temp dir"
>> +
>> +	if { ![runto_main] } {
>> +	    untested "could not run to main"
>> +	    return -1
>> +	}
>> +
>> +	gdb_breakpoint [gdb_get_line_number "break-here"]
>> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>> +
>> +	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
>> +	    "inferior cwd is correctly set"
>> +
>> +	gdb_test_multiple "pwd" "pwd after run" {
>> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
>> +		set gdb_cwd_after_run $expect_out(1,string)
>> +	    }
>> +	}
>
> Likewise.

Likewise my comment above.

>
>> +
>> +	set test "GDB cwd is unchanged after running inferior"
>> +	if { [string equal $gdb_cwd_before_run $gdb_cwd_after_run] } {
>> +	    pass $test
>> +	} else {
>> +	    fail $test
>> +	}
>
> You can use gdb_assert instead of this if/else pass/fail.

Hm, good point.  Done.

Thanks,

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

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-20 22:44               ` Pedro Alves
@ 2017-09-20 23:12                 ` Sergio Durigan Junior
  2017-09-20 23:25                   ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 23:12 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, Pedro Alves wrote:

> On 09/20/2017 09:30 PM, Sergio Durigan Junior wrote:
>> On Wednesday, September 20 2017, I wrote:
>> 
>>> On Wednesday, September 20 2017, Pedro Alves wrote:
>>>
>>>> This is all wrapped in #ifdef WINDOWS_SOCKETS, hence the question.
>>>>
>>>> It should be easy for you to determine whether WINDOWS_SOCKETS
>>>> is defined in your mingw build, and thus whether all this code
>>>> is part of the build or not.
>>>
>>> I will do that and report back.  Thanks,
>> 
>> WINDOWS_SOCKETS is not defined when building with the mingw compiler
>> from Fedora.  This means that removing that "#define" was actually not
>> correct, because "close" will not work as expected even with gnulib.
>
> Looks like it's defined by gnulib/m4/socketlib.m4, and seemingly
> we're not pulling in that module.
>
>> 
>> My proposal is to define "close" as it was being defined before, but
>> actually "#undef" it if it's already defined by other headers, like:
>> 
>>   #ifdef close
>>   #undef close
>>   #endif
>>   #define close(fd) closesocket (fd)
>> 
>> Does that work for you?
>> 
>
> (There's no need of wrap #undef with #ifdef/#endif.  That's redundant.)
>
> That'd #undef 'close' on all hosts, even if gnulib decides to
> replace it for some reason.  E.g., REPLACE_FCHDIR
> check in rpl_close (see my previous email).

Not all hosts; only on hosts that define USE_WIN32API.  This would
basically make sure we stick to the current behaviour, which is to
always define "close" as "closesocket" on win32.

> How about we switch close/closesocket around:
>
> #ifndef USE_WIN32API
> # define closesocket close
> #endif
>
> And then use closesocket instead of close?

That'd work, but my preference is to use "close" everywhere because
that's the de facto way of dealing with sockets.  Only win32 hosts need
this "closesocket" thing, and I don't think it makes sense to base use
this name in our sources.

But that's my opinion; if you want, I can reverse the logic on the
define's.

Thanks,

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

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

* Re: [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-20 23:12                 ` Sergio Durigan Junior
@ 2017-09-20 23:25                   ` Pedro Alves
  0 siblings, 0 replies; 131+ messages in thread
From: Pedro Alves @ 2017-09-20 23:25 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/21/2017 12:12 AM, Sergio Durigan Junior wrote:
> On Wednesday, September 20 2017, Pedro Alves wrote:
> 
>> (There's no need of wrap #undef with #ifdef/#endif.  That's redundant.)
>>
>> That'd #undef 'close' on all hosts, even if gnulib decides to
>> replace it for some reason.  E.g., REPLACE_FCHDIR
>> check in rpl_close (see my previous email).
> 
> Not all hosts; only on hosts that define USE_WIN32API.  This would
> basically make sure we stick to the current behaviour, which is to
> always define "close" as "closesocket" on win32.

Ah, this is all wrapped in #ifdef USE_WIN32API.  Missed that,
somehow.

> 
>> How about we switch close/closesocket around:
>>
>> #ifndef USE_WIN32API
>> # define closesocket close
>> #endif
>>
>> And then use closesocket instead of close?
> 
> That'd work, but my preference is to use "close" everywhere because
> that's the de facto way of dealing with sockets.  Only win32 hosts need
> this "closesocket" thing, and I don't think it makes sense to base use
> this name in our sources.
> 
> But that's my opinion; if you want, I can reverse the logic on the
> define's.

I don't see the problem.  Imagine it as if struct serial had
been C++-ified already, making struct ser_tcp a class, and we
added a private method like this:

void
ser_tcp::closesocket ()
{
#ifdef USE_WIN32API
   ::closesocket (fd);
#else
   close (fd);
#endif
}

Then we'd be calling closesocket instead of close.  :-)

Actually, that's pretty much the existing net_close, and
we call it in several places instead of close directly
in very nearby code:

...
	    close (scb->fd);
	    goto retry;
	  }
	if (err)
	  errno = err;
	net_close (scb);
...

Eh.

But I digress...

The #undef close approach is fine with me too
since it turns out that's wrapped in #if USE_WIN32API,
and I missed it the first time.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 5/5] Extend "set cwd" to work on gdbserver
  2017-09-20 14:34     ` Pedro Alves
@ 2017-09-20 23:49       ` Sergio Durigan Junior
  2017-09-21  1:37         ` Sergio Durigan Junior
  2017-09-22 10:47         ` Pedro Alves
  0 siblings, 2 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-20 23:49 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, Pedro Alves wrote:

> On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
>> This is the "natural" extension necessary for the "set cwd" command
>> (and the whole "set the inferior's cwd" logic) to work on gdbserver.
>> 
>> The idea here is to have a new remote packet, QSetWorkingDir (name
>> adopted from LLDB's extension to the RSP, as can be seen at
>> <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
>> which sends an hex-encoded string representing the working directory
>> that gdbserver is supposed to cd into before executing the inferior.
>> The good thing is that since this feature is already implemented on
>> nat/fork-inferior.c, all gdbserver has to do is to basically implement
>> "set_inferior_cwd" and call it whenever such packet arrives.
>> 
>> Aside from that, the patch consists basically of updates to the
>> testcase (making it available on remote targets) the documentation.
>> 
>> No regressions found.
>> 
>> gdb/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* NEWS (Changes since GDB 8.0): Add entry about new
>> 	'set-cwd-on-gdbserver' feature.
>> 	(New remote packets): Add entry for QSetWorkingDir.
>> 	* common/common-inferior.h (set_inferior_cwd): New prototype.
>> 	* infcmd.c (set_inferior_cwd): Remove "static".
>> 	* remote.c: Add PACKET_QSetWorkingDir.
>> 	(remote_protocol_features) <QSetWorkingDir>: New entry for
>> 	PACKET_QSetWorkingDir.
>> 	(extended_remote_handle_inferior_cwd): New function.
>> 	(extended_remote_create_inferior): Call
>> 	"extended_remote_handle_inferior_cwd".
>> 	(_initialize_remote): Call "add_packet_config_cmd" for
>> 	QSetWorkingDir.
>> 
>> gdb/gdbserver/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* inferiors.c (set_inferior_cwd): New function.
>> 	* server.c (handle_general_set): Handle QSetWorkingDir packet.
>> 	(handle_query): Inform that QSetWorkingDir is supported.
>> 	* win32-low.c (create_process): Pass "inferior_cwd" to
>> 	CreateProcess.
>> 
>> gdb/testsuite/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* gdb.base/set-cwd.exp: Make it available on gdbserver.
>> 
>> gdb/doc/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* gdb.texinfo (Starting your Program) <The working directory.>:
>> 	Mention remote debugging.
>> 	(Working Directory) <Your Program's Working Directory>:
>> 	Likewise.
>> 	(Connecting) <Remote Packet>: Add "set-working-dir"
>> 	and "QSetWorkingDir" to the table.
>> 	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
>> 	packet.
>> ---
>>  gdb/NEWS                           | 11 ++++++++++
>>  gdb/common/common-inferior.h       |  4 ++++
>>  gdb/doc/gdb.texinfo                | 44 ++++++++++++++++++++++++++++++++++----
>>  gdb/gdbserver/inferiors.c          |  9 ++++++++
>>  gdb/gdbserver/server.c             | 18 +++++++++++++++-
>>  gdb/gdbserver/win32-low.c          |  5 +++--
>>  gdb/infcmd.c                       |  5 ++---
>>  gdb/remote.c                       | 35 ++++++++++++++++++++++++++++++
>>  gdb/testsuite/gdb.base/set-cwd.exp | 14 ++++++++----
>>  9 files changed, 131 insertions(+), 14 deletions(-)
>> 
>> diff --git a/gdb/NEWS b/gdb/NEWS
>> index 0dcfcc98af..a0f78e4c35 100644
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -39,6 +39,14 @@
>>       variables that are to be set or unset from GDB.  These variables
>>       will affect the environment to be passed to the inferior.
>>  
>> +  ** On Unix systems, GDBserver is now able to enter a directory
>> +     before starting an inferior.
>> +
>> +     This is done by using the "cd" command in GDB, which instructs it
>> +     to tell GDBserver about this directory change the next time an
>> +     inferior is run.  If you want to make GDBserver enter the
>> +     directory your GDB is currently in, you can do a "cd ." in GDB.
>
> This all looks stale to me.

Indeed, sorry about this mistake.  I will rewrite the entry as follows:

* New features in the GDB remote stub, GDBserver

  ** GDBserver is now able to enter a directory before starting an
     inferior.

     The user can set the desired working directory to be used by the
     remote inferior on GDB, using the new "set cwd" command, which
     will instruct GDB to tell GDBserver about this directory change
     the next time an inferior is run.

>> +
>>  * New remote packets
>>  
>>  QEnvironmentHexEncoded
>> @@ -56,6 +64,9 @@ QEnvironmentReset
>>  QStartupWithShell
>>    Indicates whether the inferior must be started with a shell or not.
>>  
>> +QSetWorkingDir
>> +  Tell GDBserver to enter another directory before starting the inferior.
>
> Should this really be described in terms of gdbserver entering a
> directory?  That seems like fork-child implementation detail.
> Do we really want this to affect gdbserver's current directory
> as well, maybe in future use cases, or just the inferior's cwd?

I've changed the description of the packet to:

QSetWorkingDir
  Tell GDBserver that the inferior to be started should use a specific
  working directory.

As for your other question, I assume that if we ever want to change
gdbserver's cwd the best way would be to create a different packet, so
as not to confuse with this one.

>> --- a/gdb/common/common-inferior.h
>> +++ b/gdb/common/common-inferior.h
>> @@ -34,4 +34,8 @@ extern char *get_exec_file (int err);
>>     been set, then return NULL.  */
>>  extern const char *get_inferior_cwd ();
>>  
>> +/* Set the inferior current working directory.  This directory will be
>> +   entered by the debugger before executing the inferior.  */
>> +extern void set_inferior_cwd (const char *cwd);
>
> Again described in terms of target implementation detail.

Removed the target-specific part.

>> +
>>  #endif /* ! COMMON_INFERIOR_H */
>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
>> index c513a49c26..fc20a74bce 100644
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
>>  @item The @emph{working directory.}
>>  You can set your program's working directory with the command
>>  @code{set cwd}.  If you do not set any working directory with this
>> -command, your program will inherit @value{GDBN}'s working directory.
>> -@xref{Working Directory, ,Your Program's Working Directory}.
>> +command, your program will inherit @value{GDBN}'s working directory if
>> +native debugging, or @code{gdbserver}'s working directory if remote
>> +debugging.  @xref{Working Directory, ,Your Program's Working
>> +Directory}.
>>  
>>  @item The @emph{standard input and output.}
>>  Your program normally uses the same device for standard input and
>> @@ -2429,7 +2431,9 @@ Each time you start your program with @code{run}, the inferior will be
>>  initialized with the current working directory specified by the
>>  @code{set cwd} command.  If no directory has been specified by this
>>  command, then the inferior will inherit @value{GDBN}'s current working
>> -directory as its working directory.
>> +directory as its working directory if native debugging, or it will
>> +inherit @code{gdbserver}'s current working directory if remote
>> +debugging.
>>  
>>  You can also change @value{GDBN}'s current working directory by using
>>  the @code{cd} command.
>> @@ -2444,7 +2448,8 @@ Specify Files}.
>>  @item set cwd @r{[}@var{directory}@r{]}
>>  Set the inferior's working directory to @var{directory}.  If not
>>  given, @var{directory} uses @file{'~'}.  This has no effect on
>> -@value{GDBN}'s working directory.
>> +@value{GDBN}'s working directory.  This setting works for both native
>> +and remote debugging.
>
> Not sure we should add such a sentence for a particular command alone;
> If I read the resulting manual without context of this patch, I wonder
> whether this means that the other settings described above (like e.g.,
> set args/environment) don't work with remote debugging.

Good point.  Here's what we say a little above:

  @item The @emph{working directory.}
  You can set your program's working directory with the command
  @code{set cwd}.  If you do not set any working directory with this
  command, your program will inherit @value{GDBN}'s working directory if
  native debugging, or @code{gdbserver}'s working directory if remote
  debugging.  @xref{Working Directory, ,Your Program's Working
  Directory}.

This makes it clear that the feature works for both scenarios, so I
think it's safe to just remove the sentence on "set cwd".  This is what
I'll do.

>
>>  
>>  @kindex show cwd
>>  @cindex show inferior's working directory
>> @@ -20982,6 +20987,10 @@ are:
>>  @tab @code{QEnvironmentReset}
>>  @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
>>  
>> +@item @code{set-working-dir}
>> +@tab @code{QSetWorkingDir}
>> +@tab @code{cd}
>
> This reference to "cd" is probably incorrect in this version and should
> be "set cwd", right?

Right, fixed.  Thanks.

>> +
>>  @item @code{conditional-breakpoints-packet}
>>  @tab @code{Z0 and Z1}
>>  @tab @code{Support for target-side breakpoint condition evaluation}
>> @@ -36770,6 +36779,30 @@ Reply:
>>  @table @samp
>>  @item OK
>>  The request succeeded.
>> +
>> +@item QSetWorkingDir:@var{hex-value}
>> +@anchor{QSetWorkingDir packet}
>> +@cindex set working directory, remote request
>> +@cindex @samp{QSetWorkingDir} packet
>> +On UNIX-like targets, it is possible to set the current working
>> +directory that @command{gdbserver} will enter before starting the
>> +inferior.  This packet is used to inform @command{gdbserver} of a
>> +directory into which it should enter during the startup process.
>
> I don't see why this is talking about Unix-like targets in particular.
> You're making it work on Windows too, right?  I don't think we should
> talk in terms of gdbserver, for the matter.  I think the first sentence
> could all go away.  We should instead say that this packet is used to
> inform the remote server of the intended current directory for programs
> that are next run.

Makes sense, now that you've pointed out many other places that are
referring to target-specific details.  I'll rewrite this part as:

@item QSetWorkingDir:@var{hex-value}
@anchor{QSetWorkingDir packet}
@cindex set working directory, remote request
@cindex @samp{QSetWorkingDir} packet
This packet is used to inform @command{gdbserver} of the intended
current working directory for programs that are going to be executed.


>> +
>> +The packet is composed by @var{hex-value}, an hex encoded
>> +representation of the directory to be entered by @command{gdbserver}.
>> +
>> +This packet is only transmitted when the user issues a @code{cd}
>> +command in @value{GDBN} (@pxref{Working Directory, ,Your Program's
>> +Working Directory}).
>
> Reference to "cd" is stale.

Fixed.

>> +
>> +This packet is only available in extended mode (@pxref{extended
>> +mode}).
>> +
>> +Reply:
>> +@table @samp
>> +@item OK
>> +The request succeeded.
>>  @end table
>>  
>>  This packet is not probed by default; the remote stub must request it,
>> @@ -36800,6 +36833,9 @@ Reply:
>>  @table @samp
>>  @item OK
>>  The request succeeded.
>> +
>> +@item E @var{nn}
>> +An error occurred.  The error number @var{nn} is given as hex digits.
>>  @end table
>>  
>>  This packet is not probed by default; the remote stub must request it,
>> diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
>> index e78ad4faf1..326d01f4d9 100644
>> --- a/gdb/gdbserver/inferiors.c
>> +++ b/gdb/gdbserver/inferiors.c
>> @@ -456,3 +456,12 @@ get_inferior_cwd ()
>>  {
>>    return current_inferior_cwd;
>>  }
>> +
>> +/* See common/common-inferior.h.  */
>> +
>> +void
>> +set_inferior_cwd (const char *cwd)
>> +{
>> +  xfree ((void *) current_inferior_cwd);
>> +  current_inferior_cwd = xstrdup (cwd);
>> +}
>> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
>> index f4faff9d77..a159708632 100644
>> --- a/gdb/gdbserver/server.c
>> +++ b/gdb/gdbserver/server.c
>> @@ -869,6 +869,21 @@ handle_general_set (char *own_buf)
>>        return;
>>      }
>>  
>> +  if (startswith (own_buf, "QSetWorkingDir:"))
>> +    {
>> +      const char *p = own_buf + strlen ("QSetWorkingDir:");
>> +      std::string path = hex2str (p);
>> +
>> +      set_inferior_cwd (path.c_str ());
>> +
>> +      if (remote_debug)
>> +	debug_printf (_("[Changed current directory to %s]\n"),
>> +		      path.c_str ());
>> +      write_ok (own_buf);
>> +
>> +      return;
>> +    }
>> +
>>    /* Otherwise we didn't know what packet it was.  Say we didn't
>>       understand it.  */
>>    own_buf[0] = 0;
>> @@ -2345,7 +2360,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
>>        sprintf (own_buf,
>>  	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
>>  	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
>> -	       "QEnvironmentReset+;QEnvironmentUnset+",
>> +	       "QEnvironmentReset+;QEnvironmentUnset+;"
>> +	       "QSetWorkingDir+",
>>  	       PBUFSIZ - 1);
>>  
>>        if (target_supports_catch_syscall ())
>> diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
>> index cc84d15c2f..b9fff29d74 100644
>> --- a/gdb/gdbserver/win32-low.c
>> +++ b/gdb/gdbserver/win32-low.c
>> @@ -562,6 +562,7 @@ static BOOL
>>  create_process (const char *program, char *args,
>>  		DWORD flags, PROCESS_INFORMATION *pi)
>>  {
>> +  const char *inferior_cwd = get_inferior_cwd ();
>>    BOOL ret;
>>  
>>  #ifdef _WIN32_WCE
>> @@ -586,7 +587,7 @@ create_process (const char *program, char *args,
>>  			FALSE,    /* inherit handles, not supported */
>>  			flags,    /* start flags */
>>  			NULL,     /* environment, not supported */
>> -			NULL,     /* current directory, not supported */
>> +			inferior_cwd,     /* current directory */
>>  			NULL,     /* start info, not supported */
>>  			pi);      /* proc info */
>
> This path takes a wide string, so you'd need to 
> do the alloca + mbstowcs above, like done with wprogram.

Ah, didn't know that.  Improved the code to do it.

>>  #else
>> @@ -599,7 +600,7 @@ create_process (const char *program, char *args,
>>  			TRUE,     /* inherit handles */
>>  			flags,    /* start flags */
>>  			NULL,     /* environment */
>> -			NULL,     /* current directory */
>> +			inferior_cwd,     /* current directory */
>>  			&si,      /* start info */
>>  			pi);      /* proc info */
>>  #endif
>> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
>> index 178a3ca15f..a51a3d4e40 100644
>
>>  
>> +/* Helper function to handle the change of the current working
>> +   directory in the remote.  */
>> +
>> +static void
>> +extended_remote_handle_inferior_cwd (struct remote_state *rs)
>
> I'd call "set", not "handle" (ditto comments).  "handle" to me
> indicates that you're handling a command that you received.  But
> here we're sending the command.

OK, done.

>> +{
>> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
>> +    {
>> +      const char *inferior_cwd = get_inferior_cwd ();
>> +
>> +      if (inferior_cwd != NULL)
>> +	{
>> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
>> +					 strlen (inferior_cwd));
>> +
>> +	  xsnprintf (rs->buf, get_remote_packet_size (),
>> +		     "QSetWorkingDir:%s", hexpath.c_str ());
>> +	  putpkt (rs->buf);
>> +	  getpkt (&rs->buf, &rs->buf_size, 0);
>> +	  if (strcmp (rs->buf, "OK") != 0)
>> +	    error (_("\
>> +Remote replied unexpectedly while changing working directory: %s"),
>> +		   rs->buf);
>
> Please use packet_ok.

Done.

>> +	}
>> +    }
>> +}
>> +
>>  /* In the extended protocol we want to be able to do things like
>>     "run" and have them basically work as expected.  So we need
>>     a special create_inferior function.  We support changing the
>> @@ -9658,6 +9688,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
>>  
>>    extended_remote_environment_support (rs);
>>  
>> +  extended_remote_handle_inferior_cwd (rs);
>> +
>>    /* Now restart the remote server.  */
>>    run_worked = extended_remote_run (args) != -1;
>>    if (!run_worked)
>> @@ -14126,6 +14158,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
>>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
>>  			 "QProgramSignals", "program-signals", 0);
>>  
>> +  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
>> +			 "QSetWorkingDir", "set-working-dir", 0);
>> +
>>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
>>  			 "QStartupWithShell", "startup-with-shell", 0);
>>  
>> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
>> index 3a6ffd3862..d3104287a0 100644
>> --- a/gdb/testsuite/gdb.base/set-cwd.exp
>> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
>> @@ -15,10 +15,16 @@
>>  # You should have received a copy of the GNU General Public License
>>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>  
>> -if { ![isnative] || [is_remote target] || [is_remote host]
>> -     || [target_info gdb_protocol] == "extended-remote" } then {
>> -    untested "not implemented on gdbserver"
>> -    return
>> +if { [target_info exists gdb_protocol] } {
>> +    if { [target_info gdb_protocol] == "remote" } {
>> +	untested "not implemented on native-gdbserver"
>> +	return
>> +    }
>> +
>> +    load_lib gdbserver-support.exp
>> +    if { [skip_gdbserver_tests] } {
>> +	return
>> +    }
>>  }
>
> This drops the is_remote host and target checks, but the test is
> using  "$::env(HOME)", so it really can't work when
> remote-host/target testing, because that is accessing HOME in the
> build machine (where dejagnu runs) not of the host machine
> (where gdb runs) or the target machine (where gdbserver runs):
>
> proc test_tilde_expansion { } {
>     if { [info exists ::env(HOME)] } {
> 	with_test_prefix "test tilde expansion" {
> 	    set home $::env(HOME)

OK, that makes sense, but I wasn't aware that there is a problem between
"host" and "build" machines.  This is becoming absurdly confuse to me,
sorry.

In this case, I'd have to check for ![is_remote host], is that right?

> I don't understand the explicit check for gdbserver in
> skip_gdbserver_tests.

I was thinking of the following scenario:

- The users wants to skip gdbserver tests

- He runs the test as "make check-gdb TESTS=gdb.base/set-cwd.exp"

- Because of the unconditional call to "skip_gdbserver_tests", the test
  doesn't run at all, even though the test *should* run because the user
  hasn't specified any remote board, etc.

> Seems to me that instead of that, and the "remote" check we should skip
> the test if use_gdb_stub, because that's what indicates that when you
> connect to a target, you're already debugging something, like with
> plain remote debugging.

OK, so a simple check to "[use_gdb_stub]" would suffice, you say?  That
doesn't solve the problem with calling ::env above, right?

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

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

* Re: [PATCH v2 5/5] Extend "set cwd" to work on gdbserver
  2017-09-20 23:49       ` Sergio Durigan Junior
@ 2017-09-21  1:37         ` Sergio Durigan Junior
  2017-09-22 10:47         ` Pedro Alves
  1 sibling, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-21  1:37 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 20 2017, I wrote:

> On Wednesday, September 20 2017, Pedro Alves wrote:
>
>> On 09/19/2017 05:28 AM, Sergio Durigan Junior wrote:
>>> This is the "natural" extension necessary for the "set cwd" command
>>> (and the whole "set the inferior's cwd" logic) to work on gdbserver.
>>> 
>>> The idea here is to have a new remote packet, QSetWorkingDir (name
>>> adopted from LLDB's extension to the RSP, as can be seen at
>>> <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
>>> which sends an hex-encoded string representing the working directory
>>> that gdbserver is supposed to cd into before executing the inferior.
>>> The good thing is that since this feature is already implemented on
>>> nat/fork-inferior.c, all gdbserver has to do is to basically implement
>>> "set_inferior_cwd" and call it whenever such packet arrives.
>>> 
>>> Aside from that, the patch consists basically of updates to the
>>> testcase (making it available on remote targets) the documentation.
>>> 
>>> No regressions found.
>>> 
>>> gdb/ChangeLog:
>>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>>> 
>>> 	* NEWS (Changes since GDB 8.0): Add entry about new
>>> 	'set-cwd-on-gdbserver' feature.
>>> 	(New remote packets): Add entry for QSetWorkingDir.
>>> 	* common/common-inferior.h (set_inferior_cwd): New prototype.
>>> 	* infcmd.c (set_inferior_cwd): Remove "static".
>>> 	* remote.c: Add PACKET_QSetWorkingDir.
>>> 	(remote_protocol_features) <QSetWorkingDir>: New entry for
>>> 	PACKET_QSetWorkingDir.
>>> 	(extended_remote_handle_inferior_cwd): New function.
>>> 	(extended_remote_create_inferior): Call
>>> 	"extended_remote_handle_inferior_cwd".
>>> 	(_initialize_remote): Call "add_packet_config_cmd" for
>>> 	QSetWorkingDir.
>>> 
>>> gdb/gdbserver/ChangeLog:
>>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>>> 
>>> 	* inferiors.c (set_inferior_cwd): New function.
>>> 	* server.c (handle_general_set): Handle QSetWorkingDir packet.
>>> 	(handle_query): Inform that QSetWorkingDir is supported.
>>> 	* win32-low.c (create_process): Pass "inferior_cwd" to
>>> 	CreateProcess.
>>> 
>>> gdb/testsuite/ChangeLog:
>>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>>> 
>>> 	* gdb.base/set-cwd.exp: Make it available on gdbserver.
>>> 
>>> gdb/doc/ChangeLog:
>>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>>> 
>>> 	* gdb.texinfo (Starting your Program) <The working directory.>:
>>> 	Mention remote debugging.
>>> 	(Working Directory) <Your Program's Working Directory>:
>>> 	Likewise.
>>> 	(Connecting) <Remote Packet>: Add "set-working-dir"
>>> 	and "QSetWorkingDir" to the table.
>>> 	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
>>> 	packet.
>>> ---
>>>  gdb/NEWS                           | 11 ++++++++++
>>>  gdb/common/common-inferior.h       |  4 ++++
>>>  gdb/doc/gdb.texinfo                | 44 ++++++++++++++++++++++++++++++++++----
>>>  gdb/gdbserver/inferiors.c          |  9 ++++++++
>>>  gdb/gdbserver/server.c             | 18 +++++++++++++++-
>>>  gdb/gdbserver/win32-low.c          |  5 +++--
>>>  gdb/infcmd.c                       |  5 ++---
>>>  gdb/remote.c                       | 35 ++++++++++++++++++++++++++++++
>>>  gdb/testsuite/gdb.base/set-cwd.exp | 14 ++++++++----
>>>  9 files changed, 131 insertions(+), 14 deletions(-)
>>> 
>>> diff --git a/gdb/NEWS b/gdb/NEWS
>>> index 0dcfcc98af..a0f78e4c35 100644
>>> --- a/gdb/NEWS
>>> +++ b/gdb/NEWS
>>> @@ -39,6 +39,14 @@
>>>       variables that are to be set or unset from GDB.  These variables
>>>       will affect the environment to be passed to the inferior.
>>>  
>>> +  ** On Unix systems, GDBserver is now able to enter a directory
>>> +     before starting an inferior.
>>> +
>>> +     This is done by using the "cd" command in GDB, which instructs it
>>> +     to tell GDBserver about this directory change the next time an
>>> +     inferior is run.  If you want to make GDBserver enter the
>>> +     directory your GDB is currently in, you can do a "cd ." in GDB.
>>
>> This all looks stale to me.
>
> Indeed, sorry about this mistake.  I will rewrite the entry as follows:
>
> * New features in the GDB remote stub, GDBserver
>
>   ** GDBserver is now able to enter a directory before starting an
>      inferior.
>
>      The user can set the desired working directory to be used by the
>      remote inferior on GDB, using the new "set cwd" command, which
>      will instruct GDB to tell GDBserver about this directory change
>      the next time an inferior is run.

Actually, the first sentence is still wrong.  How about:

  ** GDBserver is now able to set the inferior's current working
     directory.

     The user can set the desired working directory to be used by the
     remote inferior on GDB, using the new "set cwd" command, which
     will instruct GDB to tell GDBserver about this directory change
     the next time an inferior is run.

?

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

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

* [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)"
  2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
@ 2017-09-21 22:59   ` Sergio Durigan Junior
  2017-09-22 11:19     ` Pedro Alves
  2017-09-21 22:59   ` [PATCH v3 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-21 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

Currently we have "current_directory" and "gdb_dirbuf" globals, which
means that we basically have two possible places to consult when we
want to know GDB's current working directory.

This is not ideal and can lead to confusion.  Moreover, the way we're
using "gdb_difbuf" along with "getcwd" is problematic because we
declare the buffer with "1024" elements hardcoded, which does not take
into account longer pathnames that are possible in many filesystems.
Using "PATH_MAX" would also not be a solution because of portability
problems.  Therefore, the best solution is to rely on the fact that
"getcwd (NULL, 0)" will "do the right thing" and return a
heap-allocated string containing the full path.  With the new "getcwd"
module from gnulib, it is now possible to do that without worrying
about breaking some host.

With this patch "current_directory" is now the only place to check for
GDB's cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* cli/cli-cmds.c (pwd_command): Use "getcwd (NULL, 0)".
	(cd_command): Likewise.  Free "current_directory" before
	assigning to it.
	* main.c (captured_main_1): Use "getcwd (NULL, 0)".
	* mi/mi-cmd-env.c (mi_cmd_env_pwd): Likewise.
	* top.c (gdb_dirbuf): Remove global declaration.
	* top.h (gdb_dirbuf): Likewise.
---
 gdb/cli/cli-cmds.c  | 17 ++++++++++++-----
 gdb/main.c          |  5 ++---
 gdb/mi/mi-cmd-env.c |  8 ++++----
 gdb/top.c           |  3 ---
 gdb/top.h           |  1 -
 5 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 260fd3f635..cbafb13837 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -384,13 +384,16 @@ pwd_command (char *args, int from_tty)
 {
   if (args)
     error (_("The \"pwd\" command does not take an argument: %s"), args);
-  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+
+  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+
+  if (cwd == NULL)
     error (_("Error finding name of working directory: %s"),
            safe_strerror (errno));
 
-  if (strcmp (gdb_dirbuf, current_directory) != 0)
+  if (strcmp (cwd.get (), current_directory) != 0)
     printf_unfiltered (_("Working directory %s\n (canonically %s).\n"),
-		       current_directory, gdb_dirbuf);
+		       current_directory, cwd.get ());
   else
     printf_unfiltered (_("Working directory %s.\n"), current_directory);
 }
@@ -418,7 +421,8 @@ cd_command (char *dir, int from_tty)
   /* There's too much mess with DOSish names like "d:", "d:.",
      "d:./foo" etc.  Instead of having lots of special #ifdef'ed code,
      simply get the canonicalized name of the current directory.  */
-  dir = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
+  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+  dir = cwd.get ();
 #endif
 
   len = strlen (dir);
@@ -436,7 +440,10 @@ cd_command (char *dir, int from_tty)
 
   dir_holder.reset (savestring (dir, len));
   if (IS_ABSOLUTE_PATH (dir_holder.get ()))
-    current_directory = dir_holder.release ();
+    {
+      xfree (current_directory);
+      current_directory = dir_holder.release ();
+    }
   else
     {
       if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
diff --git a/gdb/main.c b/gdb/main.c
index fe80511243..66ba75ba21 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -549,11 +549,10 @@ captured_main_1 (struct captured_main_args *context)
     (xstrprintf ("%s: warning: ", gdb_program_name));
   warning_pre_print = tmp_warn_preprint.get ();
 
-  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+  current_directory = getcwd (NULL, 0);
+  if (current_directory == NULL)
     perror_warning_with_name (_("error finding working directory"));
 
-  current_directory = gdb_dirbuf;
-
   /* Set the sysroot path.  */
   gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT,
 					TARGET_SYSTEM_ROOT_RELOCATABLE);
diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
index 977b6e274d..db87ead33d 100644
--- a/gdb/mi/mi-cmd-env.c
+++ b/gdb/mi/mi-cmd-env.c
@@ -73,12 +73,12 @@ mi_cmd_env_pwd (const char *command, char **argv, int argc)
     }
      
   /* Otherwise the mi level is 2 or higher.  */
-
-  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+  if (cwd == NULL)
     error (_("-environment-pwd: error finding name of working directory: %s"),
            safe_strerror (errno));
-    
-  uiout->field_string ("cwd", gdb_dirbuf);
+
+  uiout->field_string ("cwd", cwd.get ());
 }
 
 /* Change working directory.  */
diff --git a/gdb/top.c b/gdb/top.c
index 404e096755..c89e78f243 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -133,9 +133,6 @@ show_confirm (struct ui_file *file, int from_tty,
 
 char *current_directory;
 
-/* The directory name is actually stored here (usually).  */
-char gdb_dirbuf[1024];
-
 /* The last command line executed on the console.  Used for command
    repetitions.  */
 char *saved_command_line;
diff --git a/gdb/top.h b/gdb/top.h
index 45798897f6..6b66083995 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -219,7 +219,6 @@ extern void ui_unregister_input_event_handler (struct ui *ui);
 /* From top.c.  */
 extern char *saved_command_line;
 extern int confirm;
-extern char gdb_dirbuf[1024];
 extern int inhibit_gdbinit;
 extern const char gdbinit[];
 
-- 
2.13.3

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

* [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
                     ` (2 preceding siblings ...)
  2017-09-21 22:59   ` [PATCH v3 3/5] Introduce gdb_tilde_expand Sergio Durigan Junior
@ 2017-09-21 22:59   ` Sergio Durigan Junior
  2017-09-22  8:03     ` Eli Zaretskii
  2017-09-21 23:06   ` [PATCH v3 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-21 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This is the actual implementation of the "set/show cwd" commands on
GDB.  The way they work is:

- If the user sets the inferior's cwd by using "set cwd", then this
  directory is saved into current_inferior ()->cwd and is used when
  the inferior is started (see below).

- If the user doesn't set the inferior's cwd by using "set cwd", but
  rather use the "cd" command as before, then this directory is
  inherited by the inferior because GDB will have chdir'd into it.

On Unix-like hosts, the way the directory is changed before the
inferior execution is by expanding the user set directory before the
fork, and then "chdir" after the call to fork/vfork on
"fork_inferior", but before the actual execution.  On Windows, the
inferior cwd set by the user is passed directly to the CreateProcess
call, which takes care of the actual chdir for us.

This way, we'll make sure that GDB's cwd is not affected by the user
set cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (New commands): Mention "set/show cwd".
	* cli/cli-cmds.c (_initialize_cli_cmds): Mention "set cwd" on
	"cd" command's help text.
	* common/common-inferior.h (get_inferior_cwd): New prototype.
	* infcmd.c (inferior_cwd_scratch): New global variable.
	(set_inferior_cwd): New function.
	(get_inferior_cwd): Likewise.
	(set_cwd_command): Likewise.
	(show_cwd_command): Likewise.
	(_initialize_infcmd): Add "set/show cwd" commands.
	* inferior.h (class inferior) <cwd>: New field.
	* nat/fork-inferior.c: Include "gdb_tilde_expand.h".
	(fork_inferior): Change inferior's cwd before its execution.
	* windows-nat.c (windows_create_inferior): Pass inferior's cwd
	to CreateProcess.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (current_inferior_cwd): New global variable.
	(get_inferior_cwd): New function.
	* inferiors.h (struct process_info) <cwd>: New field.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention new "set cwd" command.
	(Working Directory) <Your Program's Working Directory>:
	Rephrase to explain that "set cwd" exists and is the default
	way to change the inferior's cwd.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.c: New file.
	* gdb.base/set-cwd.exp: Likewise.
---
 gdb/NEWS                           |   3 +
 gdb/cli/cli-cmds.c                 |   8 ++-
 gdb/common/common-inferior.h       |   4 ++
 gdb/doc/gdb.texinfo                |  35 +++++++---
 gdb/gdbserver/inferiors.c          |  11 +++
 gdb/infcmd.c                       |  72 +++++++++++++++++++
 gdb/inferior.h                     |   4 ++
 gdb/nat/fork-inferior.c            |  18 +++++
 gdb/testsuite/gdb.base/set-cwd.c   |  32 +++++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 140 +++++++++++++++++++++++++++++++++++++
 gdb/windows-nat.c                  |  13 +++-
 11 files changed, 327 insertions(+), 13 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.c
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 549f511b29..c131713293 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -64,6 +64,9 @@ QStartupWithShell
 
 * New commands
 
+set|show cwd
+  Set and show the current working directory for the inferior.
+
 set|show compile-gcc
   Set and show compilation command used for compiling and injecting code
   with the 'compile' commands.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 507fdc4120..14e6a06d68 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1731,9 +1731,11 @@ The commands below can be used to select other frames by number or address."),
 Print working directory.  This is used for your program as well."));
 
   c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+The debugger's current working directory specifies where scripts and other\n\
+files that can be loaded by GDB are located.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_com ("echo", class_support, echo_command, _("\
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 87c13009ed..515a8c0f4e 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
    otherwise return 0 in that case.  */
 extern char *get_exec_file (int err);
 
+/* Return the inferior's current working directory.  If nothing has
+   been set, then return NULL.  */
+extern const char *get_inferior_cwd ();
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6b320891ad..899afb92b6 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
 your program.  @xref{Environment, ,Your Program's Environment}.
 
 @item The @emph{working directory.}
-Your program inherits its working directory from @value{GDBN}.  You can set
-the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+You can set your program's working directory with the command
+@code{set cwd}.  If you do not set any working directory with this
+command, your program will inherit @value{GDBN}'s working directory.
 @xref{Working Directory, ,Your Program's Working Directory}.
 
 @item The @emph{standard input and output.}
@@ -2434,19 +2435,37 @@ variables to files that are only run when you sign on, such as
 @section Your Program's Working Directory
 
 @cindex working directory (of your program)
-Each time you start your program with @code{run}, it inherits its
-working directory from the current working directory of @value{GDBN}.
-The @value{GDBN} working directory is initially whatever it inherited
-from its parent process (typically the shell), but you can specify a new
-working directory in @value{GDBN} with the @code{cd} command.
+Each time you start your program with @code{run}, the inferior will be
+initialized with the current working directory specified by the
+@code{set cwd} command.  If no directory has been specified by this
+command, then the inferior will inherit @value{GDBN}'s current working
+directory as its working directory.
+
+You can also change @value{GDBN}'s current working directory by using
+the @code{cd} command.
 
 The @value{GDBN} working directory also serves as a default for the commands
 that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
 Specify Files}.
 
 @table @code
+@kindex set cwd
+@cindex change inferior's working directory
+@item set cwd @r{[}@var{directory}@r{]}
+Set the inferior's working directory to @var{directory}.  If not
+given, @var{directory} uses @file{'~'}.  This has no effect on
+@value{GDBN}'s working directory.  This setting only takes effect the
+next time you start the inferior.
+
+@kindex show cwd
+@cindex show inferior's working directory
+@item show cwd
+Show the inferior's working directory.  If no directory has been
+specified by @code{set cwd}, then the default inferior's working
+directory is the same as @value{GDBN}'s working directory.
+
 @kindex cd
-@cindex change working directory
+@cindex change @value{GDBN}'s working directory
 @item cd @r{[}@var{directory}@r{]}
 Set the @value{GDBN} working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 72f0412757..e78ad4faf1 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -29,6 +29,9 @@ struct thread_info *current_thread;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
 
+/* The current working directory used to start the inferior.  */
+static const char *current_inferior_cwd = NULL;
+
 void
 add_inferior_to_list (struct inferior_list *list,
 		      struct inferior_list_entry *new_inferior)
@@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
   if (!ptid_equal (ptid, minus_one_ptid))
     current_thread = find_thread_ptid (ptid);
 }
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior_cwd;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 9c0cead434..4c5bbfdbf2 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -111,6 +111,10 @@ static void run_command (char *, int);
 
 static char *inferior_args_scratch;
 
+/* Scratch area where the new cwd will be stored by 'set cwd'.  */
+
+static char *inferior_cwd_scratch;
+
 /* Scratch area where 'set inferior-tty' will store user-provided value.
    We'll immediate copy it into per-inferior storage.  */
 
@@ -246,6 +250,55 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
+/* Set the inferior current working directory.  */
+
+static void
+set_inferior_cwd (const char *cwd)
+{
+  if (*cwd == '\0')
+    error (_("You must specify a directory."));
+
+  struct inferior *inf = current_inferior ();
+
+  gdb_assert (inf != NULL);
+  inf->cwd.reset (xstrdup (cwd));
+}
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior ()->cwd.get ();
+}
+
+/* Handle the 'set cwd' command.  */
+
+static void
+set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+{
+  set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command.  */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  const char *cwd = get_inferior_cwd ();
+
+  if (cwd == NULL)
+    fprintf_filtered (gdb_stdout,
+		      _("\
+You have not set the inferior's current working directory.\n\
+The inferior will inherit GDB's cwd.\n"));
+  else
+    fprintf_filtered (gdb_stdout,
+		      _("Current working directory that will be used "
+			"when starting the inferior is \"%s\".\n"), cwd);
+}
+
 \f
 /* Compute command-line string given argument vector.  This does the
    same shell processing as fork_inferior.  */
@@ -3262,6 +3315,25 @@ Follow this command with any number of args, to be passed to the program."),
   gdb_assert (c != NULL);
   set_cmd_completer (c, filename_completer);
 
+  cmd_name = "cwd";
+  add_setshow_string_noescape_cmd (cmd_name, class_run,
+				   &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+				   _("\
+Show the current working directory that is used when the inferior is started."),
+				   _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started.  This setting does not affect GDB's current\n\
+working directory."),
+				   set_cwd_command,
+				   show_cwd_command,
+				   &setlist, &showlist);
+  c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+  gdb_assert (c != NULL);
+  set_cmd_completer (c, filename_completer);
+
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
 With an argument VAR, prints the value of environment variable VAR to\n\
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 7f2d53e5b3..498d74706a 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -355,6 +355,10 @@ public:
      should never be freed.  */
   char **argv = NULL;
 
+  /* The current working directory that will be used when starting
+     this inferior.  */
+  gdb::unique_xmalloc_ptr<char> cwd;
+
   /* The name of terminal device to use for I/O.  */
   char *terminal = NULL;
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 6ff119768c..0ce442f162 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -25,6 +25,7 @@
 #include "common-inferior.h"
 #include "common-gdbthread.h"
 #include "signals-state-save-restore.h"
+#include "gdb_tilde_expand.h"
 #include <vector>
 
 extern char **environ;
@@ -298,6 +299,8 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
   char **save_our_env;
   int i;
   int save_errno;
+  const char *inferior_cwd;
+  std::string expanded_inferior_cwd;
 
   /* If no exec file handed to us, get it from the exec-file command
      -- with a good, common error message if none is specified.  */
@@ -339,6 +342,13 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
      the parent and child flushing the same data after the fork.  */
   gdb_flush_out_err ();
 
+  /* Check if the user wants to set a different working directory for
+     the inferior.  */
+  inferior_cwd = get_inferior_cwd ();
+
+  if (inferior_cwd != NULL)
+    expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
+
   /* If there's any initialization of the target layers that must
      happen to prepare to handle the child we're about fork, do it
      now...  */
@@ -374,6 +384,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
 	 UIs.  */
       close_most_fds ();
 
+      /* Change to the requested working directory if the user
+	 requested it.  */
+      if (inferior_cwd != NULL)
+	{
+	  if (chdir (expanded_inferior_cwd.c_str ()) < 0)
+	    trace_start_error_with_name (expanded_inferior_cwd.c_str ());
+	}
+
       if (debug_fork)
 	sleep (debug_fork);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.c b/gdb/testsuite/gdb.base/set-cwd.c
new file mode 100644
index 0000000000..2a501aa675
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.c
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 Free Software Foundation, Inc.
+
+   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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char dir[4096];
+
+int
+main (int argc, char *argv[])
+{
+  const char *home = getenv ("HOME");
+
+  getcwd (dir, 4096);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
new file mode 100644
index 0000000000..f2700ec44d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -0,0 +1,140 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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/>.
+
+if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
+    untested "not implemented on gdbserver"
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    return -1
+}
+
+# Test that tilde expansion works fine.
+
+proc test_tilde_expansion { } {
+    global decimal gdb_prompt hex
+
+    with_test_prefix "test tilde expansion" {
+	gdb_test_no_output "set cwd ~/" "set cwd to ~/ dir"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test_multiple "print home" "print home var" {
+	    -re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
+		set home $expect_out(1,string)
+	    }
+	    -re "$gdb_prompt $" {
+		untested "could to retrieve home var"
+		return
+	    }
+	    default {
+		untested "could to retrieve home var"
+		return
+	    }
+	}
+
+	if { [string length $home] > 0 } {
+	    gdb_test_multiple "print dir" "print dir var" {
+		-re "\\\$$decimal = \"\(.+\)\"\(, .*repeats.*\)?\r\n$gdb_prompt $" {
+		    set curdir $expect_out(1,string)
+		}
+		-re "$gdb_prompt $" {
+		    fail "failed to retrieve dir var"
+		    return -1
+		}
+		default {
+		    fail "failed to retrieve dir var"
+		    return -1
+		}
+	    }
+
+	    gdb_assert [string equal $curdir $home] \
+		"successfully chdir'd into home"
+	} else {
+	    untested "could not determine value of HOME"
+	    return
+	}
+    }
+}
+
+# Test that when we "set cwd" the inferior will be started under the
+# correct working directory and GDB will not be affected by this.
+
+proc test_cd_into_dir { } {
+    global decimal gdb_prompt
+
+    with_test_prefix "test cd into temp dir" {
+	gdb_test_multiple "pwd" "pwd before run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_before_run $expect_out(1,string)
+	    }
+	    -re ".*$gdb_prompt $" {
+		fail "failed to obtain cwd before run"
+		return -1
+	    }
+	    default {
+		fail "failed to obtain cwd before run"
+		return -1
+	    }
+	}
+
+	set tmpdir [standard_output_file ""]
+
+	gdb_test_no_output "set cwd $tmpdir" "set cwd to temp dir"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	    "inferior cwd is correctly set"
+
+	gdb_test_multiple "pwd" "pwd after run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_after_run $expect_out(1,string)
+	    }
+	    -re ".*$gdb_prompt $" {
+		fail "failed to obtain cwd after run"
+		return -1
+	    }
+	    default {
+		fail "failed to obtain cwd after run"
+		return -1
+	    }
+	}
+
+	gdb_assert [string equal $gdb_cwd_before_run $gdb_cwd_after_run] \
+	    "GDB cwd is unchanged after running inferior"
+    }
+}
+
+test_cd_into_dir
+clean_restart $binfile
+test_tilde_expansion
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 3e1894410d..c762222654 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2432,6 +2432,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   cygwin_buf_t *toexec;
   cygwin_buf_t *cygallargs;
   cygwin_buf_t *args;
+  cygwin_buf_t *infcwd;
   char **old_env = NULL;
   PWCHAR w32_env;
   size_t len;
@@ -2461,6 +2462,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   BOOL ret;
   DWORD flags = 0;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
+  const char *inferior_cwd = get_inferior_cwd ();
 
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
@@ -2488,8 +2490,15 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 	error (_("Error starting executable: %d"), errno);
       cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
       mbstowcs (cygallargs, allargs, len);
+
+      len = mbstowcs (NULL, inferior_cwd, 0) + 1;
+      if (len == (size_t) -1)
+	error (_("Invalid cwd for inferior: %d"), errno);
+      infcwd = (wchar_t *) alloca (len * sizeof (wchar_t));
+      mbstowcs (infcwd, inferior_cwd, len);
 #else  /* !__USEWIDE */
       cygallargs = allargs;
+      infcwd = (cygwin_buf_t *) inferior_cwd;
 #endif
     }
   else
@@ -2574,7 +2583,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 		       TRUE,	/* inherit handles */
 		       flags,	/* start flags */
 		       w32_env,	/* environment */
-		       NULL,	/* current directory */
+		       infcwd,	/* current directory */
 		       &si,
 		       &pi);
   if (w32_env)
@@ -2697,7 +2706,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 			TRUE,	/* inherit handles */
 			flags,	/* start flags */
 			w32env,	/* environment */
-			NULL,	/* current directory */
+			inferior_cwd,	/* current directory */
 			&si,
 			&pi);
   if (tty != INVALID_HANDLE_VALUE)
-- 
2.13.3

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

* [PATCH v3 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
  2017-09-21 22:59   ` [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
@ 2017-09-21 22:59   ` Sergio Durigan Junior
  2017-09-22 11:01     ` Pedro Alves
  2017-09-21 22:59   ` [PATCH v3 3/5] Introduce gdb_tilde_expand Sergio Durigan Junior
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-21 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This patch is too long to send to the mailing list, so I'm making it
available here:

  https://git.sergiodj.net/binutils-gdb.git/commit/?h=sergiodj/set-cwd-command&id=ba0db8beb2ee1f75aa923338639c8185afc92fe5

These two modules are necessary because of the rework that will be
done in the "change directory" logic on GDB/gdbserver in the next
commits.

First, we will get rid of the "gdb_dirbuf" global variable and instead
rely on the fact that "getcwd (NULL, 0)", which is a GNU extension,
returns a heap-allocated string with the necessary bytes to hold the
full path.  This is a good practice not only because globals are not
ideal but also because there is no good way to know beforehand the
size of the full pathname allowed in the filesystem ("PATH_MAX" is not
portable and does not reflect all the possible filesystems out there).

We will also have a way to "cd" to a directory also on gdbserver, but
in order to do that uniformly, there must be a way to do tilde
expansion on directories provided by the user.  Currently, GDB uses
"tilde_expand" from readline to do that, but gdbserver doesn't link
against readline and therefore cannot use this function.  The solution
is to use "glob" instead, which can perform tilde expansion as a GNU
extension.  Therefore, we need gnulib's version of "glob".

A special note is necessary for gdb/ser-tcp.c.  It defines "close" as
"closesocket" on Win32 targets.  If we leave the code as is, this
would conflict with gnulib's definition of "close".  Therefore, in
order to keep the same code path from before this import, I decided to
"#undef close" first, and then let the original (re)definition of it
take place.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gnulib/aclocal.m4: Regenerate.
	* gnulib/config.in: Regenerate.
	* gnulib/configure: Regenerate.
	* gnulib/import/Makefile.am: Regenerate.
	* gnulib/import/Makefile.in: Regenerate.
	* gnulib/import/assure.h: New file.
	* gnulib/import/at-func.c: Likewise
	* gnulib/import/chdir-long.c: New file.
	* gnulib/import/chdir-long.h: New file.
	* gnulib/import/cloexec.c: New file.
	* gnulib/import/cloexec.h: New file.
	* gnulib/import/close.c: New file.
	* gnulib/import/closedir.c: New file.
	* gnulib/import/dirent-private.h: New file.
	* gnulib/import/dup-safer.c: New file.
	* gnulib/import/dup.c: New file.
	* gnulib/import/dup2.c: New file.
	* gnulib/import/error.c: New file.
	* gnulib/import/error.h: New file.
	* gnulib/import/exitfail.c: New file.
	* gnulib/import/exitfail.h: New file.
	* gnulib/import/fchdir.c: New file.
	* gnulib/import/fcntl.c: New file.
	* gnulib/import/fcntl.in.h: New file.
	* gnulib/import/fd-hook.c: New file.
	* gnulib/import/fd-hook.h: New file.
	* gnulib/import/fd-safer.c: New file.
	* gnulib/import/fdopendir.c: New file.
	* gnulib/import/filename.h: New file.
	* gnulib/import/filenamecat-lgpl.c: New file.
	* gnulib/import/filenamecat.h: New file.
	* gnulib/import/fstat.c: New file.
	* gnulib/import/fstatat.c: New file.
	* gnulib/import/getcwd-lgpl.c: New file.
	* gnulib/import/getcwd.c: New file.
	* gnulib/import/getdtablesize.c: New file.
	* gnulib/import/getlogin_r.c: New file.
	* gnulib/import/getprogname.c: New file.
	* gnulib/import/getprogname.h: New file.
	* gnulib/import/gettext.h: New file.
	* gnulib/import/glob-libc.h: New file.
	* gnulib/import/glob.c: New file.
	* gnulib/import/glob.in.h: New file.
	* gnulib/import/intprops.h: New file.
	* gnulib/import/m4/chdir-long.m4: New file.
	* gnulib/import/m4/close.m4: New file.
	* gnulib/import/m4/closedir.m4: New file.
	* gnulib/import/m4/d-ino.m4: New file.
	* gnulib/import/m4/d-type.m4: New file.
	* gnulib/import/m4/dup.m4: New file.
	* gnulib/import/m4/dup2.m4: New file.
	* gnulib/import/m4/error.m4: New file.
	* gnulib/import/m4/fchdir.m4: New file.
	* gnulib/import/m4/fcntl.m4: New file.
	* gnulib/import/m4/fcntl_h.m4: New file.
	* gnulib/import/m4/fdopendir.m4: New file.
	* gnulib/import/m4/filenamecat.m4: New file.
	* gnulib/import/m4/fstat.m4: New file.
	* gnulib/import/m4/fstatat.m4: New file.
	* gnulib/import/m4/getcwd-abort-bug.m4: New file.
	* gnulib/import/m4/getcwd-path-max.m4: New file.
	* gnulib/import/m4/getcwd.m4: New file.
	* gnulib/import/m4/getdtablesize.m4: New file.
	* gnulib/import/m4/getlogin_r.m4: New file.
	* gnulib/import/m4/getprogname.m4: New file.
	* gnulib/import/m4/glob.m4: New file.
	* gnulib/import/m4/gnulib-cache.m4: Regenerate
	* gnulib/import/m4/gnulib-comp.m4: Regenerate.
	* gnulib/import/m4/mempcpy.m4: New file.
	* gnulib/import/m4/memrchr.m4: New file.
	* gnulib/import/m4/mode_t.m4: New file.
	* gnulib/import/m4/msvc-inval.m4: New file.
	* gnulib/import/m4/msvc-nothrow.m4: New file.
	* gnulib/import/m4/open.m4: New file.
	* gnulib/import/m4/openat.m4: New file.
	* gnulib/import/m4/opendir.m4: New file.
	* gnulib/import/m4/readdir.m4: New file.
	* gnulib/import/m4/realloc.m4: New file.
	* gnulib/import/m4/rewinddir.m4: New file.
	* gnulib/import/m4/save-cwd.m4: New file.
	* gnulib/import/m4/strdup.m4: New file.
	* gnulib/import/m4/strerror.m4: New file.
	* gnulib/import/m4/unistd-safer.m4: New file.
	* gnulib/import/mempcpy.c: New file.
	* gnulib/import/memrchr.c: New file.
	* gnulib/import/msvc-inval.c: New file.
	* gnulib/import/msvc-inval.h: New file.
	* gnulib/import/msvc-nothrow.c: New file.
	* gnulib/import/msvc-nothrow.h: New file.
	* gnulib/import/open.c: New file.
	* gnulib/import/openat-die.c: New file.
	* gnulib/import/openat-priv.h: New file.
	* gnulib/import/openat-proc.c: New file.
	* gnulib/import/openat.c: New file.
	* gnulib/import/openat.h: New file.
	* gnulib/import/opendir.c: New file.
	* gnulib/import/pipe-safer.c: New file.
	* gnulib/import/readdir.c: New file.
	* gnulib/import/realloc.c: New file.
	* gnulib/import/rewinddir.c: New file.
	* gnulib/import/save-cwd.c: New file.
	* gnulib/import/save-cwd.h: New file.
	* gnulib/import/strdup.c: New file.
	* gnulib/import/strerror-override.c: New file.
	* gnulib/import/strerror-override.h: New file.
	* gnulib/import/strerror.c: New file.
	* gnulib/import/unistd--.h: New file.
	* gnulib/import/unistd-safer.h: New file.
	* gnulib/update-gnulib.sh (IMPORTED_GNULIB_MODULES): Add
	"getcwd" and "glob".
	* ser-tcp.c: Undefine "close" before redefining it.
---
 gdb/gnulib/aclocal.m4                    |    37 +
 gdb/gnulib/config.in                     |   267 +
 gdb/gnulib/configure                     | 12423 +++++++++++++++++++----------
 gdb/gnulib/import/Makefile.am            |   421 +-
 gdb/gnulib/import/Makefile.in            |   236 +-
 gdb/gnulib/import/assure.h               |    37 +
 gdb/gnulib/import/at-func.c              |   146 +
 gdb/gnulib/import/chdir-long.c           |   264 +
 gdb/gnulib/import/chdir-long.h           |    30 +
 gdb/gnulib/import/cloexec.c              |    83 +
 gdb/gnulib/import/cloexec.h              |    38 +
 gdb/gnulib/import/close.c                |    69 +
 gdb/gnulib/import/closedir.c             |    71 +
 gdb/gnulib/import/dirent-private.h       |    40 +
 gdb/gnulib/import/dup-safer.c            |    34 +
 gdb/gnulib/import/dup.c                  |    86 +
 gdb/gnulib/import/dup2.c                 |   215 +
 gdb/gnulib/import/error.c                |   406 +
 gdb/gnulib/import/error.h                |    75 +
 gdb/gnulib/import/exitfail.c             |    24 +
 gdb/gnulib/import/exitfail.h             |    18 +
 gdb/gnulib/import/fchdir.c               |   208 +
 gdb/gnulib/import/fcntl.c                |   414 +
 gdb/gnulib/import/fcntl.in.h             |   363 +
 gdb/gnulib/import/fd-hook.c              |   116 +
 gdb/gnulib/import/fd-hook.h              |   119 +
 gdb/gnulib/import/fd-safer.c             |    49 +
 gdb/gnulib/import/fdopendir.c            |   249 +
 gdb/gnulib/import/filename.h             |    54 +
 gdb/gnulib/import/filenamecat-lgpl.c     |    88 +
 gdb/gnulib/import/filenamecat.h          |    27 +
 gdb/gnulib/import/fstat.c                |    88 +
 gdb/gnulib/import/fstatat.c              |   135 +
 gdb/gnulib/import/getcwd-lgpl.c          |   126 +
 gdb/gnulib/import/getcwd.c               |   446 ++
 gdb/gnulib/import/getdtablesize.c        |   121 +
 gdb/gnulib/import/getlogin_r.c           |    87 +
 gdb/gnulib/import/getprogname.c          |   151 +
 gdb/gnulib/import/getprogname.h          |    40 +
 gdb/gnulib/import/gettext.h              |   292 +
 gdb/gnulib/import/glob-libc.h            |   212 +
 gdb/gnulib/import/glob.c                 |  1808 +++++
 gdb/gnulib/import/glob.in.h              |    93 +
 gdb/gnulib/import/intprops.h             |   464 ++
 gdb/gnulib/import/m4/chdir-long.m4       |    30 +
 gdb/gnulib/import/m4/close.m4            |    33 +
 gdb/gnulib/import/m4/closedir.m4         |    30 +
 gdb/gnulib/import/m4/d-ino.m4            |    56 +
 gdb/gnulib/import/m4/d-type.m4           |    32 +
 gdb/gnulib/import/m4/dup.m4              |    45 +
 gdb/gnulib/import/m4/dup2.m4             |   117 +
 gdb/gnulib/import/m4/error.m4            |    27 +
 gdb/gnulib/import/m4/fchdir.m4           |    61 +
 gdb/gnulib/import/m4/fcntl.m4            |   126 +
 gdb/gnulib/import/m4/fcntl_h.m4          |    50 +
 gdb/gnulib/import/m4/fdopendir.m4        |    61 +
 gdb/gnulib/import/m4/filenamecat.m4      |    16 +
 gdb/gnulib/import/m4/fstat.m4            |    36 +
 gdb/gnulib/import/m4/fstatat.m4          |    60 +
 gdb/gnulib/import/m4/getcwd-abort-bug.m4 |   140 +
 gdb/gnulib/import/m4/getcwd-path-max.m4  |   217 +
 gdb/gnulib/import/m4/getcwd.m4           |   162 +
 gdb/gnulib/import/m4/getdtablesize.m4    |    46 +
 gdb/gnulib/import/m4/getlogin_r.m4       |    88 +
 gdb/gnulib/import/m4/getprogname.m4      |    43 +
 gdb/gnulib/import/m4/glob.m4             |    76 +
 gdb/gnulib/import/m4/gnulib-cache.m4     |     4 +-
 gdb/gnulib/import/m4/gnulib-comp.m4      |   317 +
 gdb/gnulib/import/m4/mempcpy.m4          |    26 +
 gdb/gnulib/import/m4/memrchr.m4          |    23 +
 gdb/gnulib/import/m4/mode_t.m4           |    26 +
 gdb/gnulib/import/m4/msvc-inval.m4       |    19 +
 gdb/gnulib/import/m4/msvc-nothrow.m4     |    10 +
 gdb/gnulib/import/m4/open.m4             |    91 +
 gdb/gnulib/import/m4/openat.m4           |    36 +
 gdb/gnulib/import/m4/opendir.m4          |    31 +
 gdb/gnulib/import/m4/readdir.m4          |    15 +
 gdb/gnulib/import/m4/realloc.m4          |    79 +
 gdb/gnulib/import/m4/rewinddir.m4        |    15 +
 gdb/gnulib/import/m4/save-cwd.m4         |    11 +
 gdb/gnulib/import/m4/strdup.m4           |    36 +
 gdb/gnulib/import/m4/strerror.m4         |    96 +
 gdb/gnulib/import/m4/unistd-safer.m4     |    10 +
 gdb/gnulib/import/mempcpy.c              |    28 +
 gdb/gnulib/import/memrchr.c              |   161 +
 gdb/gnulib/import/msvc-inval.c           |   129 +
 gdb/gnulib/import/msvc-inval.h           |   222 +
 gdb/gnulib/import/msvc-nothrow.c         |    49 +
 gdb/gnulib/import/msvc-nothrow.h         |    43 +
 gdb/gnulib/import/open.c                 |   181 +
 gdb/gnulib/import/openat-die.c           |    62 +
 gdb/gnulib/import/openat-priv.h          |    64 +
 gdb/gnulib/import/openat-proc.c          |   134 +
 gdb/gnulib/import/openat.c               |   286 +
 gdb/gnulib/import/openat.h               |   123 +
 gdb/gnulib/import/opendir.c              |   169 +
 gdb/gnulib/import/pipe-safer.c           |    56 +
 gdb/gnulib/import/readdir.c              |    98 +
 gdb/gnulib/import/realloc.c              |    79 +
 gdb/gnulib/import/rewinddir.c            |    49 +
 gdb/gnulib/import/save-cwd.c             |    99 +
 gdb/gnulib/import/save-cwd.h             |    34 +
 gdb/gnulib/import/strdup.c               |    54 +
 gdb/gnulib/import/strerror-override.c    |   302 +
 gdb/gnulib/import/strerror-override.h    |    56 +
 gdb/gnulib/import/strerror.c             |    70 +
 gdb/gnulib/import/unistd--.h             |    32 +
 gdb/gnulib/import/unistd-safer.h         |    31 +
 gdb/gnulib/update-gnulib.sh              |     2 +
 gdb/ser-tcp.c                            |     1 +
 110 files changed, 21324 insertions(+), 4457 deletions(-)
 create mode 100644 gdb/gnulib/import/assure.h
 create mode 100644 gdb/gnulib/import/at-func.c
 create mode 100644 gdb/gnulib/import/chdir-long.c
 create mode 100644 gdb/gnulib/import/chdir-long.h
 create mode 100644 gdb/gnulib/import/cloexec.c
 create mode 100644 gdb/gnulib/import/cloexec.h
 create mode 100644 gdb/gnulib/import/close.c
 create mode 100644 gdb/gnulib/import/closedir.c
 create mode 100644 gdb/gnulib/import/dirent-private.h
 create mode 100644 gdb/gnulib/import/dup-safer.c
 create mode 100644 gdb/gnulib/import/dup.c
 create mode 100644 gdb/gnulib/import/dup2.c
 create mode 100644 gdb/gnulib/import/error.c
 create mode 100644 gdb/gnulib/import/error.h
 create mode 100644 gdb/gnulib/import/exitfail.c
 create mode 100644 gdb/gnulib/import/exitfail.h
 create mode 100644 gdb/gnulib/import/fchdir.c
 create mode 100644 gdb/gnulib/import/fcntl.c
 create mode 100644 gdb/gnulib/import/fcntl.in.h
 create mode 100644 gdb/gnulib/import/fd-hook.c
 create mode 100644 gdb/gnulib/import/fd-hook.h
 create mode 100644 gdb/gnulib/import/fd-safer.c
 create mode 100644 gdb/gnulib/import/fdopendir.c
 create mode 100644 gdb/gnulib/import/filename.h
 create mode 100644 gdb/gnulib/import/filenamecat-lgpl.c
 create mode 100644 gdb/gnulib/import/filenamecat.h
 create mode 100644 gdb/gnulib/import/fstat.c
 create mode 100644 gdb/gnulib/import/fstatat.c
 create mode 100644 gdb/gnulib/import/getcwd-lgpl.c
 create mode 100644 gdb/gnulib/import/getcwd.c
 create mode 100644 gdb/gnulib/import/getdtablesize.c
 create mode 100644 gdb/gnulib/import/getlogin_r.c
 create mode 100644 gdb/gnulib/import/getprogname.c
 create mode 100644 gdb/gnulib/import/getprogname.h
 create mode 100644 gdb/gnulib/import/gettext.h
 create mode 100644 gdb/gnulib/import/glob-libc.h
 create mode 100644 gdb/gnulib/import/glob.c
 create mode 100644 gdb/gnulib/import/glob.in.h
 create mode 100644 gdb/gnulib/import/intprops.h
 create mode 100644 gdb/gnulib/import/m4/chdir-long.m4
 create mode 100644 gdb/gnulib/import/m4/close.m4
 create mode 100644 gdb/gnulib/import/m4/closedir.m4
 create mode 100644 gdb/gnulib/import/m4/d-ino.m4
 create mode 100644 gdb/gnulib/import/m4/d-type.m4
 create mode 100644 gdb/gnulib/import/m4/dup.m4
 create mode 100644 gdb/gnulib/import/m4/dup2.m4
 create mode 100644 gdb/gnulib/import/m4/error.m4
 create mode 100644 gdb/gnulib/import/m4/fchdir.m4
 create mode 100644 gdb/gnulib/import/m4/fcntl.m4
 create mode 100644 gdb/gnulib/import/m4/fcntl_h.m4
 create mode 100644 gdb/gnulib/import/m4/fdopendir.m4
 create mode 100644 gdb/gnulib/import/m4/filenamecat.m4
 create mode 100644 gdb/gnulib/import/m4/fstat.m4
 create mode 100644 gdb/gnulib/import/m4/fstatat.m4
 create mode 100644 gdb/gnulib/import/m4/getcwd-abort-bug.m4
 create mode 100644 gdb/gnulib/import/m4/getcwd-path-max.m4
 create mode 100644 gdb/gnulib/import/m4/getcwd.m4
 create mode 100644 gdb/gnulib/import/m4/getdtablesize.m4
 create mode 100644 gdb/gnulib/import/m4/getlogin_r.m4
 create mode 100644 gdb/gnulib/import/m4/getprogname.m4
 create mode 100644 gdb/gnulib/import/m4/glob.m4
 create mode 100644 gdb/gnulib/import/m4/mempcpy.m4
 create mode 100644 gdb/gnulib/import/m4/memrchr.m4
 create mode 100644 gdb/gnulib/import/m4/mode_t.m4
 create mode 100644 gdb/gnulib/import/m4/msvc-inval.m4
 create mode 100644 gdb/gnulib/import/m4/msvc-nothrow.m4
 create mode 100644 gdb/gnulib/import/m4/open.m4
 create mode 100644 gdb/gnulib/import/m4/openat.m4
 create mode 100644 gdb/gnulib/import/m4/opendir.m4
 create mode 100644 gdb/gnulib/import/m4/readdir.m4
 create mode 100644 gdb/gnulib/import/m4/realloc.m4
 create mode 100644 gdb/gnulib/import/m4/rewinddir.m4
 create mode 100644 gdb/gnulib/import/m4/save-cwd.m4
 create mode 100644 gdb/gnulib/import/m4/strdup.m4
 create mode 100644 gdb/gnulib/import/m4/strerror.m4
 create mode 100644 gdb/gnulib/import/m4/unistd-safer.m4
 create mode 100644 gdb/gnulib/import/mempcpy.c
 create mode 100644 gdb/gnulib/import/memrchr.c
 create mode 100644 gdb/gnulib/import/msvc-inval.c
 create mode 100644 gdb/gnulib/import/msvc-inval.h
 create mode 100644 gdb/gnulib/import/msvc-nothrow.c
 create mode 100644 gdb/gnulib/import/msvc-nothrow.h
 create mode 100644 gdb/gnulib/import/open.c
 create mode 100644 gdb/gnulib/import/openat-die.c
 create mode 100644 gdb/gnulib/import/openat-priv.h
 create mode 100644 gdb/gnulib/import/openat-proc.c
 create mode 100644 gdb/gnulib/import/openat.c
 create mode 100644 gdb/gnulib/import/openat.h
 create mode 100644 gdb/gnulib/import/opendir.c
 create mode 100644 gdb/gnulib/import/pipe-safer.c
 create mode 100644 gdb/gnulib/import/readdir.c
 create mode 100644 gdb/gnulib/import/realloc.c
 create mode 100644 gdb/gnulib/import/rewinddir.c
 create mode 100644 gdb/gnulib/import/save-cwd.c
 create mode 100644 gdb/gnulib/import/save-cwd.h
 create mode 100644 gdb/gnulib/import/strdup.c
 create mode 100644 gdb/gnulib/import/strerror-override.c
 create mode 100644 gdb/gnulib/import/strerror-override.h
 create mode 100644 gdb/gnulib/import/strerror.c
 create mode 100644 gdb/gnulib/import/unistd--.h
 create mode 100644 gdb/gnulib/import/unistd-safer.h

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

* New "set cwd" command
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
                   ` (6 preceding siblings ...)
  2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
@ 2017-09-21 22:59 ` Sergio Durigan Junior
  2017-09-21 22:59   ` [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
                     ` (4 more replies)
  2017-09-28  4:10 ` [PATCH v4 0/3] New "set cwd" command Sergio Durigan Junior
  2017-09-29 22:58 ` [PATCH v5 0/3] New "set cwd" command Sergio Durigan Junior
  9 siblings, 5 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-21 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves

v1: https://sourceware.org/ml/gdb-patches/2017-09/msg00321.html
v2: https://sourceware.org/ml/gdb-patches/2017-09/msg00458.html

Changes from v2:

* Patch #1:

  - Mention that "getcwd (NULL, 0)" is a GNU extension on the commit
    log.

  - Rewrite ChangeLog to explicitly say "New file"/"Regenerate"
    instead of "Likewise".

  - Do not remove definition of "close" on gdb/ser-tcp.c; instead,
    "#undef close" before (re)defining it as "closesocket".

* Patch #2:

  - Fix s/target/host/ on commit log.

  - Remove call to '.get ()' method on "gdb::unique_xmalloc_ptr<char>"
    when checking to see if it was initialized correctly.

* Patch #3:

  - This now introduces "gdb_tilde_expand" instead of "gdb_chdir".

  - Improve cases when using a "gdb::unique_xmalloc_ptr<char>" would
    be better.

  - Fix method declaration format inside classes.

* Patch #4:

  - Add sentence on "cd" command's help text explaining what the GDB's
    cwd affects.

  - Improve documentation and explain that cwd changes via "set cwd"
    only take effect the next time the inferior is started.

  - Remove implementation details that explained how UNIX-like targets
    change the inferior's cwd from a few comments.

  - Declare "cwd" field from "struct inferior" as
    "gdb::unique_xmalloc_ptr<char>".

  - Improve message displayed by "show cwd" when the user hasn't set
    the cwd.

  - Improve way that "fork_inferior" changes the directory before
    executing the inferior, obeying the async-signal-safe restriction
    of the function.

  - Update Windows code to deal with wide strings.

  - Remove BUFSIZ from the testcase C file.

  - Fix/improve the way we detect if the testcase is running on a
    remote debugging scenario.

  - Based on a private conversation I had with Pedro, the
    "test_tilde_expansion" method has also been rewritten to avoid
    problems when we're dealing with a remote host.

  - Implement failure detection when gathering information about the
    cwd before/after running the inferior.

  - Use gdb_assert.

* Patch #5:

  - Update text on gdb/NEWS.

  - Remove target-specific implementation detail from
    "set_inferior_cwd"'s comment.

  - Remove sentence explicitly saying that "set cwd" works for both
    native and remote debugging.

  - Update text of "QSetWorkingDir" packet description and make it
    target-independent, as well as update a few references.

  - Update Windows code to deal with wide strings.

  - s/extended_remote_handle_inferior_cwd/extended_remote_set_inferior_cwd/

  - Use packet_ok.

  - Again, update the testcase in order to better detect when we're
    dealing with gdbserver test.



This patch series is a followup of the discussion that happened at:

  https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html

It implements a new GDB command, "set cwd", which is used to set the
current working directory of the inferior that will be started.  This
command works for both native and remote debugging scenarios.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.

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

* [PATCH v3 3/5] Introduce gdb_tilde_expand
  2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
  2017-09-21 22:59   ` [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
  2017-09-21 22:59   ` [PATCH v3 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
@ 2017-09-21 22:59   ` Sergio Durigan Junior
  2017-09-22 11:57     ` Pedro Alves
  2017-09-21 22:59   ` [PATCH v3 4/5] Implement "set cwd" command on GDB Sergio Durigan Junior
  2017-09-21 23:06   ` [PATCH v3 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
  4 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-21 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

Currently, whenever we want to handle paths provided by the user and
perform tilde expansion on GDB, we rely on "tilde_expand", which comes
from readline.  This was enough for our use cases so far, but the
situation will change when we start dealing with paths on gdbserver as
well, which is what the next patches implement.

Unfortunately it is not possible to use "tilde_expand" in this case
because gdbserver doesn't use readline.  For that reason I decided to
implement a new "gdb_tilde_expand" function, which is basically a
wrapper for "glob" and its GNU extension, GLOB_TILDE.  With the import
of the "glob" module from gnulib, this is a no-brainer.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add gdb_tilde_expand.c.
	(HFILES_NO_SRCDIR): Add gdb_tilde_expand.h.
	(COMMON_OBS): Add gdb_tilde_expand.o.
	* cli/cli-cmds.c: Include "gdb_tilde_expand.h".
	(cd_command): Use "gdb_tilde_expand" instead of "tilde_expand".
	* common/gdb_tilde_expand.c: New file.
	* common/gdb_tilde_expand.h: Likewise.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add $(srcdir)/common/gdb_tilde_expand.c.
	(OBS): Add gdb_tilde_expand.o.
---
 gdb/Makefile.in               |  3 ++
 gdb/cli/cli-cmds.c            | 10 +++---
 gdb/common/gdb_tilde_expand.c | 82 +++++++++++++++++++++++++++++++++++++++++++
 gdb/common/gdb_tilde_expand.h | 27 ++++++++++++++
 gdb/gdbserver/Makefile.in     |  2 ++
 5 files changed, 119 insertions(+), 5 deletions(-)
 create mode 100644 gdb/common/gdb_tilde_expand.c
 create mode 100644 gdb/common/gdb_tilde_expand.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 5740d43bb7..d0e3ed2917 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1245,6 +1245,7 @@ SFILES = \
 	common/filestuff.c \
 	common/format.c \
 	common/job-control.c \
+	common/gdb_tilde_expand.c \
 	common/gdb_vecs.c \
 	common/new-op.c \
 	common/print-utils.c \
@@ -1529,6 +1530,7 @@ HFILES_NO_SRCDIR = \
 	common/fileio.h \
 	common/format.h \
 	common/gdb_assert.h \
+	common/gdb_tilde_expand.h \
 	common/gdb_locale.h \
 	common/gdb_setjmp.h \
 	common/gdb_signals.h \
@@ -1734,6 +1736,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	frame-unwind.o \
 	gcore.o \
 	gdb_bfd.o \
+	gdb_tilde_expand.o \
 	gdb-dlfcn.o \
 	gdb_obstack.o \
 	gdb_regex.o \
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index cbafb13837..507fdc4120 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -54,6 +54,8 @@
 #include "tui/tui.h"	/* For tui_active et.al.  */
 #endif
 
+#include "gdb_tilde_expand.h"
+
 #include <fcntl.h>
 #include <algorithm>
 #include <string>
@@ -410,10 +412,8 @@ cd_command (char *dir, int from_tty)
      repeat might be useful but is more likely to be a mistake.  */
   dont_repeat ();
 
-  gdb::unique_xmalloc_ptr<char> dir_holder
-    (tilde_expand (dir != NULL ? dir : "~"));
-  dir = dir_holder.get ();
-
+  std::string expanded_path = gdb_tilde_expand (dir != NULL ? dir : "~");
+  dir = (char *) expanded_path.c_str ();
   if (chdir (dir) < 0)
     perror_with_name (dir);
 
@@ -438,7 +438,7 @@ cd_command (char *dir, int from_tty)
 	len--;
     }
 
-  dir_holder.reset (savestring (dir, len));
+  gdb::unique_xmalloc_ptr<char> dir_holder (savestring (dir, len));
   if (IS_ABSOLUTE_PATH (dir_holder.get ()))
     {
       xfree (current_directory);
diff --git a/gdb/common/gdb_tilde_expand.c b/gdb/common/gdb_tilde_expand.c
new file mode 100644
index 0000000000..08ff4190d2
--- /dev/null
+++ b/gdb/common/gdb_tilde_expand.c
@@ -0,0 +1,82 @@
+/* Perform tilde expansion on paths for GDB and gdbserver.
+
+   Copyright (C) 2017 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 "gdb_tilde_expand.h"
+#include <glob.h>
+
+/* RAII-style class wrapping "glob".  */
+
+class gdb_glob
+{
+public:
+  /* Construct a "gdb_glob" object by calling "glob" with the provided
+     parameters.  This function can throw if "glob" fails.  */
+  gdb_glob (const char *pattern, int flags,
+	    int (*errfunc) (const char *epath, int eerrno))
+  {
+    int ret = glob (pattern, flags, errfunc, &m_glob);
+
+    if (ret != 0)
+      {
+	if (ret == GLOB_NOMATCH)
+	  error (_("Could not find a match for '%s'."), pattern);
+	else
+	  error (_("glob could not process pattern '%s'."),
+		 pattern);
+      }
+  }
+
+  /* Destroy the object and free M_GLOB.  */
+  ~gdb_glob ()
+  {
+    globfree (&m_glob);
+  }
+
+  /* Return the GL_PATHC component of M_GLOB.  */
+  int pathc () const
+  {
+    return m_glob.gl_pathc;
+  }
+
+  /* Return the GL_PATHV component of M_GLOB.  */
+  char **pathv () const
+  {
+    return m_glob.gl_pathv;
+  }
+
+private:
+  /* The actual glob object we're dealing with.  */
+  glob_t m_glob;
+};
+
+/* See common/gdb_tilde_expand.h.  */
+
+std::string
+gdb_tilde_expand (const char *dir)
+{
+  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);
+
+  gdb_assert (glob.pathc () > 0);
+  /* "glob" may return more than one match to the path provided by the
+     user, but we are only interested in the first match.  */
+  std::string expanded_dir = glob.pathv ()[0];
+
+  return expanded_dir;
+}
diff --git a/gdb/common/gdb_tilde_expand.h b/gdb/common/gdb_tilde_expand.h
new file mode 100644
index 0000000000..a5d923d66b
--- /dev/null
+++ b/gdb/common/gdb_tilde_expand.h
@@ -0,0 +1,27 @@
+/* Perform tilde expansion on paths for GDB and gdbserver.
+
+   Copyright (C) 2017 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 HAVE_GDB_TILDE_EXPAND_H
+#define HAVE_GDB_TILDE_EXPAND_H
+
+/* Perform path expansion (i.e., tilde expansion) on DIR, and return
+   the full path.  */
+extern std::string gdb_tilde_expand (const char *dir);
+
+#endif /* ! HAVE_GDB_TILDE_EXPAND_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 1bbe515629..6c931ba952 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -205,6 +205,7 @@ SFILES = \
 	$(srcdir)/common/fileio.c \
 	$(srcdir)/common/filestuff.c \
 	$(srcdir)/common/job-control.c \
+	$(srcdir)/common/gdb_tilde_expand.c \
 	$(srcdir)/common/gdb_vecs.c \
 	$(srcdir)/common/new-op.c \
 	$(srcdir)/common/print-utils.c \
@@ -247,6 +248,7 @@ OBS = \
 	fileio.o \
 	filestuff.o \
 	format.o \
+	gdb_tilde_expand.o \
 	gdb_vecs.o \
 	hostio.o \
 	inferiors.o \
-- 
2.13.3

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

* [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
                     ` (3 preceding siblings ...)
  2017-09-21 22:59   ` [PATCH v3 4/5] Implement "set cwd" command on GDB Sergio Durigan Junior
@ 2017-09-21 23:06   ` Sergio Durigan Junior
  2017-09-22  8:12     ` Eli Zaretskii
  2017-09-27 14:42     ` Pedro Alves
  4 siblings, 2 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-21 23:06 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Sergio Durigan Junior

This is the "natural" extension necessary for the "set cwd" command
(and the whole "set the inferior's cwd" logic) to work on gdbserver.

The idea here is to have a new remote packet, QSetWorkingDir (name
adopted from LLDB's extension to the RSP, as can be seen at
<https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
which sends an hex-encoded string representing the working directory
that gdbserver is supposed to cd into before executing the inferior.
The good thing is that since this feature is already implemented on
nat/fork-inferior.c, all gdbserver has to do is to basically implement
"set_inferior_cwd" and call it whenever such packet arrives.

Aside from that, the patch consists basically of updates to the
testcase (making it available on remote targets) and the
documentation.

No regressions found.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (Changes since GDB 8.0): Add entry about new
	'set-cwd-on-gdbserver' feature.
	(New remote packets): Add entry for QSetWorkingDir.
	* common/common-inferior.h (set_inferior_cwd): New prototype.
	* infcmd.c (set_inferior_cwd): Remove "static".
	(show_cwd_command): Expand text to include remote debugging.
	* remote.c: Add PACKET_QSetWorkingDir.
	(remote_protocol_features) <QSetWorkingDir>: New entry for
	PACKET_QSetWorkingDir.
	(extended_remote_set_inferior_cwd): New function.
	(extended_remote_create_inferior): Call
	"extended_remote_set_inferior_cwd".
	(_initialize_remote): Call "add_packet_config_cmd" for
	QSetWorkingDir.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (set_inferior_cwd): New function.
	* server.c (handle_general_set): Handle QSetWorkingDir packet.
	(handle_query): Inform that QSetWorkingDir is supported.
	* win32-low.c (create_process): Pass the inferior's cwd to
	CreateProcess.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.exp: Make it available on gdbserver.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention remote debugging.
	(Working Directory) <Your Program's Working Directory>:
	Likewise.
	(Connecting) <Remote Packet>: Add "set-working-dir"
	and "QSetWorkingDir" to the table.
	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
	packet.
---
 gdb/NEWS                           | 12 ++++++++++++
 gdb/common/common-inferior.h       |  3 +++
 gdb/doc/gdb.texinfo                | 39 +++++++++++++++++++++++++++++++++++---
 gdb/gdbserver/inferiors.c          |  9 +++++++++
 gdb/gdbserver/server.c             | 18 +++++++++++++++++-
 gdb/gdbserver/win32-low.c          | 15 ++++++++++++---
 gdb/infcmd.c                       |  7 ++++---
 gdb/remote.c                       | 37 ++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 11 +++++++++--
 9 files changed, 139 insertions(+), 12 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index c131713293..4ac340eeb5 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -23,6 +23,14 @@
 
 * New features in the GDB remote stub, GDBserver
 
+  ** GDBserver is now able to set the inferior's current working
+     directory.
+
+     The user can set the desired working directory to be used by the
+     remote inferior on GDB, using the new "set cwd" command, which
+     will instruct GDB to tell GDBserver about this directory change
+     the next time an inferior is run.
+
   ** New "--selftest" command line option runs some GDBserver self
      tests.  These self tests are disabled in releases.
 
@@ -56,6 +64,10 @@ QEnvironmentReset
 QStartupWithShell
   Indicates whether the inferior must be started with a shell or not.
 
+QSetWorkingDir
+  Tell GDBserver that the inferior to be started should use a specific
+  working directory.
+
 * The "maintenance print c-tdesc" command now takes an optional
   argument which is the file name of XML target description.
 
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 515a8c0f4e..26acddc84a 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -34,4 +34,7 @@ extern char *get_exec_file (int err);
    been set, then return NULL.  */
 extern const char *get_inferior_cwd ();
 
+/* Set the inferior current working directory.  */
+extern void set_inferior_cwd (const char *cwd);
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 899afb92b6..7434de2a68 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
 @item The @emph{working directory.}
 You can set your program's working directory with the command
 @code{set cwd}.  If you do not set any working directory with this
-command, your program will inherit @value{GDBN}'s working directory.
-@xref{Working Directory, ,Your Program's Working Directory}.
+command, your program will inherit @value{GDBN}'s working directory if
+native debugging, or @code{gdbserver}'s working directory if remote
+debugging.  @xref{Working Directory, ,Your Program's Working
+Directory}.
 
 @item The @emph{standard input and output.}
 Your program normally uses the same device for standard input and
@@ -2439,7 +2441,9 @@ Each time you start your program with @code{run}, the inferior will be
 initialized with the current working directory specified by the
 @code{set cwd} command.  If no directory has been specified by this
 command, then the inferior will inherit @value{GDBN}'s current working
-directory as its working directory.
+directory as its working directory if native debugging, or it will
+inherit @code{gdbserver}'s current working directory if remote
+debugging.
 
 You can also change @value{GDBN}'s current working directory by using
 the @code{cd} command.
@@ -20993,6 +20997,10 @@ are:
 @tab @code{QEnvironmentReset}
 @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
 
+@item @code{set-working-dir}
+@tab @code{QSetWorkingDir}
+@tab @code{set cwd}
+
 @item @code{conditional-breakpoints-packet}
 @tab @code{Z0 and Z1}
 @tab @code{Support for target-side breakpoint condition evaluation}
@@ -36781,6 +36789,28 @@ Reply:
 @table @samp
 @item OK
 The request succeeded.
+
+@item QSetWorkingDir:@var{hex-value}
+@anchor{QSetWorkingDir packet}
+@cindex set working directory, remote request
+@cindex @samp{QSetWorkingDir} packet
+This packet is used to inform @command{gdbserver} of the intended
+current working directory for programs that are going to be executed.
+
+The packet is composed by @var{hex-value}, an hex encoded
+representation of the directory to be entered by @command{gdbserver}.
+
+This packet is only transmitted when the user issues a @code{set cwd}
+command in @value{GDBN} (@pxref{Working Directory, ,Your Program's
+Working Directory}).
+
+This packet is only available in extended mode (@pxref{extended
+mode}).
+
+Reply:
+@table @samp
+@item OK
+The request succeeded.
 @end table
 
 This packet is not probed by default; the remote stub must request it,
@@ -36811,6 +36841,9 @@ Reply:
 @table @samp
 @item OK
 The request succeeded.
+
+@item E @var{nn}
+An error occurred.  The error number @var{nn} is given as hex digits.
 @end table
 
 This packet is not probed by default; the remote stub must request it,
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index e78ad4faf1..326d01f4d9 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -456,3 +456,12 @@ get_inferior_cwd ()
 {
   return current_inferior_cwd;
 }
+
+/* See common/common-inferior.h.  */
+
+void
+set_inferior_cwd (const char *cwd)
+{
+  xfree ((void *) current_inferior_cwd);
+  current_inferior_cwd = xstrdup (cwd);
+}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index f3eee31052..14f8a732a7 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -869,6 +869,21 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QSetWorkingDir:"))
+    {
+      const char *p = own_buf + strlen ("QSetWorkingDir:");
+      std::string path = hex2str (p);
+
+      set_inferior_cwd (path.c_str ());
+
+      if (remote_debug)
+	debug_printf (_("[Changed current directory to %s]\n"),
+		      path.c_str ());
+      write_ok (own_buf);
+
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -2355,7 +2370,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       sprintf (own_buf,
 	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
 	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
-	       "QEnvironmentReset+;QEnvironmentUnset+",
+	       "QEnvironmentReset+;QEnvironmentUnset+;"
+	       "QSetWorkingDir+",
 	       PBUFSIZ - 1);
 
       if (target_supports_catch_syscall ())
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index cc84d15c2f..62b222d2fa 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -562,10 +562,11 @@ static BOOL
 create_process (const char *program, char *args,
 		DWORD flags, PROCESS_INFORMATION *pi)
 {
+  const char *inferior_cwd = get_inferior_cwd ();
   BOOL ret;
 
 #ifdef _WIN32_WCE
-  wchar_t *p, *wprogram, *wargs;
+  wchar_t *p, *wprogram, *wargs, *wcwd = NULL;
   size_t argslen;
 
   wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
@@ -579,6 +580,14 @@ create_process (const char *program, char *args,
   wargs = alloca ((argslen + 1) * sizeof (wchar_t));
   mbstowcs (wargs, args, argslen + 1);
 
+  if (inferior_cwd != NULL)
+    {
+      size_t cwdlen = strlen (inferior_cwd);
+
+      wcwd = alloca ((cwdlen + 1) * sizeof (wchar_t));
+      mbstowcs (wcwd, inferior_cwd, cwdlen + 1);
+    }
+
   ret = CreateProcessW (wprogram, /* image name */
 			wargs,    /* command line */
 			NULL,     /* security, not supported */
@@ -586,7 +595,7 @@ create_process (const char *program, char *args,
 			FALSE,    /* inherit handles, not supported */
 			flags,    /* start flags */
 			NULL,     /* environment, not supported */
-			NULL,     /* current directory, not supported */
+			wcwd,     /* current directory */
 			NULL,     /* start info, not supported */
 			pi);      /* proc info */
 #else
@@ -599,7 +608,7 @@ create_process (const char *program, char *args,
 			TRUE,     /* inherit handles */
 			flags,    /* start flags */
 			NULL,     /* environment */
-			NULL,     /* current directory */
+			inferior_cwd,     /* current directory */
 			&si,      /* start info */
 			pi);      /* proc info */
 #endif
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 4c5bbfdbf2..f483a33a44 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -250,9 +250,9 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
-/* Set the inferior current working directory.  */
+/* See common/common-inferior.h.  */
 
-static void
+void
 set_inferior_cwd (const char *cwd)
 {
   if (*cwd == '\0')
@@ -292,7 +292,8 @@ show_cwd_command (struct ui_file *file, int from_tty,
     fprintf_filtered (gdb_stdout,
 		      _("\
 You have not set the inferior's current working directory.\n\
-The inferior will inherit GDB's cwd.\n"));
+The inferior will inherit GDB's cwd if native debugging, or gdbserver's\n\
+cwd if remote debugging.\n"));
   else
     fprintf_filtered (gdb_stdout,
 		      _("Current working directory that will be used "
diff --git a/gdb/remote.c b/gdb/remote.c
index 33b0c2a09d..18d3aaea3f 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1434,6 +1434,7 @@ enum {
   PACKET_QPassSignals,
   PACKET_QCatchSyscalls,
   PACKET_QProgramSignals,
+  PACKET_QSetWorkingDir,
   PACKET_QStartupWithShell,
   PACKET_QEnvironmentHexEncoded,
   PACKET_QEnvironmentReset,
@@ -4665,6 +4666,8 @@ static const struct protocol_feature remote_protocol_features[] = {
     PACKET_QCatchSyscalls },
   { "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
     PACKET_QProgramSignals },
+  { "QSetWorkingDir", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QSetWorkingDir },
   { "QStartupWithShell", PACKET_DISABLE, remote_supported_packet,
     PACKET_QStartupWithShell },
   { "QEnvironmentHexEncoded", PACKET_DISABLE, remote_supported_packet,
@@ -9644,6 +9647,35 @@ extended_remote_environment_support (struct remote_state *rs)
       send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
 }
 
+/* Helper function to set the current working directory for the
+   inferior in the remote.  */
+
+static void
+extended_remote_set_inferior_cwd (struct remote_state *rs)
+{
+  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
+    {
+      const char *inferior_cwd = get_inferior_cwd ();
+
+      if (inferior_cwd != NULL)
+	{
+	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
+					 strlen (inferior_cwd));
+
+	  xsnprintf (rs->buf, get_remote_packet_size (),
+		     "QSetWorkingDir:%s", hexpath.c_str ());
+	  putpkt (rs->buf);
+	  getpkt (&rs->buf, &rs->buf_size, 0);
+	  if (packet_ok (rs->buf,
+			 &remote_protocol_packets[PACKET_QSetWorkingDir])
+	      != PACKET_OK)
+	    error (_("\
+Remote replied unexpectedly while changing working directory: %s"),
+		   rs->buf);
+	}
+    }
+}
+
 /* In the extended protocol we want to be able to do things like
    "run" and have them basically work as expected.  So we need
    a special create_inferior function.  We support changing the
@@ -9686,6 +9718,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
 
   extended_remote_environment_support (rs);
 
+  extended_remote_set_inferior_cwd (rs);
+
   /* Now restart the remote server.  */
   run_worked = extended_remote_run (args) != -1;
   if (!run_worked)
@@ -14185,6 +14219,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
 			 "QProgramSignals", "program-signals", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
+			 "QSetWorkingDir", "set-working-dir", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
 			 "QStartupWithShell", "startup-with-shell", 0);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
index f2700ec44d..32458e384e 100644
--- a/gdb/testsuite/gdb.base/set-cwd.exp
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -15,11 +15,18 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
-    untested "not implemented on gdbserver"
+if { [use_gdb_stub] } {
+    untested "not valid on native-gdbserver"
     return
 }
 
+if { [target_info gdb_protocol] == "remote" } {
+    load_lib gdbserver-support.exp
+    if { [skip_gdbserver_tests] } {
+	return
+    }
+}
+
 standard_testfile
 
 if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
-- 
2.13.3

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-21 22:59   ` [PATCH v3 4/5] Implement "set cwd" command on GDB Sergio Durigan Junior
@ 2017-09-22  8:03     ` Eli Zaretskii
  2017-09-22 12:31       ` Pedro Alves
  2017-09-22 18:00       ` Sergio Durigan Junior
  0 siblings, 2 replies; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-22  8:03 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: Pedro Alves <palves@redhat.com>,	Sergio Durigan Junior <sergiodj@redhat.com>
> Date: Thu, 21 Sep 2017 18:59:25 -0400
> 
> This is the actual implementation of the "set/show cwd" commands on
> GDB.  The way they work is:
> 
> - If the user sets the inferior's cwd by using "set cwd", then this
>   directory is saved into current_inferior ()->cwd and is used when
>   the inferior is started (see below).
> 
> - If the user doesn't set the inferior's cwd by using "set cwd", but
>   rather use the "cd" command as before, then this directory is
>   inherited by the inferior because GDB will have chdir'd into it.
> 
> On Unix-like hosts, the way the directory is changed before the
> inferior execution is by expanding the user set directory before the
> fork, and then "chdir" after the call to fork/vfork on
> "fork_inferior", but before the actual execution.  On Windows, the
> inferior cwd set by the user is passed directly to the CreateProcess
> call, which takes care of the actual chdir for us.

Thanks, I have some comments.

> diff --git a/gdb/NEWS b/gdb/NEWS
> index 549f511b29..c131713293 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -64,6 +64,9 @@ QStartupWithShell
>  
>  * New commands
>  
> +set|show cwd
> +  Set and show the current working directory for the inferior.
> +
>  set|show compile-gcc
>    Set and show compilation command used for compiling and injecting code
>    with the 'compile' commands.

This part is OK.

> +@kindex set cwd
> +@cindex change inferior's working directory
> +@item set cwd @r{[}@var{directory}@r{]}
> +Set the inferior's working directory to @var{directory}.  If not
> +given, @var{directory} uses @file{'~'}.

I think we should document here what does "~" mean on MS-Windows,
especially since, when HOME is not in the environment, Gnulib's glob
module doesn't behave according to MS platform recommendations (which
say not to create files directly below %HOMEDRIVE%%HOMEPATH%).

More generally, I think we should say here that the argument is
glob-expanded, because this is user-visible behavior (right?).  Also,
how will TAB-completion react to input of this command? will it expand
the input typed so far?

> +@kindex show cwd
> +@cindex show inferior's working directory
> +@item show cwd
> +Show the inferior's working directory.  If no directory has been
> +specified by @code{set cwd}, then the default inferior's working
> +directory is the same as @value{GDBN}'s working directory.

Does this show the original value typed by the user, or the expanded
value?  E.g., if the user types "set cwd ~/foo", what will "show cwd"
display?  If it shows the unexpanded form, does that mean the actual
cwd will change if, say, HOME changes?

Should we store the cwd after tilde-expansion?

> @@ -2461,6 +2462,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>    BOOL ret;
>    DWORD flags = 0;
>    const char *inferior_io_terminal = get_inferior_io_terminal ();
> +  const char *inferior_cwd = get_inferior_cwd ();
>  
>    if (!exec_file)
>      error (_("No executable specified, use `target exec'."));
> @@ -2488,8 +2490,15 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>  	error (_("Error starting executable: %d"), errno);
>        cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
>        mbstowcs (cygallargs, allargs, len);
> +
> +      len = mbstowcs (NULL, inferior_cwd, 0) + 1;
> +      if (len == (size_t) -1)
> +	error (_("Invalid cwd for inferior: %d"), errno);
> +      infcwd = (wchar_t *) alloca (len * sizeof (wchar_t));
> +      mbstowcs (infcwd, inferior_cwd, len);
>  #else  /* !__USEWIDE */
>        cygallargs = allargs;
> +      infcwd = (cygwin_buf_t *) inferior_cwd;
>  #endif
>      }
>    else
> @@ -2574,7 +2583,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>  		       TRUE,	/* inherit handles */
>  		       flags,	/* start flags */
>  		       w32_env,	/* environment */
> -		       NULL,	/* current directory */
> +		       infcwd,	/* current directory */
>  		       &si,
>  		       &pi);
>    if (w32_env)
> @@ -2697,7 +2706,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>  			TRUE,	/* inherit handles */
>  			flags,	/* start flags */
>  			w32env,	/* environment */
> -			NULL,	/* current directory */
> +			inferior_cwd,	/* current directory */
>  			&si,
>  			&pi);
>    if (tty != INVALID_HANDLE_VALUE)

This seems to pass the unexpanded cwd directly to CreateProcess.  I
don't think this will work on Windows, as this directory is not
interpreted by any shell, so "~" will cause errors.  I think we should
pass this via gdb_tilde_expand, like we do in the Unix case, and I
also think we should mirror all the slashes in the result, just in
case.

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-21 23:06   ` [PATCH v3 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
@ 2017-09-22  8:12     ` Eli Zaretskii
  2017-09-22 18:46       ` Sergio Durigan Junior
  2017-09-27 14:42     ` Pedro Alves
  1 sibling, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-22  8:12 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: Pedro Alves <palves@redhat.com>,	Sergio Durigan Junior <sergiodj@redhat.com>
> Date: Thu, 21 Sep 2017 18:59:26 -0400
> 
> This is the "natural" extension necessary for the "set cwd" command
> (and the whole "set the inferior's cwd" logic) to work on gdbserver.
> 
> The idea here is to have a new remote packet, QSetWorkingDir (name
> adopted from LLDB's extension to the RSP, as can be seen at
> <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
> which sends an hex-encoded string representing the working directory
> that gdbserver is supposed to cd into before executing the inferior.
> The good thing is that since this feature is already implemented on
> nat/fork-inferior.c, all gdbserver has to do is to basically implement
> "set_inferior_cwd" and call it whenever such packet arrives.

This once again raises the issue of whether to send expanded or
unexpanded directory down the wire, and if unexpanded, then what is
the meaning of the default "~" in the inferior.

> diff --git a/gdb/NEWS b/gdb/NEWS
> index c131713293..4ac340eeb5 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -23,6 +23,14 @@
>  
>  * New features in the GDB remote stub, GDBserver
>  
> +  ** GDBserver is now able to set the inferior's current working
> +     directory.
> +
> +     The user can set the desired working directory to be used by the
> +     remote inferior on GDB, using the new "set cwd" command, which
> +     will instruct GDB to tell GDBserver about this directory change
> +     the next time an inferior is run.
> +
>    ** New "--selftest" command line option runs some GDBserver self
>       tests.  These self tests are disabled in releases.
>  
> @@ -56,6 +64,10 @@ QEnvironmentReset
>  QStartupWithShell
>    Indicates whether the inferior must be started with a shell or not.
>  
> +QSetWorkingDir
> +  Tell GDBserver that the inferior to be started should use a specific
> +  working directory.
> +
>  * The "maintenance print c-tdesc" command now takes an optional
>    argument which is the file name of XML target description.

This part is OK.

> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 899afb92b6..7434de2a68 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo

OK for this part.

> +  if (inferior_cwd != NULL)
> +    {
> +      size_t cwdlen = strlen (inferior_cwd);
> +
> +      wcwd = alloca ((cwdlen + 1) * sizeof (wchar_t));
> +      mbstowcs (wcwd, inferior_cwd, cwdlen + 1);
> +    }

no error checking of the mbstowcs conversion?

>    ret = CreateProcessW (wprogram, /* image name */
>  			wargs,    /* command line */
>  			NULL,     /* security, not supported */
> @@ -586,7 +595,7 @@ create_process (const char *program, char *args,
>  			FALSE,    /* inherit handles, not supported */
>  			flags,    /* start flags */
>  			NULL,     /* environment, not supported */
> -			NULL,     /* current directory, not supported */
> +			wcwd,     /* current directory */
>  			NULL,     /* start info, not supported */
>  			pi);      /* proc info */
>  #else
> @@ -599,7 +608,7 @@ create_process (const char *program, char *args,
>  			TRUE,     /* inherit handles */
>  			flags,    /* start flags */
>  			NULL,     /* environment */
> -			NULL,     /* current directory */
> +			inferior_cwd,     /* current directory */
>  			&si,      /* start info */
>  			pi);      /* proc info */

Once again, this feeds CreateProcess with an unexpanded directory,
which AFAIU will not work if the directory includes "~".

> +static void
> +extended_remote_set_inferior_cwd (struct remote_state *rs)
> +{
> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
> +    {
> +      const char *inferior_cwd = get_inferior_cwd ();
> +
> +      if (inferior_cwd != NULL)
> +	{
> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
> +					 strlen (inferior_cwd));
> +

Shouldn't this do some encoding conversion, from the GDB charset to
the target charset, before encoding in hex?

Thanks.

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

* Re: [PATCH v2 5/5] Extend "set cwd" to work on gdbserver
  2017-09-20 23:49       ` Sergio Durigan Junior
  2017-09-21  1:37         ` Sergio Durigan Junior
@ 2017-09-22 10:47         ` Pedro Alves
  2017-09-22 18:33           ` Sergio Durigan Junior
  1 sibling, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 10:47 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/21/2017 12:49 AM, Sergio Durigan Junior wrote:
> On Wednesday, September 20 2017, Pedro Alves wrote:

>> This all looks stale to me.
> 
> Indeed, sorry about this mistake.  I will rewrite the entry as follows:
> 
> * New features in the GDB remote stub, GDBserver
> 
>   ** GDBserver is now able to enter a directory before starting an
>      inferior.
> 
>      The user can set the desired working directory to be used by the
>      remote inferior on GDB, using the new "set cwd" command, which
>      will instruct GDB to tell GDBserver about this directory change
>      the next time an inferior is run.

I still think this is talking too much in terms of implementation
detail, but I'll reply again to v3.

>>> --- a/gdb/testsuite/gdb.base/set-cwd.exp
>>> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
>>> @@ -15,10 +15,16 @@
>>>  # You should have received a copy of the GNU General Public License
>>>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>>  
>>> -if { ![isnative] || [is_remote target] || [is_remote host]
>>> -     || [target_info gdb_protocol] == "extended-remote" } then {
>>> -    untested "not implemented on gdbserver"
>>> -    return
>>> +if { [target_info exists gdb_protocol] } {
>>> +    if { [target_info gdb_protocol] == "remote" } {
>>> +	untested "not implemented on native-gdbserver"
>>> +	return
>>> +    }
>>> +
>>> +    load_lib gdbserver-support.exp
>>> +    if { [skip_gdbserver_tests] } {
>>> +	return
>>> +    }
>>>  }
>>
>> This drops the is_remote host and target checks, but the test is
>> using  "$::env(HOME)", so it really can't work when
>> remote-host/target testing, because that is accessing HOME in the
>> build machine (where dejagnu runs) not of the host machine
>> (where gdb runs) or the target machine (where gdbserver runs):
>>
>> proc test_tilde_expansion { } {
>>     if { [info exists ::env(HOME)] } {
>> 	with_test_prefix "test tilde expansion" {
>> 	    set home $::env(HOME)
> 
> OK, that makes sense, but I wasn't aware that there is a problem between
> "host" and "build" machines.  This is becoming absurdly confuse to me,
> sorry.

We've discussed this off list already.

> 
> In this case, I'd have to check for ![is_remote host], is that right?
> 
>> I don't understand the explicit check for gdbserver in
>> skip_gdbserver_tests.
> 
> I was thinking of the following scenario:
> 
> - The users wants to skip gdbserver tests
> 
> - He runs the test as "make check-gdb TESTS=gdb.base/set-cwd.exp"
> 
> - Because of the unconditional call to "skip_gdbserver_tests", the test
>   doesn't run at all, even though the test *should* run because the user
>   hasn't specified any remote board, etc.

And that's what I don't understand at all.  skip_gdbserver_tests
is useful for the gdb.server/ tests that spawn gdbserver even
if testing with the local/unix board, i.e., the native target.
But this testcase isn't spawning gdbserver manually, unlike e.g., the
gdb.server/ tests.  It just runs against whatever target is
specified by --target_board.

> 
>> Seems to me that instead of that, and the "remote" check we should skip
>> the test if use_gdb_stub, because that's what indicates that when you
>> connect to a target, you're already debugging something, like with
>> plain remote debugging.
> 
> OK, so a simple check to "[use_gdb_stub]" would suffice, you say?  That
> doesn't solve the problem with calling ::env above, right?

Thanks,
Pedro Alves

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

* Re: [PATCH v3 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-21 22:59   ` [PATCH v3 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
@ 2017-09-22 11:01     ` Pedro Alves
  2017-09-22 17:29       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 11:01 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:

> 	* gnulib/import/m4/gnulib-cache.m4: Regenerate

Missing period.

> 	* ser-tcp.c: Undefine "close" before redefining it.

diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
index f35991c..c8be37b 100644
--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -42,6 +42,7 @@
>  #ifndef ETIMEDOUT
>  #define ETIMEDOUT WSAETIMEDOUT
>  #endif
> +#undef close
>  #define close(fd) closesocket (fd)
>  #define ioctl ioctlsocket
>  #else

Please add a comment.  Something like:

/* Gnulib defines close too, but gnulib's replacement
   doesn't call closesocket unless we import the
   socketlib module.  */

Otherwise OK.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)"
  2017-09-21 22:59   ` [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
@ 2017-09-22 11:19     ` Pedro Alves
  2017-09-22 17:30       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 11:19 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* cli/cli-cmds.c (pwd_command): Use "getcwd (NULL, 0)".
> 	(cd_command): Likewise.  Free "current_directory" before
> 	assigning to it.
> 	* main.c (captured_main_1): Use "getcwd (NULL, 0)".
> 	* mi/mi-cmd-env.c (mi_cmd_env_pwd): Likewise.
> 	* top.c (gdb_dirbuf): Remove global declaration.
> 	* top.h (gdb_dirbuf): Likewise.

OK.  And trying the new thing:

Reviewed-by: Pedro Alves <palves@redhat.com>

... provided the nit below is addressed.

You can push patches 1 and 2 now, without waiting for the
rest of the series.

> diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
> index 977b6e274d..db87ead33d 100644
> --- a/gdb/mi/mi-cmd-env.c
> +++ b/gdb/mi/mi-cmd-env.c
> @@ -73,12 +73,12 @@ mi_cmd_env_pwd (const char *command, char **argv, int argc)
>      }
>       
>    /* Otherwise the mi level is 2 or higher.  */
> -
> -  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))

Please leave the empty line after the comment.  That comment is
logically related to the code above, not the getcwd call.

> +  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
> +  if (cwd == NULL)
>      error (_("-environment-pwd: error finding name of working directory: %s"),
>             safe_strerror (errno));
> -    
> -  uiout->field_string ("cwd", gdb_dirbuf);
> +
> +  uiout->field_string ("cwd", cwd.get ());
>  }

Thanks,
Pedro Alves

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

* Re: [PATCH v3 3/5] Introduce gdb_tilde_expand
  2017-09-21 22:59   ` [PATCH v3 3/5] Introduce gdb_tilde_expand Sergio Durigan Junior
@ 2017-09-22 11:57     ` Pedro Alves
  2017-09-22 17:37       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 11:57 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:

> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
> index cbafb13837..507fdc4120 100644
> --- a/gdb/cli/cli-cmds.c
> +++ b/gdb/cli/cli-cmds.c
> @@ -54,6 +54,8 @@
>  #include "tui/tui.h"	/* For tui_active et.al.  */
>  #endif
>  
> +#include "gdb_tilde_expand.h"
> +
>  #include <fcntl.h>
>  #include <algorithm>
>  #include <string>
> @@ -410,10 +412,8 @@ cd_command (char *dir, int from_tty)
>       repeat might be useful but is more likely to be a mistake.  */
>    dont_repeat ();
>  
> -  gdb::unique_xmalloc_ptr<char> dir_holder
> -    (tilde_expand (dir != NULL ? dir : "~"));
> -  dir = dir_holder.get ();
> -
> +  std::string expanded_path = gdb_tilde_expand (dir != NULL ? dir : "~");
> +  dir = (char *) expanded_path.c_str ();
>    if (chdir (dir) < 0)
>      perror_with_name (dir);
>  
> @@ -438,7 +438,7 @@ cd_command (char *dir, int from_tty)
>  	len--;
>      }
>  
> -  dir_holder.reset (savestring (dir, len));
> +  gdb::unique_xmalloc_ptr<char> dir_holder (savestring (dir, len));
>    if (IS_ABSOLUTE_PATH (dir_holder.get ()))
>      {
>        xfree (current_directory);


I realized something: in light of the fact that "cd" is not what
is used to specify the inferior's cwd anymore since v1, patching
this particular use of tilde_expand, and not others seems arbitrary.

I.e., this now looks like kind of a spurious change to me, and
I think you should drop the changes to this file...

> +/* See common/gdb_tilde_expand.h.  */
> +
> +std::string
> +gdb_tilde_expand (const char *dir)
> +{
> +  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);

By my reading of man glob, GLOB_TILDE_CHECK already implies GLOB_TILDE.

I'm not sure whether GLOB_ONLYDIR is the right thing to do in
a function whose name doesn't suggest that it concern itself
with anything other than tilde expansion.  E.g., if we replaced
tilde_expand with gdb_tilde_expand in place that expect to match
files (like e.g., gdb_print_filename), then would this work as is?

Maybe you should rename this to gdb_tilde_expand_dir (leaving
the file names as is).

Thanks,
Pedro Alves

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22  8:03     ` Eli Zaretskii
@ 2017-09-22 12:31       ` Pedro Alves
  2017-09-22 18:15         ` Sergio Durigan Junior
  2017-09-22 18:00       ` Sergio Durigan Junior
  1 sibling, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 12:31 UTC (permalink / raw)
  To: Eli Zaretskii, Sergio Durigan Junior; +Cc: gdb-patches

On 09/22/2017 09:02 AM, Eli Zaretskii wrote:
>> From: Sergio Durigan Junior <sergiodj@redhat.com>

> 
>> +@kindex set cwd
>> +@cindex change inferior's working directory
>> +@item set cwd @r{[}@var{directory}@r{]}
>> +Set the inferior's working directory to @var{directory}.  If not
>> +given, @var{directory} uses @file{'~'}.
> 
> I think we should document here what does "~" mean on MS-Windows,
> especially since, when HOME is not in the environment, Gnulib's glob
> module doesn't behave according to MS platform recommendations (which
> say not to create files directly below %HOMEDRIVE%%HOMEPATH%).
> 
> More generally, I think we should say here that the argument is
> glob-expanded, because this is user-visible behavior (right?).  Also,
> how will TAB-completion react to input of this command? will it expand
> the input typed so far?

Actually, should the command default to ~ at all?  Shouldn't we
make "set cwd" clear the setting to the default state, i.e.,
empty?  Otherwise, how do you get back to the default state?

>> +@kindex show cwd
>> +@cindex show inferior's working directory
>> +@item show cwd
>> +Show the inferior's working directory.  If no directory has been
>> +specified by @code{set cwd}, then the default inferior's working
>> +directory is the same as @value{GDBN}'s working directory.
> 
> Does this show the original value typed by the user, or the expanded
> value?  E.g., if the user types "set cwd ~/foo", what will "show cwd"
> display?  If it shows the unexpanded form, does that mean the actual
> cwd will change if, say, HOME changes?
> 
> Should we store the cwd after tilde-expansion?

I don't think so, because this is an inferior setting.  I.e.,
e.g., when remote debugging, only the target (remote side) can
do the expansion, and the user may set this before connecting
to a target (remote, native, etc.), even.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 1/5] Import "glob" and "getcwd" modules from gnulib
  2017-09-22 11:01     ` Pedro Alves
@ 2017-09-22 17:29       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 17:29 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Friday, September 22 2017, Pedro Alves wrote:

> On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:
>
>> 	* gnulib/import/m4/gnulib-cache.m4: Regenerate
>
> Missing period.

Fixed.

>> 	* ser-tcp.c: Undefine "close" before redefining it.
>
> diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
> index f35991c..c8be37b 100644
> --- a/gdb/ser-tcp.c
> +++ b/gdb/ser-tcp.c
> @@ -42,6 +42,7 @@
>>  #ifndef ETIMEDOUT
>>  #define ETIMEDOUT WSAETIMEDOUT
>>  #endif
>> +#undef close
>>  #define close(fd) closesocket (fd)
>>  #define ioctl ioctlsocket
>>  #else
>
> Please add a comment.  Something like:
>
> /* Gnulib defines close too, but gnulib's replacement
>    doesn't call closesocket unless we import the
>    socketlib module.  */

Added.

> Otherwise OK.

Pushed.

6ec2e0f5bddc69d55e09fe56792edf7a109ff8ae

Thanks,

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

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

* Re: [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)"
  2017-09-22 11:19     ` Pedro Alves
@ 2017-09-22 17:30       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 17:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Friday, September 22 2017, Pedro Alves wrote:

> On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:
>> 
>> gdb/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* cli/cli-cmds.c (pwd_command): Use "getcwd (NULL, 0)".
>> 	(cd_command): Likewise.  Free "current_directory" before
>> 	assigning to it.
>> 	* main.c (captured_main_1): Use "getcwd (NULL, 0)".
>> 	* mi/mi-cmd-env.c (mi_cmd_env_pwd): Likewise.
>> 	* top.c (gdb_dirbuf): Remove global declaration.
>> 	* top.h (gdb_dirbuf): Likewise.
>
> OK.  And trying the new thing:
>
> Reviewed-by: Pedro Alves <palves@redhat.com>
>
> ... provided the nit below is addressed.

AFAIU I had to add this to the commit log.  I did this; if this wasn't
correct, I apologize.

>> diff --git a/gdb/mi/mi-cmd-env.c b/gdb/mi/mi-cmd-env.c
>> index 977b6e274d..db87ead33d 100644
>> --- a/gdb/mi/mi-cmd-env.c
>> +++ b/gdb/mi/mi-cmd-env.c
>> @@ -73,12 +73,12 @@ mi_cmd_env_pwd (const char *command, char **argv, int argc)
>>      }
>>       
>>    /* Otherwise the mi level is 2 or higher.  */
>> -
>> -  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
>
> Please leave the empty line after the comment.  That comment is
> logically related to the code above, not the getcwd call.

Done.

>> +  gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
>> +  if (cwd == NULL)
>>      error (_("-environment-pwd: error finding name of working directory: %s"),
>>             safe_strerror (errno));
>> -    
>> -  uiout->field_string ("cwd", gdb_dirbuf);
>> +
>> +  uiout->field_string ("cwd", cwd.get ());
>>  }
>
> Thanks,
> Pedro Alves

Pushed.

43573013c9836f2b91b74b9b29dac35fdb41e06b

Thanks,

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

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

* Re: [PATCH v3 3/5] Introduce gdb_tilde_expand
  2017-09-22 11:57     ` Pedro Alves
@ 2017-09-22 17:37       ` Sergio Durigan Junior
  2017-09-22 17:41         ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 17:37 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Friday, September 22 2017, Pedro Alves wrote:

> On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:
>
>> diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
>> index cbafb13837..507fdc4120 100644
>> --- a/gdb/cli/cli-cmds.c
>> +++ b/gdb/cli/cli-cmds.c
>> @@ -54,6 +54,8 @@
>>  #include "tui/tui.h"	/* For tui_active et.al.  */
>>  #endif
>>  
>> +#include "gdb_tilde_expand.h"
>> +
>>  #include <fcntl.h>
>>  #include <algorithm>
>>  #include <string>
>> @@ -410,10 +412,8 @@ cd_command (char *dir, int from_tty)
>>       repeat might be useful but is more likely to be a mistake.  */
>>    dont_repeat ();
>>  
>> -  gdb::unique_xmalloc_ptr<char> dir_holder
>> -    (tilde_expand (dir != NULL ? dir : "~"));
>> -  dir = dir_holder.get ();
>> -
>> +  std::string expanded_path = gdb_tilde_expand (dir != NULL ? dir : "~");
>> +  dir = (char *) expanded_path.c_str ();
>>    if (chdir (dir) < 0)
>>      perror_with_name (dir);
>>  
>> @@ -438,7 +438,7 @@ cd_command (char *dir, int from_tty)
>>  	len--;
>>      }
>>  
>> -  dir_holder.reset (savestring (dir, len));
>> +  gdb::unique_xmalloc_ptr<char> dir_holder (savestring (dir, len));
>>    if (IS_ABSOLUTE_PATH (dir_holder.get ()))
>>      {
>>        xfree (current_directory);
>
>
> I realized something: in light of the fact that "cd" is not what
> is used to specify the inferior's cwd anymore since v1, patching
> this particular use of tilde_expand, and not others seems arbitrary.
>
> I.e., this now looks like kind of a spurious change to me, and
> I think you should drop the changes to this file...

Yeah, you're right.  I still intend to keep the cleanups, if that's OK
for you.

>> +/* See common/gdb_tilde_expand.h.  */
>> +
>> +std::string
>> +gdb_tilde_expand (const char *dir)
>> +{
>> +  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);
>
> By my reading of man glob, GLOB_TILDE_CHECK already implies GLOB_TILDE.

Yes, but I think it pays to be explicit in this case.

> I'm not sure whether GLOB_ONLYDIR is the right thing to do in
> a function whose name doesn't suggest that it concern itself
> with anything other than tilde expansion.  E.g., if we replaced
> tilde_expand with gdb_tilde_expand in place that expect to match
> files (like e.g., gdb_print_filename), then would this work as is?
>
> Maybe you should rename this to gdb_tilde_expand_dir (leaving
> the file names as is).

Or I could simply remove GLOB_ONLYDIR (which is a leftover from the
previous versions of the patch) and make this function generic.  In
fact, I think I prefer this approach, because according to the manpage:

GLOB_ONLYDIR
	This is a hint to  glob() that the caller is interested
	only  in directories  that match  the pattern.   If the
	implementation    can   easily    determine   file-type
	information, then  nondirectory files are  not returned
	to the  caller.  However,  the caller must  still check
	that returned  files are directories.  (The  purpose of
	this flag  is merely  to optimize performance  when the
	caller is interested only in directories.)

I.e., it's only a helper flag for "glob".

I'll remove GLOB_ONLYDIR and resubmit the patch.

Thanks,

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

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

* Re: [PATCH v3 3/5] Introduce gdb_tilde_expand
  2017-09-22 17:37       ` Sergio Durigan Junior
@ 2017-09-22 17:41         ` Pedro Alves
  2017-09-22 18:07           ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 17:41 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/22/2017 06:37 PM, Sergio Durigan Junior wrote:
> On Friday, September 22 2017, Pedro Alves wrote:

>> I realized something: in light of the fact that "cd" is not what
>> is used to specify the inferior's cwd anymore since v1, patching
>> this particular use of tilde_expand, and not others seems arbitrary.
>>
>> I.e., this now looks like kind of a spurious change to me, and
>> I think you should drop the changes to this file...
> 
> Yeah, you're right.  I still intend to keep the cleanups, if that's OK
> for you.

I don't know what you mean by that.

> 
>>> +/* See common/gdb_tilde_expand.h.  */
>>> +
>>> +std::string
>>> +gdb_tilde_expand (const char *dir)
>>> +{
>>> +  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);
>>
>> By my reading of man glob, GLOB_TILDE_CHECK already implies GLOB_TILDE.
> 
> Yes, but I think it pays to be explicit in this case.

I think it only adds to confusion.  I did "man glob",
saw that GLOB_TILDE_CHECK implies GLOB_TILDE and then
got to wonder why is GLOB_TILDE being passed explicitly.

> I'll remove GLOB_ONLYDIR and resubmit the patch.

Fine with me.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22  8:03     ` Eli Zaretskii
  2017-09-22 12:31       ` Pedro Alves
@ 2017-09-22 18:00       ` Sergio Durigan Junior
  2017-09-22 18:56         ` Eli Zaretskii
  1 sibling, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 18:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Friday, September 22 2017, Eli Zaretskii wrote:

>> +@kindex set cwd
>> +@cindex change inferior's working directory
>> +@item set cwd @r{[}@var{directory}@r{]}
>> +Set the inferior's working directory to @var{directory}.  If not
>> +given, @var{directory} uses @file{'~'}.
>
> I think we should document here what does "~" mean on MS-Windows,
> especially since, when HOME is not in the environment, Gnulib's glob
> module doesn't behave according to MS platform recommendations (which
> say not to create files directly below %HOMEDRIVE%%HOMEPATH%).

Sure, but just to be clear, this text was strongly based on another part
of the docs, which also mentions '~' without explaining further.

As I am totally out of the loop when it comes to Windows environments,
I'd appreciate a suggestion for the new text.

> More generally, I think we should say here that the argument is
> glob-expanded, because this is user-visible behavior (right?).  Also,
> how will TAB-completion react to input of this command? will it expand
> the input typed so far?

TAB-completion will not change anything; we don't have such a facility
on GDB AFAIK.  But it will complete the input.

>> +@kindex show cwd
>> +@cindex show inferior's working directory
>> +@item show cwd
>> +Show the inferior's working directory.  If no directory has been
>> +specified by @code{set cwd}, then the default inferior's working
>> +directory is the same as @value{GDBN}'s working directory.
>
> Does this show the original value typed by the user, or the expanded
> value?  E.g., if the user types "set cwd ~/foo", what will "show cwd"
> display?  If it shows the unexpanded form, does that mean the actual
> cwd will change if, say, HOME changes?

Pedro and I had a conversation about this specific topic yesterday, and
the decision was that the host should not do any path expansion on this
case.  Therefore, whatever the user sets with "set cwd" is not expanded
until the inferior starts, which means that it is the target who
performs the expansion.

> Should we store the cwd after tilde-expansion?

I don't think so.  Or at least I cannot see a reason to do that.

>> @@ -2461,6 +2462,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>    BOOL ret;
>>    DWORD flags = 0;
>>    const char *inferior_io_terminal = get_inferior_io_terminal ();
>> +  const char *inferior_cwd = get_inferior_cwd ();
>>  
>>    if (!exec_file)
>>      error (_("No executable specified, use `target exec'."));
>> @@ -2488,8 +2490,15 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>  	error (_("Error starting executable: %d"), errno);
>>        cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
>>        mbstowcs (cygallargs, allargs, len);
>> +
>> +      len = mbstowcs (NULL, inferior_cwd, 0) + 1;
>> +      if (len == (size_t) -1)
>> +	error (_("Invalid cwd for inferior: %d"), errno);
>> +      infcwd = (wchar_t *) alloca (len * sizeof (wchar_t));
>> +      mbstowcs (infcwd, inferior_cwd, len);
>>  #else  /* !__USEWIDE */
>>        cygallargs = allargs;
>> +      infcwd = (cygwin_buf_t *) inferior_cwd;
>>  #endif
>>      }
>>    else
>> @@ -2574,7 +2583,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>  		       TRUE,	/* inherit handles */
>>  		       flags,	/* start flags */
>>  		       w32_env,	/* environment */
>> -		       NULL,	/* current directory */
>> +		       infcwd,	/* current directory */
>>  		       &si,
>>  		       &pi);
>>    if (w32_env)
>> @@ -2697,7 +2706,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>  			TRUE,	/* inherit handles */
>>  			flags,	/* start flags */
>>  			w32env,	/* environment */
>> -			NULL,	/* current directory */
>> +			inferior_cwd,	/* current directory */
>>  			&si,
>>  			&pi);
>>    if (tty != INVALID_HANDLE_VALUE)
>
> This seems to pass the unexpanded cwd directly to CreateProcess.  I
> don't think this will work on Windows, as this directory is not
> interpreted by any shell, so "~" will cause errors.  I think we should
> pass this via gdb_tilde_expand, like we do in the Unix case, and I
> also think we should mirror all the slashes in the result, just in
> case.

Hm, you're right.  I will call "gdb_tilde_expand" here.  I'm not sure
what you mean by "mirror all the slashes in the result".  Do you mean
"escape the slashes"?

Thanks,

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

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

* Re: [PATCH v3 3/5] Introduce gdb_tilde_expand
  2017-09-22 17:41         ` Pedro Alves
@ 2017-09-22 18:07           ` Sergio Durigan Junior
  2017-09-22 18:20             ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 18:07 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Friday, September 22 2017, Pedro Alves wrote:

> On 09/22/2017 06:37 PM, Sergio Durigan Junior wrote:
>> On Friday, September 22 2017, Pedro Alves wrote:
>
>>> I realized something: in light of the fact that "cd" is not what
>>> is used to specify the inferior's cwd anymore since v1, patching
>>> this particular use of tilde_expand, and not others seems arbitrary.
>>>
>>> I.e., this now looks like kind of a spurious change to me, and
>>> I think you should drop the changes to this file...
>> 
>> Yeah, you're right.  I still intend to keep the cleanups, if that's OK
>> for you.
>
> I don't know what you mean by that.

Sorry, I hadn't really understood what you were saying.  I will remove
the changes to gdb/cli/cli-cmds.c from the patch.

>>>> +/* See common/gdb_tilde_expand.h.  */
>>>> +
>>>> +std::string
>>>> +gdb_tilde_expand (const char *dir)
>>>> +{
>>>> +  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);
>>>
>>> By my reading of man glob, GLOB_TILDE_CHECK already implies GLOB_TILDE.
>> 
>> Yes, but I think it pays to be explicit in this case.
>
> I think it only adds to confusion.  I did "man glob",
> saw that GLOB_TILDE_CHECK implies GLOB_TILDE and then
> got to wonder why is GLOB_TILDE being passed explicitly.

Well, I personally don't really see the reason for the confusion here
since you could have read GLOB_TILDE's entry as well and noticed that
there is nothing fancy being done here, but I respect your way of
thinking, so I will just remove GLOB_TILDE_CHECK.

Thanks,

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

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 12:31       ` Pedro Alves
@ 2017-09-22 18:15         ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 18:15 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Eli Zaretskii, gdb-patches

On Friday, September 22 2017, Pedro Alves wrote:

> On 09/22/2017 09:02 AM, Eli Zaretskii wrote:
>>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>
>> 
>>> +@kindex set cwd
>>> +@cindex change inferior's working directory
>>> +@item set cwd @r{[}@var{directory}@r{]}
>>> +Set the inferior's working directory to @var{directory}.  If not
>>> +given, @var{directory} uses @file{'~'}.
>> 
>> I think we should document here what does "~" mean on MS-Windows,
>> especially since, when HOME is not in the environment, Gnulib's glob
>> module doesn't behave according to MS platform recommendations (which
>> say not to create files directly below %HOMEDRIVE%%HOMEPATH%).
>> 
>> More generally, I think we should say here that the argument is
>> glob-expanded, because this is user-visible behavior (right?).  Also,
>> how will TAB-completion react to input of this command? will it expand
>> the input typed so far?
>
> Actually, should the command default to ~ at all?  Shouldn't we
> make "set cwd" clear the setting to the default state, i.e.,
> empty?  Otherwise, how do you get back to the default state?

That's a good point.  "set cwd" currently mimics what "cd" does, and
that's the reason for this "default is to use ~" decision.

I can certainly make "set cwd" without arguments to clear out whatever
has been set by the user.  I think that's a more sensible decision
indeed.

Thanks,

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

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

* Re: [PATCH v3 3/5] Introduce gdb_tilde_expand
  2017-09-22 18:07           ` Sergio Durigan Junior
@ 2017-09-22 18:20             ` Pedro Alves
  2017-09-22 18:22               ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 18:20 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/22/2017 07:07 PM, Sergio Durigan Junior wrote:
> On Friday, September 22 2017, Pedro Alves wrote:
> 
>>>>> +/* See common/gdb_tilde_expand.h.  */
>>>>> +
>>>>> +std::string
>>>>> +gdb_tilde_expand (const char *dir)
>>>>> +{
>>>>> +  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);
>>>>
>>>> By my reading of man glob, GLOB_TILDE_CHECK already implies GLOB_TILDE.
>>>
>>> Yes, but I think it pays to be explicit in this case.
>>
>> I think it only adds to confusion.  I did "man glob",
>> saw that GLOB_TILDE_CHECK implies GLOB_TILDE and then
>> got to wonder why is GLOB_TILDE being passed explicitly.
> 
> Well, I personally don't really see the reason for the confusion here
> since you could have read GLOB_TILDE's entry as well and noticed that
> there is nothing fancy being done here, but I respect your way of
> thinking, so I will just remove GLOB_TILDE_CHECK.

I did not suggest to remove GLOB_TILDE_CHECK.

What I'm saying is that the man page looks like this:

      GLOB_TILDE
              Carry out tilde expansion. (...)

      GLOB_TILDE_CHECK
              This provides behavior similar to that of GLOB_TILDE.  The difference is that (...)

And from reading this, my interpretation is that GLOB_TILDE
and GLOB_TILDE_CHECK are two different modes.  From that
description, I'd think it reasonable for glob to reject
"GLOB_TILDE | GLOB_TILDE_CHECK" as ambiguous -- which mode
to you want with that?

Note that it says "provides behavior similar", not
"in combination with GLOB_TILDE".

With GLOB_TILDE | GLOB_TILDE_CHECK, I assumed that you
meant GLOB_TILDE_CHECK, but I have no idea whether that's
what all glob implementations actually end up interpreting
it as.  But why leave that ambiguity?  Just specify what
you want, exactly.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 3/5] Introduce gdb_tilde_expand
  2017-09-22 18:20             ` Pedro Alves
@ 2017-09-22 18:22               ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 18:22 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Friday, September 22 2017, Pedro Alves wrote:

> On 09/22/2017 07:07 PM, Sergio Durigan Junior wrote:
>> On Friday, September 22 2017, Pedro Alves wrote:
>> 
>>>>>> +/* See common/gdb_tilde_expand.h.  */
>>>>>> +
>>>>>> +std::string
>>>>>> +gdb_tilde_expand (const char *dir)
>>>>>> +{
>>>>>> +  gdb_glob glob (dir, GLOB_TILDE | GLOB_TILDE_CHECK | GLOB_ONLYDIR, NULL);
>>>>>
>>>>> By my reading of man glob, GLOB_TILDE_CHECK already implies GLOB_TILDE.
>>>>
>>>> Yes, but I think it pays to be explicit in this case.
>>>
>>> I think it only adds to confusion.  I did "man glob",
>>> saw that GLOB_TILDE_CHECK implies GLOB_TILDE and then
>>> got to wonder why is GLOB_TILDE being passed explicitly.
>> 
>> Well, I personally don't really see the reason for the confusion here
>> since you could have read GLOB_TILDE's entry as well and noticed that
>> there is nothing fancy being done here, but I respect your way of
>> thinking, so I will just remove GLOB_TILDE_CHECK.
>
> I did not suggest to remove GLOB_TILDE_CHECK.

Sorry, my bad, I meant "remove GLOB_TILDE".

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

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

* Re: [PATCH v2 5/5] Extend "set cwd" to work on gdbserver
  2017-09-22 10:47         ` Pedro Alves
@ 2017-09-22 18:33           ` Sergio Durigan Junior
  2017-09-27 13:28             ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 18:33 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Friday, September 22 2017, Pedro Alves wrote:

> On 09/21/2017 12:49 AM, Sergio Durigan Junior wrote:
>> On Wednesday, September 20 2017, Pedro Alves wrote:
>
>>> This all looks stale to me.
>> 
>> Indeed, sorry about this mistake.  I will rewrite the entry as follows:
>> 
>> * New features in the GDB remote stub, GDBserver
>> 
>>   ** GDBserver is now able to enter a directory before starting an
>>      inferior.
>> 
>>      The user can set the desired working directory to be used by the
>>      remote inferior on GDB, using the new "set cwd" command, which
>>      will instruct GDB to tell GDBserver about this directory change
>>      the next time an inferior is run.
>
> I still think this is talking too much in terms of implementation
> detail, but I'll reply again to v3.

I'm curious to know why.  I'll wait for your review.

>> In this case, I'd have to check for ![is_remote host], is that right?
>> 
>>> I don't understand the explicit check for gdbserver in
>>> skip_gdbserver_tests.
>> 
>> I was thinking of the following scenario:
>> 
>> - The users wants to skip gdbserver tests
>> 
>> - He runs the test as "make check-gdb TESTS=gdb.base/set-cwd.exp"
>> 
>> - Because of the unconditional call to "skip_gdbserver_tests", the test
>>   doesn't run at all, even though the test *should* run because the user
>>   hasn't specified any remote board, etc.
>
> And that's what I don't understand at all.  skip_gdbserver_tests
> is useful for the gdb.server/ tests that spawn gdbserver even
> if testing with the local/unix board, i.e., the native target.
> But this testcase isn't spawning gdbserver manually, unlike e.g., the
> gdb.server/ tests.  It just runs against whatever target is
> specified by --target_board.

Ah.  Then I *really* misunderstood these concepts.  Thanks for
clarifying this to me.  v3 still has the call to "skip_gdbserver_tests",
so please ignore it.

Thanks,

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

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-22  8:12     ` Eli Zaretskii
@ 2017-09-22 18:46       ` Sergio Durigan Junior
  2017-09-22 19:09         ` Eli Zaretskii
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 18:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Friday, September 22 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: Pedro Alves <palves@redhat.com>,	Sergio Durigan Junior <sergiodj@redhat.com>
>> Date: Thu, 21 Sep 2017 18:59:26 -0400
>> 
>> This is the "natural" extension necessary for the "set cwd" command
>> (and the whole "set the inferior's cwd" logic) to work on gdbserver.
>> 
>> The idea here is to have a new remote packet, QSetWorkingDir (name
>> adopted from LLDB's extension to the RSP, as can be seen at
>> <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
>> which sends an hex-encoded string representing the working directory
>> that gdbserver is supposed to cd into before executing the inferior.
>> The good thing is that since this feature is already implemented on
>> nat/fork-inferior.c, all gdbserver has to do is to basically implement
>> "set_inferior_cwd" and call it whenever such packet arrives.
>
> This once again raises the issue of whether to send expanded or
> unexpanded directory down the wire, and if unexpanded, then what is
> the meaning of the default "~" in the inferior.

FWIW, I decided (based on another message by Pedro) to modify the
behaviour of "set cwd" without arguments.  Before it was setting the
inferior's cwd as "~", but now it clears out whatever cwd that has been
specified by the user.

But of course, the user can still do "set cwd ~".  We do not expand
paths on the host, as I explained in another message, so gdbserver will
see "~" coming down the wire.  Then, when the inferior is to be started,
gdbserver will perform the path expansion based on what
"gdb_tilde_expand" (i.e., "glob") does.

>> +  if (inferior_cwd != NULL)
>> +    {
>> +      size_t cwdlen = strlen (inferior_cwd);
>> +
>> +      wcwd = alloca ((cwdlen + 1) * sizeof (wchar_t));
>> +      mbstowcs (wcwd, inferior_cwd, cwdlen + 1);
>> +    }
>
> no error checking of the mbstowcs conversion?

Sorry, I am not a Windows programmer.  Other places in the code also
don't check for errors.  I'd be happy to improve this code, but I refuse
to touch a Windows machine so I'm doing this all this without any
testing.  But please, feel absolutely free to point out how this code
should look like.

>>    ret = CreateProcessW (wprogram, /* image name */
>>  			wargs,    /* command line */
>>  			NULL,     /* security, not supported */
>> @@ -586,7 +595,7 @@ create_process (const char *program, char *args,
>>  			FALSE,    /* inherit handles, not supported */
>>  			flags,    /* start flags */
>>  			NULL,     /* environment, not supported */
>> -			NULL,     /* current directory, not supported */
>> +			wcwd,     /* current directory */
>>  			NULL,     /* start info, not supported */
>>  			pi);      /* proc info */
>>  #else
>> @@ -599,7 +608,7 @@ create_process (const char *program, char *args,
>>  			TRUE,     /* inherit handles */
>>  			flags,    /* start flags */
>>  			NULL,     /* environment */
>> -			NULL,     /* current directory */
>> +			inferior_cwd,     /* current directory */
>>  			&si,      /* start info */
>>  			pi);      /* proc info */
>
> Once again, this feeds CreateProcess with an unexpanded directory,
> which AFAIU will not work if the directory includes "~".

You're right; I've changed that now.

>> +static void
>> +extended_remote_set_inferior_cwd (struct remote_state *rs)
>> +{
>> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
>> +    {
>> +      const char *inferior_cwd = get_inferior_cwd ();
>> +
>> +      if (inferior_cwd != NULL)
>> +	{
>> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
>> +					 strlen (inferior_cwd));
>> +
>
> Shouldn't this do some encoding conversion, from the GDB charset to
> the target charset, before encoding in hex?

I don't know.  There's nothing related to charset on gdb/gdbserver/, but
then again I don't know if we've ever encountered a case that demanded
conversions.  I can investigate this a bit more.

Thanks,

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

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 18:00       ` Sergio Durigan Junior
@ 2017-09-22 18:56         ` Eli Zaretskii
  2017-09-22 19:24           ` Pedro Alves
                             ` (2 more replies)
  0 siblings, 3 replies; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-22 18:56 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: gdb-patches@sourceware.org,  palves@redhat.com
> Date: Fri, 22 Sep 2017 14:00:51 -0400
> 
> On Friday, September 22 2017, Eli Zaretskii wrote:
> 
> >> +@kindex set cwd
> >> +@cindex change inferior's working directory
> >> +@item set cwd @r{[}@var{directory}@r{]}
> >> +Set the inferior's working directory to @var{directory}.  If not
> >> +given, @var{directory} uses @file{'~'}.
> >
> > I think we should document here what does "~" mean on MS-Windows,
> > especially since, when HOME is not in the environment, Gnulib's glob
> > module doesn't behave according to MS platform recommendations (which
> > say not to create files directly below %HOMEDRIVE%%HOMEPATH%).
> 
> Sure, but just to be clear, this text was strongly based on another part
> of the docs, which also mentions '~' without explaining further.
> 
> As I am totally out of the loop when it comes to Windows environments,
> I'd appreciate a suggestion for the new text.

If you write the Unix part, I can propose how to amend it to cover
Windows.  OK?

> > Does this show the original value typed by the user, or the expanded
> > value?  E.g., if the user types "set cwd ~/foo", what will "show cwd"
> > display?  If it shows the unexpanded form, does that mean the actual
> > cwd will change if, say, HOME changes?
> 
> Pedro and I had a conversation about this specific topic yesterday, and
> the decision was that the host should not do any path expansion on this
> case.  Therefore, whatever the user sets with "set cwd" is not expanded
> until the inferior starts, which means that it is the target who
> performs the expansion.

There's no contradiction between these two sides of this issue.  For
native debugging, host == target, so the host can expand.  For the
non-native debugging, you can ask the target to do the expansion and
store the result.  Either way IMO is better than expanding at run
time, because the latter makes the expansion dependent on factors
which could be out of the user control, and also requires every use
of the value to call gdb_tilde_expand, thus wasting cycles.

> > This seems to pass the unexpanded cwd directly to CreateProcess.  I
> > don't think this will work on Windows, as this directory is not
> > interpreted by any shell, so "~" will cause errors.  I think we should
> > pass this via gdb_tilde_expand, like we do in the Unix case, and I
> > also think we should mirror all the slashes in the result, just in
> > case.
> 
> Hm, you're right.  I will call "gdb_tilde_expand" here.  I'm not sure
> what you mean by "mirror all the slashes in the result".  Do you mean
> "escape the slashes"?

No, I mean convert forward slashes to backslashes.

Thanks.

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-22 18:46       ` Sergio Durigan Junior
@ 2017-09-22 19:09         ` Eli Zaretskii
  2017-09-22 20:47           ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-22 19:09 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: gdb-patches@sourceware.org,  palves@redhat.com
> Date: Fri, 22 Sep 2017 14:45:59 -0400
> 
> >> +  if (inferior_cwd != NULL)
> >> +    {
> >> +      size_t cwdlen = strlen (inferior_cwd);
> >> +
> >> +      wcwd = alloca ((cwdlen + 1) * sizeof (wchar_t));
> >> +      mbstowcs (wcwd, inferior_cwd, cwdlen + 1);
> >> +    }
> >
> > no error checking of the mbstowcs conversion?
> 
> Sorry, I am not a Windows programmer.  Other places in the code also
> don't check for errors.

Not checking for errors in these conversions can be worse on Windows
than on other platforms, because the Windows' wchar_t supports only
the BMP, so the chances of getting a conversion error are higher than
on Unix.

> I'd be happy to improve this code, but I refuse to touch a Windows
> machine so I'm doing this all this without any testing.  But please,
> feel absolutely free to point out how this code should look like.

mbstowcs returns NULL if it fails, so I suggest to throw an error in
that case.  I see no reason for anything fancier.

> >> +static void
> >> +extended_remote_set_inferior_cwd (struct remote_state *rs)
> >> +{
> >> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
> >> +    {
> >> +      const char *inferior_cwd = get_inferior_cwd ();
> >> +
> >> +      if (inferior_cwd != NULL)
> >> +	{
> >> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
> >> +					 strlen (inferior_cwd));
> >> +
> >
> > Shouldn't this do some encoding conversion, from the GDB charset to
> > the target charset, before encoding in hex?
> 
> I don't know.  There's nothing related to charset on gdb/gdbserver/, but
> then again I don't know if we've ever encountered a case that demanded
> conversions.  I can investigate this a bit more.

GDB does know about target-charset and host-charset.  I'd expect file
names that are sent to the target be in the target charset, but since
what get_inferior_cwd returns is in host charset (it was typed by the
user), I think a conversion might be in order.

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 18:56         ` Eli Zaretskii
@ 2017-09-22 19:24           ` Pedro Alves
  2017-09-22 19:41             ` Eli Zaretskii
  2017-09-22 20:24           ` Sergio Durigan Junior
  2017-09-22 20:55           ` Sergio Durigan Junior
  2 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 19:24 UTC (permalink / raw)
  To: Eli Zaretskii, Sergio Durigan Junior; +Cc: gdb-patches

On 09/22/2017 07:56 PM, Eli Zaretskii wrote:
> There's no contradiction between these two sides of this issue.  For
> native debugging, host == target, so the host can expand.  For the
> non-native debugging, you can ask the target to do the expansion and
> store the result.  

You can't, not as the actual value of the setting, because the
setting can be tweaked before GDB is even connected to a target.

I.e., you can do:

(gdb) set cwd ~  # I haven't even connected to a target yet.
                 # Where should this be expanded? 
                 # On host may be incorrect.
                 # '~' -> /home/pedro on this machine
(gdb) target extended-remote foo:9999
(gdb) start
error: /home/pedro does not exist   
# '~' is /mount/home/pedro on 'foo'
(gdb) kill
(gdb) target extended-remote bar:9999
(gdb) start
error: /home/pedro does not exist
# '~' is /nfs/home/palves on 'bar'


It may be useful to display the expanded path as extra info,
like in:

(gdb) set cwd ~foo/bar
(gdb) show cwd
The current directory is ~foo/bar (/home/foo/bar)
                                   ^^^^^^^^^^^^^

though that'd require a new remote protocol packet.

> Either way IMO is better than expanding at run
> time, because the latter makes the expansion dependent on factors
> which could be out of the user control, 

I don't see what the problem is here.

> and also requires every use
> of the value to call gdb_tilde_expand, thus wasting cycles.

I don't think that significant, compared to all the other
work / syscalls / remote protocol roundtrips that we have
to do to start a process.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 19:24           ` Pedro Alves
@ 2017-09-22 19:41             ` Eli Zaretskii
  2017-09-22 20:27               ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-22 19:41 UTC (permalink / raw)
  To: Pedro Alves; +Cc: sergiodj, gdb-patches

> Cc: gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 22 Sep 2017 20:24:40 +0100
>
> (gdb) set cwd ~  # I haven't even connected to a target yet.
>                  # Where should this be expanded? 
>                  # On host may be incorrect.
>                  # '~' -> /home/pedro on this machine

You can expand it when you connect.  The value has no use until then
anyway.

> > Either way IMO is better than expanding at run
> > time, because the latter makes the expansion dependent on factors
> > which could be out of the user control, 
> 
> I don't see what the problem is here.
> 
> > and also requires every use
> > of the value to call gdb_tilde_expand, thus wasting cycles.
> 
> I don't think that significant, compared to all the other
> work / syscalls / remote protocol roundtrips that we have
> to do to start a process.

It may be insignificant in terms of CPU usage, but it's a nuisance
that people will keep forgetting to do, as demonstrated in this case.

Anyway, I will shut up now.  I just feel that keeping this unexpanded
is wrong in the long run, that's all.

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 18:56         ` Eli Zaretskii
  2017-09-22 19:24           ` Pedro Alves
@ 2017-09-22 20:24           ` Sergio Durigan Junior
  2017-09-23  5:51             ` Eli Zaretskii
  2017-09-22 20:55           ` Sergio Durigan Junior
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 20:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Friday, September 22 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: gdb-patches@sourceware.org,  palves@redhat.com
>> Date: Fri, 22 Sep 2017 14:00:51 -0400
>> 
>> On Friday, September 22 2017, Eli Zaretskii wrote:
>> 
>> >> +@kindex set cwd
>> >> +@cindex change inferior's working directory
>> >> +@item set cwd @r{[}@var{directory}@r{]}
>> >> +Set the inferior's working directory to @var{directory}.  If not
>> >> +given, @var{directory} uses @file{'~'}.
>> >
>> > I think we should document here what does "~" mean on MS-Windows,
>> > especially since, when HOME is not in the environment, Gnulib's glob
>> > module doesn't behave according to MS platform recommendations (which
>> > say not to create files directly below %HOMEDRIVE%%HOMEPATH%).
>> 
>> Sure, but just to be clear, this text was strongly based on another part
>> of the docs, which also mentions '~' without explaining further.
>> 
>> As I am totally out of the loop when it comes to Windows environments,
>> I'd appreciate a suggestion for the new text.
>
> If you write the Unix part, I can propose how to amend it to cover
> Windows.  OK?

Deal.  Thanks.

>> > This seems to pass the unexpanded cwd directly to CreateProcess.  I
>> > don't think this will work on Windows, as this directory is not
>> > interpreted by any shell, so "~" will cause errors.  I think we should
>> > pass this via gdb_tilde_expand, like we do in the Unix case, and I
>> > also think we should mirror all the slashes in the result, just in
>> > case.
>> 
>> Hm, you're right.  I will call "gdb_tilde_expand" here.  I'm not sure
>> what you mean by "mirror all the slashes in the result".  Do you mean
>> "escape the slashes"?
>
> No, I mean convert forward slashes to backslashes.

Sorry, I wasn't familiar with the term.  Anyway, I think I can implement
that.  In fact, I think gdbserver/win32-low.c:create_process already
does that, right?

  wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
  mbstowcs (wprogram, program, strlen (program) + 1);

  for (p = wprogram; *p; ++p)
    if (L'/' == *p)
      *p = L'\\';

Anyway, I'll do the same for the inferior's cwd.

Thanks,

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

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 19:41             ` Eli Zaretskii
@ 2017-09-22 20:27               ` Sergio Durigan Junior
  2017-09-22 20:37                 ` Pedro Alves
  2017-09-23  5:52                 ` Eli Zaretskii
  0 siblings, 2 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 20:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Pedro Alves, gdb-patches

On Friday, September 22 2017, Eli Zaretskii wrote:

>> Cc: gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>
>> Date: Fri, 22 Sep 2017 20:24:40 +0100
>>
>> (gdb) set cwd ~  # I haven't even connected to a target yet.
>>                  # Where should this be expanded? 
>>                  # On host may be incorrect.
>>                  # '~' -> /home/pedro on this machine
>
> You can expand it when you connect.  The value has no use until then
> anyway.

So you're proposing that we discard the previous path expansion done
before connecting, right?  I'm just trying to understand your proposal
here, not to bikeshed or anything.

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

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 20:27               ` Sergio Durigan Junior
@ 2017-09-22 20:37                 ` Pedro Alves
  2017-09-23  5:55                   ` Eli Zaretskii
  2017-09-23  5:52                 ` Eli Zaretskii
  1 sibling, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-22 20:37 UTC (permalink / raw)
  To: Sergio Durigan Junior, Eli Zaretskii; +Cc: gdb-patches

On 09/22/2017 09:26 PM, Sergio Durigan Junior wrote:
> On Friday, September 22 2017, Eli Zaretskii wrote:
> 
>>> Cc: gdb-patches@sourceware.org
>>> From: Pedro Alves <palves@redhat.com>
>>> Date: Fri, 22 Sep 2017 20:24:40 +0100
>>>
>>> (gdb) set cwd ~  # I haven't even connected to a target yet.
>>>                  # Where should this be expanded? 
>>>                  # On host may be incorrect.
>>>                  # '~' -> /home/pedro on this machine
>>
>> You can expand it when you connect.  The value has no use until then
>> anyway.
> 
> So you're proposing that we discard the previous path expansion done
> before connecting, right?  I'm just trying to understand your proposal
> here, not to bikeshed or anything.
> 

That would mean keep both non-expanded, and expanded paths around,
which is what I was suggesting with:

 (gdb) set cwd ~foo/bar
 (gdb) show cwd
 The current directory is ~foo/bar (/home/foo/bar)
                                    ^^^^^^^^^^^^^

The (^^^) part was meant to indicate "currently expands to this".

Which means we'd add a new remote packet to request "expand 
this path and give me back the result".

(I think we could do that as a follow up extension.)

But that's not what I understood Eli suggesting.  I understood
it as gdb expanding whatever's the value set on connection.
But I don't see how that could work, because before gdb connects
to a remote target explicitly, it's as if gdb was connected to
the native target (that's how "run" works without typing
"target native" explicitly, though you can type that), so
by the time you connect to the remote target, it's already
too late, gdb has already expanded on the host, and there's
nothing left to expand.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-22 19:09         ` Eli Zaretskii
@ 2017-09-22 20:47           ` Sergio Durigan Junior
  2017-09-23  6:00             ` Eli Zaretskii
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 20:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Friday, September 22 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: gdb-patches@sourceware.org,  palves@redhat.com
>> Date: Fri, 22 Sep 2017 14:45:59 -0400
>> 
>> >> +  if (inferior_cwd != NULL)
>> >> +    {
>> >> +      size_t cwdlen = strlen (inferior_cwd);
>> >> +
>> >> +      wcwd = alloca ((cwdlen + 1) * sizeof (wchar_t));
>> >> +      mbstowcs (wcwd, inferior_cwd, cwdlen + 1);
>> >> +    }
>> >
>> > no error checking of the mbstowcs conversion?
>> 
>> Sorry, I am not a Windows programmer.  Other places in the code also
>> don't check for errors.
>
> Not checking for errors in these conversions can be worse on Windows
> than on other platforms, because the Windows' wchar_t supports only
> the BMP, so the chances of getting a conversion error are higher than
> on Unix.
>
>> I'd be happy to improve this code, but I refuse to touch a Windows
>> machine so I'm doing this all this without any testing.  But please,
>> feel absolutely free to point out how this code should look like.
>
> mbstowcs returns NULL if it fails, so I suggest to throw an error in
> that case.  I see no reason for anything fancier.

OK, that I can do :-).

>> >> +static void
>> >> +extended_remote_set_inferior_cwd (struct remote_state *rs)
>> >> +{
>> >> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
>> >> +    {
>> >> +      const char *inferior_cwd = get_inferior_cwd ();
>> >> +
>> >> +      if (inferior_cwd != NULL)
>> >> +	{
>> >> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
>> >> +					 strlen (inferior_cwd));
>> >> +
>> >
>> > Shouldn't this do some encoding conversion, from the GDB charset to
>> > the target charset, before encoding in hex?
>> 
>> I don't know.  There's nothing related to charset on gdb/gdbserver/, but
>> then again I don't know if we've ever encountered a case that demanded
>> conversions.  I can investigate this a bit more.
>
> GDB does know about target-charset and host-charset.  I'd expect file
> names that are sent to the target be in the target charset, but since
> what get_inferior_cwd returns is in host charset (it was typed by the
> user), I think a conversion might be in order.

I don't know.  We never seem to do that in other cases.  For example,
when we are starting the inferior remotely:

  static int
  extended_remote_run (const std::string &args)
  {
    ...
    if (strlen (remote_exec_file) * 2 + len >= get_remote_packet_size ())
      error (_("Remote file name too long for run packet"));
    len += 2 * bin2hex ((gdb_byte *) remote_exec_file, rs->buf + len,
                        strlen (remote_exec_file));


The "remote_exec_file" variable is also something that the user inputs
through the "set remote exec-file" command.  It doesn't seem like we
need to worry about charset conversion here.

Thanks,

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

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 18:56         ` Eli Zaretskii
  2017-09-22 19:24           ` Pedro Alves
  2017-09-22 20:24           ` Sergio Durigan Junior
@ 2017-09-22 20:55           ` Sergio Durigan Junior
  2017-09-23  6:05             ` Eli Zaretskii
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-22 20:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Friday, September 22 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: gdb-patches@sourceware.org,  palves@redhat.com
>> Date: Fri, 22 Sep 2017 14:00:51 -0400
>> 
>> On Friday, September 22 2017, Eli Zaretskii wrote:
>> 
>> >> +@kindex set cwd
>> >> +@cindex change inferior's working directory
>> >> +@item set cwd @r{[}@var{directory}@r{]}
>> >> +Set the inferior's working directory to @var{directory}.  If not
>> >> +given, @var{directory} uses @file{'~'}.
>> >
>> > I think we should document here what does "~" mean on MS-Windows,
>> > especially since, when HOME is not in the environment, Gnulib's glob
>> > module doesn't behave according to MS platform recommendations (which
>> > say not to create files directly below %HOMEDRIVE%%HOMEPATH%).
>> 
>> Sure, but just to be clear, this text was strongly based on another part
>> of the docs, which also mentions '~' without explaining further.
>> 
>> As I am totally out of the loop when it comes to Windows environments,
>> I'd appreciate a suggestion for the new text.
>
> If you write the Unix part, I can propose how to amend it to cover
> Windows.  OK?

What do you think:

@table @code
@kindex set cwd
@cindex change inferior's working directory
@item set cwd @r{[}@var{directory}@r{]}
Set the inferior's working directory to @var{directory}, which will be
@code{glob}-expanded in order to resolve tildes (@file{~}).  If no
argument has been specified, the command clears the setting and resets
it to an empty state.  This setting has no effect on @value{GDBN}'s
working directory, and it only takes effect the next time you start
the inferior.

?

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

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 20:24           ` Sergio Durigan Junior
@ 2017-09-23  5:51             ` Eli Zaretskii
  0 siblings, 0 replies; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-23  5:51 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: gdb-patches@sourceware.org,  palves@redhat.com
> Date: Fri, 22 Sep 2017 16:24:26 -0400
> 
> > No, I mean convert forward slashes to backslashes.
> 
> Sorry, I wasn't familiar with the term.

Nothing to be sorry about.

> Anyway, I think I can implement
> that.  In fact, I think gdbserver/win32-low.c:create_process already
> does that, right?
> 
>   wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
>   mbstowcs (wprogram, program, strlen (program) + 1);
> 
>   for (p = wprogram; *p; ++p)
>     if (L'/' == *p)
>       *p = L'\\';

Yes, that's it.  But this is for wchar_t strings, not for char
strings, of course.

Thanks.

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 20:27               ` Sergio Durigan Junior
  2017-09-22 20:37                 ` Pedro Alves
@ 2017-09-23  5:52                 ` Eli Zaretskii
  1 sibling, 0 replies; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-23  5:52 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: palves, gdb-patches

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: Pedro Alves <palves@redhat.com>,  gdb-patches@sourceware.org
> Date: Fri, 22 Sep 2017 16:26:56 -0400
> 
> >> (gdb) set cwd ~  # I haven't even connected to a target yet.
> >>                  # Where should this be expanded? 
> >>                  # On host may be incorrect.
> >>                  # '~' -> /home/pedro on this machine
> >
> > You can expand it when you connect.  The value has no use until then
> > anyway.
> 
> So you're proposing that we discard the previous path expansion done
> before connecting, right?

Yes, discard and replace with the actual expansion which the target
returns.

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 20:37                 ` Pedro Alves
@ 2017-09-23  5:55                   ` Eli Zaretskii
  2017-09-27 14:02                     ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-23  5:55 UTC (permalink / raw)
  To: Pedro Alves; +Cc: sergiodj, gdb-patches

> Cc: gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 22 Sep 2017 21:37:49 +0100
> 
> That would mean keep both non-expanded, and expanded paths around,
> which is what I was suggesting with:
> 
>  (gdb) set cwd ~foo/bar
>  (gdb) show cwd
>  The current directory is ~foo/bar (/home/foo/bar)
>                                     ^^^^^^^^^^^^^

Keeping both is also OK, although I don't see how it would solve the
problems Pedro mentioned earlier, and also now:

> But that's not what I understood Eli suggesting.  I understood
> it as gdb expanding whatever's the value set on connection.
> But I don't see how that could work, because before gdb connects
> to a remote target explicitly, it's as if gdb was connected to
> the native target (that's how "run" works without typing
> "target native" explicitly, though you can type that), so
> by the time you connect to the remote target, it's already
> too late, gdb has already expanded on the host, and there's
> nothing left to expand.

I don't understand this description, which is not surprising, since my
knowledge of the machinery involved in this is very superficial.

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-22 20:47           ` Sergio Durigan Junior
@ 2017-09-23  6:00             ` Eli Zaretskii
  0 siblings, 0 replies; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-23  6:00 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: gdb-patches@sourceware.org,  palves@redhat.com
> Date: Fri, 22 Sep 2017 16:47:26 -0400
> 
> > GDB does know about target-charset and host-charset.  I'd expect file
> > names that are sent to the target be in the target charset, but since
> > what get_inferior_cwd returns is in host charset (it was typed by the
> > user), I think a conversion might be in order.
> 
> I don't know.  We never seem to do that in other cases.  For example,
> when we are starting the inferior remotely:
> 
>   static int
>   extended_remote_run (const std::string &args)
>   {
>     ...
>     if (strlen (remote_exec_file) * 2 + len >= get_remote_packet_size ())
>       error (_("Remote file name too long for run packet"));
>     len += 2 * bin2hex ((gdb_byte *) remote_exec_file, rs->buf + len,
>                         strlen (remote_exec_file));
> 
> 
> The "remote_exec_file" variable is also something that the user inputs
> through the "set remote exec-file" command.  It doesn't seem like we
> need to worry about charset conversion here.

If remote_exec_file came from the target, that's okay, as it would be
already in the target charset.  But if it is typed by the user, then I
guess we indeed have such problems, when the 2 charsets are different.

Anyway, I don't want to block the changeset or hijack the discussions.
Feel free to go ahead with pushing if we generally ignore this issue
elsewhere.

Thanks.

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-22 20:55           ` Sergio Durigan Junior
@ 2017-09-23  6:05             ` Eli Zaretskii
  2017-09-23 17:01               ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-23  6:05 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches, palves

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Cc: gdb-patches@sourceware.org,  palves@redhat.com
> Date: Fri, 22 Sep 2017 16:55:35 -0400
> 
> @table @code
> @kindex set cwd
> @cindex change inferior's working directory
> @item set cwd @r{[}@var{directory}@r{]}
> Set the inferior's working directory to @var{directory}, which will be
> @code{glob}-expanded in order to resolve tildes (@file{~}).  If no
> argument has been specified, the command clears the setting and resets
> it to an empty state.  This setting has no effect on @value{GDBN}'s
> working directory, and it only takes effect the next time you start
> the inferior.

OK.  I'd suggest to append this text.

  The @file{~} in @var{directory} is a short for the @dfn{home
  directory}, usually pointed to by the @env{HOME} environment
  variable.  On MS-Windows, if @env{HOME} is not defined, @value{GDBN}
  uses the concatenation of @env{HOMEDRIVE} and @env{HOMEPATH} as
  fallback.

(This ignores the "~username" case -- is that important enough to
mention?)

Btw, what should the user do if the file name includes a literal '~'?
Escape it with a backslash?

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-23  6:05             ` Eli Zaretskii
@ 2017-09-23 17:01               ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-23 17:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, palves

On Saturday, September 23 2017, Eli Zaretskii wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Cc: gdb-patches@sourceware.org,  palves@redhat.com
>> Date: Fri, 22 Sep 2017 16:55:35 -0400
>> 
>> @table @code
>> @kindex set cwd
>> @cindex change inferior's working directory
>> @item set cwd @r{[}@var{directory}@r{]}
>> Set the inferior's working directory to @var{directory}, which will be
>> @code{glob}-expanded in order to resolve tildes (@file{~}).  If no
>> argument has been specified, the command clears the setting and resets
>> it to an empty state.  This setting has no effect on @value{GDBN}'s
>> working directory, and it only takes effect the next time you start
>> the inferior.
>
> OK.  I'd suggest to append this text.
>
>   The @file{~} in @var{directory} is a short for the @dfn{home
>   directory}, usually pointed to by the @env{HOME} environment
>   variable.  On MS-Windows, if @env{HOME} is not defined, @value{GDBN}
>   uses the concatenation of @env{HOMEDRIVE} and @env{HOMEPATH} as
>   fallback.

Thanks, added.

> (This ignores the "~username" case -- is that important enough to
> mention?)

I don't think so.  I mean, the "~username" tilde expansion is part of
the default behaviour, so I think it's OK to leave it implicit.

> Btw, what should the user do if the file name includes a literal '~'?
> Escape it with a backslash?

Yes.

Thanks,

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

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

* Re: [PATCH v2 5/5] Extend "set cwd" to work on gdbserver
  2017-09-22 18:33           ` Sergio Durigan Junior
@ 2017-09-27 13:28             ` Pedro Alves
  0 siblings, 0 replies; 131+ messages in thread
From: Pedro Alves @ 2017-09-27 13:28 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches


On 09/22/2017 07:33 PM, Sergio Durigan Junior wrote:
> On Friday, September 22 2017, Pedro Alves wrote:
> 
>> On 09/21/2017 12:49 AM, Sergio Durigan Junior wrote:
>>> On Wednesday, September 20 2017, Pedro Alves wrote:
>>
>>>> This all looks stale to me.
>>>
>>> Indeed, sorry about this mistake.  I will rewrite the entry as follows:
>>>
>>> * New features in the GDB remote stub, GDBserver
>>>
>>>   ** GDBserver is now able to enter a directory before starting an
>>>      inferior.
>>>
>>>      The user can set the desired working directory to be used by the
>>>      remote inferior on GDB, using the new "set cwd" command, which
>>>      will instruct GDB to tell GDBserver about this directory change
>>>      the next time an inferior is run.
>>
>> I still think this is talking too much in terms of implementation
>> detail, but I'll reply again to v3.
> 
> I'm curious to know why.  I'll wait for your review.

Specifically:

 "GDBserver is now able to enter a directory before starting an inferior."

This is Unix/fork specific.

 "to tell GDBserver about this directory change"

"change" seems to imply GDBserver itself changes dir.  The new inferior
never changes directory because it is started with the specified
directory in the first place.

I'll go look at v3 now.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-23  5:55                   ` Eli Zaretskii
@ 2017-09-27 14:02                     ` Pedro Alves
  2017-09-29 15:31                       ` Eli Zaretskii
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-27 14:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sergiodj, gdb-patches

On 09/23/2017 06:55 AM, Eli Zaretskii wrote:
>> Cc: gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>
>> Date: Fri, 22 Sep 2017 21:37:49 +0100
>>
>> That would mean keep both non-expanded, and expanded paths around,
>> which is what I was suggesting with:
>>
>>  (gdb) set cwd ~foo/bar
>>  (gdb) show cwd
>>  The current directory is ~foo/bar (/home/foo/bar)
>>                                     ^^^^^^^^^^^^^
> 
> Keeping both is also OK, although I don't see how it would solve the
> problems Pedro mentioned earlier, and also now:
> 
>> But that's not what I understood Eli suggesting.  I understood
>> it as gdb expanding whatever's the value set on connection.
>> But I don't see how that could work, because before gdb connects
>> to a remote target explicitly, it's as if gdb was connected to
>> the native target (that's how "run" works without typing
>> "target native" explicitly, though you can type that), so
>> by the time you connect to the remote target, it's already
>> too late, gdb has already expanded on the host, and there's
>> nothing left to expand.
> 
> I don't understand this description, which is not surprising, since my
> knowledge of the machinery involved in this is very superficial.
> 

Let's say that GDB keeps track of the desired cwd for the inferior
as a single string, like Sergio's patch is doing.  Say the user does:

 $ gdb
 (gdb) file program
 (gdb) set cwd ~

At this point, GDB it not "connected" to any target yet.  However,
if the user types "run", GDB automatically uses the native
target to run the inferior.  So typing "run" after the above is
equivalent to:

 $ gdb
 (gdb) file program
 (gdb) set cwd ~
 (gdb) target native
 (gdb) run

OK, now the question is, when to expand that '~'.  If it is
expanded immediately at "set cwd" time, then we end up expanding
it incorrectly in case the user actually wanted to debug remotely:

 $ gdb
 (gdb) file program
 (gdb) set cwd ~
 (gdb) show cwd
 /home/pedro   # local path, doesn't exists on the 'foo' machine.
 (gdb) target extended-remote foo:12345
 (gdb) show cwd
 /home/pedro   # does not exist on 'foo'

If is it instead expanded only when GDB connects to a target, then
we get this:

 $ gdb
 (gdb) file program
 (gdb) set cwd ~
 (gdb) show cwd
 ~   # not expanded yet!
 (gdb) start  # gdb expands ~ -> /home/pedro, then starts the inferior
 (gdb) show cwd
 /home/pedro  # now it's expanded.  users scratches head.
 (gdb) kill
 (gdb) target extended-remote foo:12345    # switch same inferior
                                           # to different target
 (gdb) show cwd
 /home/pedro  # whoops, lost original '~' path, and this path
              # doesn't make sense for the 'foo' machine.


If GDB does not expand the set cwd path ever except internally
when starting the inferior, then the problems shown just above
never happen.

> Keeping both is also OK, although I don't see how it would solve the
> problems Pedro mentioned earlier, and also now:

The problems I mentioned are solved by not expanding in the
first place.  Saving both original-path-as-specified-by-user and 
expanded-path (or expanding on demand when displaying the path to the
user and saving it nowhere) would then be a way to let the user
know what the path expands to on the current target, without losing the
originally set path.  Like:

 $ gdb
 (gdb) file program
 (gdb) set cwd ~
 (gdb) show cwd
 cwd is: ~   
 expands to /home/pedro on current target
 (gdb) start
 (gdb) show cwd
 cwd is: ~   
 expands to /home/pedro on current target
 (gdb) kill
 (gdb) target extended-remote foo:12345
 (gdb) show cwd
 cwd is: ~
 expands to /mnt/home/palves on current target
 (gdb) disconnect
 (gdb) target extended-remote bar:12345
 (gdb) show cwd
 cwd is: ~   
 expands to /nfs/homes/pedro on current target

I'm not sure it's worth the trouble to show the
expansions like this.  But if we make GDB _not_ expand
the "set cwd" setting's value itself, as I was proposing,
then we can always come back and improve GDB's output like
above, to inform the user what the setting expands to,
as extra info.

Hope that is clearer.

Thanks,
Pedro Alves

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-21 23:06   ` [PATCH v3 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
  2017-09-22  8:12     ` Eli Zaretskii
@ 2017-09-27 14:42     ` Pedro Alves
  2017-09-27 21:48       ` Sergio Durigan Junior
  1 sibling, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-27 14:42 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches

On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:
> This is the "natural" extension necessary for the "set cwd" command
> (and the whole "set the inferior's cwd" logic) to work on gdbserver.
> 
> The idea here is to have a new remote packet, QSetWorkingDir (name
> adopted from LLDB's extension to the RSP, as can be seen at
> <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
> which sends an hex-encoded string representing the working directory
> that gdbserver is supposed to cd into before executing the inferior.
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Unix implementation detail.

> The good thing is that since this feature is already implemented on
> nat/fork-inferior.c, all gdbserver has to do is to basically implement
> "set_inferior_cwd" and call it whenever such packet arrives.

Unix implementation detail.  That's not how it works for Windows.

> 
> Aside from that, the patch consists basically of updates to the
> testcase (making it available on remote targets) and the
> documentation.
> 
> No regressions found.
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* NEWS (Changes since GDB 8.0): Add entry about new
> 	'set-cwd-on-gdbserver' feature.
> 	(New remote packets): Add entry for QSetWorkingDir.
> 	* common/common-inferior.h (set_inferior_cwd): New prototype.
> 	* infcmd.c (set_inferior_cwd): Remove "static".
> 	(show_cwd_command): Expand text to include remote debugging.
> 	* remote.c: Add PACKET_QSetWorkingDir.
> 	(remote_protocol_features) <QSetWorkingDir>: New entry for
> 	PACKET_QSetWorkingDir.
> 	(extended_remote_set_inferior_cwd): New function.
> 	(extended_remote_create_inferior): Call
> 	"extended_remote_set_inferior_cwd".
> 	(_initialize_remote): Call "add_packet_config_cmd" for
> 	QSetWorkingDir.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* inferiors.c (set_inferior_cwd): New function.
> 	* server.c (handle_general_set): Handle QSetWorkingDir packet.
> 	(handle_query): Inform that QSetWorkingDir is supported.
> 	* win32-low.c (create_process): Pass the inferior's cwd to
> 	CreateProcess.
> 
> gdb/testsuite/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* gdb.base/set-cwd.exp: Make it available on gdbserver.
> 
> gdb/doc/ChangeLog:
> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
> 
> 	* gdb.texinfo (Starting your Program) <The working directory.>:
> 	Mention remote debugging.
> 	(Working Directory) <Your Program's Working Directory>:
> 	Likewise.
> 	(Connecting) <Remote Packet>: Add "set-working-dir"
> 	and "QSetWorkingDir" to the table.
> 	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
> 	packet.
> ---
>  gdb/NEWS                           | 12 ++++++++++++
>  gdb/common/common-inferior.h       |  3 +++
>  gdb/doc/gdb.texinfo                | 39 +++++++++++++++++++++++++++++++++++---
>  gdb/gdbserver/inferiors.c          |  9 +++++++++
>  gdb/gdbserver/server.c             | 18 +++++++++++++++++-
>  gdb/gdbserver/win32-low.c          | 15 ++++++++++++---
>  gdb/infcmd.c                       |  7 ++++---
>  gdb/remote.c                       | 37 ++++++++++++++++++++++++++++++++++++
>  gdb/testsuite/gdb.base/set-cwd.exp | 11 +++++++++--
>  9 files changed, 139 insertions(+), 12 deletions(-)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index c131713293..4ac340eeb5 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -23,6 +23,14 @@
>  
>  * New features in the GDB remote stub, GDBserver
>  
> +  ** GDBserver is now able to set the inferior's current working
> +     directory.
> +
> +     The user can set the desired working directory to be used by the
> +     remote inferior on GDB, using the new "set cwd" command, which
> +     will instruct GDB to tell GDBserver about this directory change
> +     the next time an inferior is run.
> +
>    ** New "--selftest" command line option runs some GDBserver self
>       tests.  These self tests are disabled in releases.
>  
> @@ -56,6 +64,10 @@ QEnvironmentReset
>  QStartupWithShell
>    Indicates whether the inferior must be started with a shell or not.
>  
> +QSetWorkingDir
> +  Tell GDBserver that the inferior to be started should use a specific
> +  working directory.
> +
>  * The "maintenance print c-tdesc" command now takes an optional
>    argument which is the file name of XML target description.
>  
> diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
> index 515a8c0f4e..26acddc84a 100644
> --- a/gdb/common/common-inferior.h
> +++ b/gdb/common/common-inferior.h
> @@ -34,4 +34,7 @@ extern char *get_exec_file (int err);
>     been set, then return NULL.  */
>  extern const char *get_inferior_cwd ();
>  
> +/* Set the inferior current working directory.  */
> +extern void set_inferior_cwd (const char *cwd);
> +
>  #endif /* ! COMMON_INFERIOR_H */
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 899afb92b6..7434de2a68 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
>  @item The @emph{working directory.}
>  You can set your program's working directory with the command
>  @code{set cwd}.  If you do not set any working directory with this
> -command, your program will inherit @value{GDBN}'s working directory.
> -@xref{Working Directory, ,Your Program's Working Directory}.
> +command, your program will inherit @value{GDBN}'s working directory if
> +native debugging, or @code{gdbserver}'s working directory if remote
> +debugging.  @xref{Working Directory, ,Your Program's Working
> +Directory}.

Elsewhere in the manual we say "the remote server" instead of @code{gdbserver},
because not all remote debugging uses gdbserver.

>  
>  @item The @emph{standard input and output.}
>  Your program normally uses the same device for standard input and
> @@ -2439,7 +2441,9 @@ Each time you start your program with @code{run}, the inferior will be
>  initialized with the current working directory specified by the
>  @code{set cwd} command.  If no directory has been specified by this
>  command, then the inferior will inherit @value{GDBN}'s current working
> -directory as its working directory.
> +directory as its working directory if native debugging, or it will
> +inherit @code{gdbserver}'s current working directory if remote
> +debugging.

Ditto.

>  
>  You can also change @value{GDBN}'s current working directory by using
>  the @code{cd} command.
> @@ -20993,6 +20997,10 @@ are:
>  @tab @code{QEnvironmentReset}
>  @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
>  
> +@item @code{set-working-dir}
> +@tab @code{QSetWorkingDir}
> +@tab @code{set cwd}
> +
>  @item @code{conditional-breakpoints-packet}
>  @tab @code{Z0 and Z1}
>  @tab @code{Support for target-side breakpoint condition evaluation}
> @@ -36781,6 +36789,28 @@ Reply:
>  @table @samp
>  @item OK
>  The request succeeded.
> +
> +@item QSetWorkingDir:@var{hex-value}

I think it'd be clearer to say @var{directory}, and
then say below that @var{directory} is an hex-encoded
string, like you're already doing.  That's what we do
elsewhere in the manual.

> +@anchor{QSetWorkingDir packet}
> +@cindex set working directory, remote request
> +@cindex @samp{QSetWorkingDir} packet
> +This packet is used to inform @command{gdbserver} of the intended

Ditto re. "gdbserver".

> +current working directory for programs that are going to be executed.
> +
> +The packet is composed by @var{hex-value}, an hex encoded
> +representation of the directory to be entered by @command{gdbserver}.
> +
> +This packet is only transmitted when the user issues a @code{set cwd}
> +command in @value{GDBN} (@pxref{Working Directory, ,Your Program's
> +Working Directory}).

"This packet is only transmitted when set cwd" suggests to me that
the packet is sent immediately when the user types "set cwd".

  This packet is only transmitted if the user explicitly
  specifies a directory with the @kdb{set cwd} command.

note: 
  s/when/if/.
  s/@code/@kdb

> diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
> index e78ad4faf1..326d01f4d9 100644
> --- a/gdb/gdbserver/inferiors.c
> +++ b/gdb/gdbserver/inferiors.c
> @@ -456,3 +456,12 @@ get_inferior_cwd ()
>  {
>    return current_inferior_cwd;
>  }
> +
> +/* See common/common-inferior.h.  */
> +
> +void
> +set_inferior_cwd (const char *cwd)
> +{
> +  xfree ((void *) current_inferior_cwd);
> +  current_inferior_cwd = xstrdup (cwd);
> +}
> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
> index f3eee31052..14f8a732a7 100644
> --- a/gdb/gdbserver/server.c
> +++ b/gdb/gdbserver/server.c
> @@ -869,6 +869,21 @@ handle_general_set (char *own_buf)
>        return;
>      }
>  
> +  if (startswith (own_buf, "QSetWorkingDir:"))
> +    {
> +      const char *p = own_buf + strlen ("QSetWorkingDir:");
> +      std::string path = hex2str (p);
> +
> +      set_inferior_cwd (path.c_str ());
> +
> +      if (remote_debug)
> +	debug_printf (_("[Changed current directory to %s]\n"),
> +		      path.c_str ());

Please tweak the debug string to be clear that this is the
inferior's cwd, not gdbserver's.

> +      write_ok (own_buf);
> +
> +      return;
> +    }
> +
>    /* Otherwise we didn't know what packet it was.  Say we didn't
>       understand it.  */
>    own_buf[0] = 0;
> @@ -2355,7 +2370,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
>        sprintf (own_buf,
>  	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
>  	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
> -	       "QEnvironmentReset+;QEnvironmentUnset+",
> +	       "QEnvironmentReset+;QEnvironmentUnset+;"
> +	       "QSetWorkingDir+",
>  	       PBUFSIZ - 1);
>  
>        if (target_supports_catch_syscall ())
> diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
> index cc84d15c2f..62b222d2fa 100644
> --- a/gdb/gdbserver/win32-low.c
> +++ b/gdb/gdbserver/win32-low.c
> @@ -562,10 +562,11 @@ static BOOL
>  create_process (const char *program, char *args,
>  		DWORD flags, PROCESS_INFORMATION *pi)
>  {
> +  const char *inferior_cwd = get_inferior_cwd ();
>    BOOL ret;
>  
>  #ifdef _WIN32_WCE
> -  wchar_t *p, *wprogram, *wargs;
> +  wchar_t *p, *wprogram, *wargs, *wcwd = NULL;
>    size_t argslen;
>  
>    wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
> @@ -579,6 +580,14 @@ create_process (const char *program, char *args,
>    wargs = alloca ((argslen + 1) * sizeof (wchar_t));
>    mbstowcs (wargs, args, argslen + 1);
>  
> +  if (inferior_cwd != NULL)
> +    {
> +      size_t cwdlen = strlen (inferior_cwd);
> +
> +      wcwd = alloca ((cwdlen + 1) * sizeof (wchar_t));
> +      mbstowcs (wcwd, inferior_cwd, cwdlen + 1);
> +    }
> +
>    ret = CreateProcessW (wprogram, /* image name */
>  			wargs,    /* command line */
>  			NULL,     /* security, not supported */
> @@ -586,7 +595,7 @@ create_process (const char *program, char *args,
>  			FALSE,    /* inherit handles, not supported */
>  			flags,    /* start flags */
>  			NULL,     /* environment, not supported */
> -			NULL,     /* current directory, not supported */
> +			wcwd,     /* current directory */
>  			NULL,     /* start info, not supported */
>  			pi);      /* proc info */
>  #else
> @@ -599,7 +608,7 @@ create_process (const char *program, char *args,
>  			TRUE,     /* inherit handles */
>  			flags,    /* start flags */
>  			NULL,     /* environment */
> -			NULL,     /* current directory */
> +			inferior_cwd,     /* current directory */
>  			&si,      /* start info */
>  			pi);      /* proc info */
>  #endif
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 4c5bbfdbf2..f483a33a44 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -250,9 +250,9 @@ show_args_command (struct ui_file *file, int from_tty,
>    deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
>  }
>  
> -/* Set the inferior current working directory.  */
> +/* See common/common-inferior.h.  */
>  
> -static void
> +void
>  set_inferior_cwd (const char *cwd)
>  {
>    if (*cwd == '\0')
> @@ -292,7 +292,8 @@ show_cwd_command (struct ui_file *file, int from_tty,
>      fprintf_filtered (gdb_stdout,
>  		      _("\
>  You have not set the inferior's current working directory.\n\
> -The inferior will inherit GDB's cwd.\n"));
> +The inferior will inherit GDB's cwd if native debugging, or gdbserver's\n\
> +cwd if remote debugging.\n"));

gdbserver -> remote server.

> +static void
> +extended_remote_set_inferior_cwd (struct remote_state *rs)
> +{
> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
> +    {
> +      const char *inferior_cwd = get_inferior_cwd ();
> +
> +      if (inferior_cwd != NULL)
> +	{

What happens if you do:

 set cwd foo
 run
 kill
 set cwd    # clear
 run

Do we clear the cwd on the remote end or we do we fail the
NULL check above?

> +/* See common/common-inferior.h.  */
> +
> +void
> +set_inferior_cwd (const char *cwd)
> +{
> +  xfree ((void *) current_inferior_cwd);
> +  current_inferior_cwd = xstrdup (cwd);
> +}

This always sets to non-NULL.  So is it really possible
to get back to the original clear state?  Doesn't look like it?
Do we have a test for that?


> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
> +					 strlen (inferior_cwd));
> +
> +	  xsnprintf (rs->buf, get_remote_packet_size (),
> +		     "QSetWorkingDir:%s", hexpath.c_str ());
> +	  putpkt (rs->buf);
> +	  getpkt (&rs->buf, &rs->buf_size, 0);
> +	  if (packet_ok (rs->buf,
> +			 &remote_protocol_packets[PACKET_QSetWorkingDir])
> +	      != PACKET_OK)
> +	    error (_("\
> +Remote replied unexpectedly while changing working directory: %s"),
> +		   rs->buf);

Again "changing".   Maybe say "setting the inferior's working directory"
instead.


> +	}
> +    }
> +}
> +
>  /* In the extended protocol we want to be able to do things like
>     "run" and have them basically work as expected.  So we need
>     a special create_inferior function.  We support changing the
> @@ -9686,6 +9718,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
>  
>    extended_remote_environment_support (rs);
>  
> +  extended_remote_set_inferior_cwd (rs);
> +
>    /* Now restart the remote server.  */
>    run_worked = extended_remote_run (args) != -1;
>    if (!run_worked)
> @@ -14185,6 +14219,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
>  			 "QProgramSignals", "program-signals", 0);
>  
> +  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
> +			 "QSetWorkingDir", "set-working-dir", 0);
> +
>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
>  			 "QStartupWithShell", "startup-with-shell", 0);
>  
> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
> index f2700ec44d..32458e384e 100644
> --- a/gdb/testsuite/gdb.base/set-cwd.exp
> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
> @@ -15,11 +15,18 @@
>  # You should have received a copy of the GNU General Public License
>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>  
> -if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
> -    untested "not implemented on gdbserver"
> +if { [use_gdb_stub] } {
> +    untested "not valid on native-gdbserver"

There are many other boards that set use_gdb_stub, not just
native-gdbserver.  Other testcases say:

untested "skipping tests due to use_gdb_stub"


>      return
>  }
>  
> +if { [target_info gdb_protocol] == "remote" } {
> +    load_lib gdbserver-support.exp
> +    if { [skip_gdbserver_tests] } {
> +	return
> +    }
> +}
> +

Please remember to drop this part.

>  standard_testfile
>  
>  if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
> 


Thanks,
Pedro Alves

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-27 14:42     ` Pedro Alves
@ 2017-09-27 21:48       ` Sergio Durigan Junior
  2017-09-29 14:03         ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-27 21:48 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Wednesday, September 27 2017, Pedro Alves wrote:

> On 09/21/2017 11:59 PM, Sergio Durigan Junior wrote:
>> This is the "natural" extension necessary for the "set cwd" command
>> (and the whole "set the inferior's cwd" logic) to work on gdbserver.
>> 
>> The idea here is to have a new remote packet, QSetWorkingDir (name
>> adopted from LLDB's extension to the RSP, as can be seen at
>> <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
>> which sends an hex-encoded string representing the working directory
>> that gdbserver is supposed to cd into before executing the inferior.
>        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Unix implementation detail.

Rewrote as:

  [...]
  The idea here is to have a new remote packet, QSetWorkingDir (name
  adopted from LLDB's extension to the RSP, as can be seen at
  <https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
  which sends an hex-encoded string representing the working directory
  that the remote inferior will use.

  For UNIX-like targets this feature is already implemented on
  nat/fork-inferior.c, and all gdbserver has to do is to basically
  implement "set_inferior_cwd" and call it whenever such packet arrives.
  For other targets, like Windows, it is possible to use the existing
  "get_inferior_cwd" function and do the necessary steps to make sure
  that the inferior will use the specified working directory.
  [...]

>> The good thing is that since this feature is already implemented on
>> nat/fork-inferior.c, all gdbserver has to do is to basically implement
>> "set_inferior_cwd" and call it whenever such packet arrives.
>
> Unix implementation detail.  That's not how it works for Windows.

See above.

>> 
>> Aside from that, the patch consists basically of updates to the
>> testcase (making it available on remote targets) and the
>> documentation.
>> 
>> No regressions found.
>> 
>> gdb/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* NEWS (Changes since GDB 8.0): Add entry about new
>> 	'set-cwd-on-gdbserver' feature.
>> 	(New remote packets): Add entry for QSetWorkingDir.
>> 	* common/common-inferior.h (set_inferior_cwd): New prototype.
>> 	* infcmd.c (set_inferior_cwd): Remove "static".
>> 	(show_cwd_command): Expand text to include remote debugging.
>> 	* remote.c: Add PACKET_QSetWorkingDir.
>> 	(remote_protocol_features) <QSetWorkingDir>: New entry for
>> 	PACKET_QSetWorkingDir.
>> 	(extended_remote_set_inferior_cwd): New function.
>> 	(extended_remote_create_inferior): Call
>> 	"extended_remote_set_inferior_cwd".
>> 	(_initialize_remote): Call "add_packet_config_cmd" for
>> 	QSetWorkingDir.
>> 
>> gdb/gdbserver/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* inferiors.c (set_inferior_cwd): New function.
>> 	* server.c (handle_general_set): Handle QSetWorkingDir packet.
>> 	(handle_query): Inform that QSetWorkingDir is supported.
>> 	* win32-low.c (create_process): Pass the inferior's cwd to
>> 	CreateProcess.
>> 
>> gdb/testsuite/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* gdb.base/set-cwd.exp: Make it available on gdbserver.
>> 
>> gdb/doc/ChangeLog:
>> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>> 
>> 	* gdb.texinfo (Starting your Program) <The working directory.>:
>> 	Mention remote debugging.
>> 	(Working Directory) <Your Program's Working Directory>:
>> 	Likewise.
>> 	(Connecting) <Remote Packet>: Add "set-working-dir"
>> 	and "QSetWorkingDir" to the table.
>> 	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
>> 	packet.
>> ---
>>  gdb/NEWS                           | 12 ++++++++++++
>>  gdb/common/common-inferior.h       |  3 +++
>>  gdb/doc/gdb.texinfo                | 39 +++++++++++++++++++++++++++++++++++---
>>  gdb/gdbserver/inferiors.c          |  9 +++++++++
>>  gdb/gdbserver/server.c             | 18 +++++++++++++++++-
>>  gdb/gdbserver/win32-low.c          | 15 ++++++++++++---
>>  gdb/infcmd.c                       |  7 ++++---
>>  gdb/remote.c                       | 37 ++++++++++++++++++++++++++++++++++++
>>  gdb/testsuite/gdb.base/set-cwd.exp | 11 +++++++++--
>>  9 files changed, 139 insertions(+), 12 deletions(-)
>> 
>> diff --git a/gdb/NEWS b/gdb/NEWS
>> index c131713293..4ac340eeb5 100644
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -23,6 +23,14 @@
>>  
>>  * New features in the GDB remote stub, GDBserver
>>  
>> +  ** GDBserver is now able to set the inferior's current working
>> +     directory.
>> +
>> +     The user can set the desired working directory to be used by the
>> +     remote inferior on GDB, using the new "set cwd" command, which
>> +     will instruct GDB to tell GDBserver about this directory change
>> +     the next time an inferior is run.
>> +
>>    ** New "--selftest" command line option runs some GDBserver self
>>       tests.  These self tests are disabled in releases.
>>  
>> @@ -56,6 +64,10 @@ QEnvironmentReset
>>  QStartupWithShell
>>    Indicates whether the inferior must be started with a shell or not.
>>  
>> +QSetWorkingDir
>> +  Tell GDBserver that the inferior to be started should use a specific
>> +  working directory.
>> +
>>  * The "maintenance print c-tdesc" command now takes an optional
>>    argument which is the file name of XML target description.
>>  
>> diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
>> index 515a8c0f4e..26acddc84a 100644
>> --- a/gdb/common/common-inferior.h
>> +++ b/gdb/common/common-inferior.h
>> @@ -34,4 +34,7 @@ extern char *get_exec_file (int err);
>>     been set, then return NULL.  */
>>  extern const char *get_inferior_cwd ();
>>  
>> +/* Set the inferior current working directory.  */
>> +extern void set_inferior_cwd (const char *cwd);
>> +
>>  #endif /* ! COMMON_INFERIOR_H */
>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
>> index 899afb92b6..7434de2a68 100644
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
>>  @item The @emph{working directory.}
>>  You can set your program's working directory with the command
>>  @code{set cwd}.  If you do not set any working directory with this
>> -command, your program will inherit @value{GDBN}'s working directory.
>> -@xref{Working Directory, ,Your Program's Working Directory}.
>> +command, your program will inherit @value{GDBN}'s working directory if
>> +native debugging, or @code{gdbserver}'s working directory if remote
>> +debugging.  @xref{Working Directory, ,Your Program's Working
>> +Directory}.
>
> Elsewhere in the manual we say "the remote server" instead of @code{gdbserver},
> because not all remote debugging uses gdbserver.

Updated.

>>  
>>  @item The @emph{standard input and output.}
>>  Your program normally uses the same device for standard input and
>> @@ -2439,7 +2441,9 @@ Each time you start your program with @code{run}, the inferior will be
>>  initialized with the current working directory specified by the
>>  @code{set cwd} command.  If no directory has been specified by this
>>  command, then the inferior will inherit @value{GDBN}'s current working
>> -directory as its working directory.
>> +directory as its working directory if native debugging, or it will
>> +inherit @code{gdbserver}'s current working directory if remote
>> +debugging.
>
> Ditto.

Updated.

>>  
>>  You can also change @value{GDBN}'s current working directory by using
>>  the @code{cd} command.
>> @@ -20993,6 +20997,10 @@ are:
>>  @tab @code{QEnvironmentReset}
>>  @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
>>  
>> +@item @code{set-working-dir}
>> +@tab @code{QSetWorkingDir}
>> +@tab @code{set cwd}
>> +
>>  @item @code{conditional-breakpoints-packet}
>>  @tab @code{Z0 and Z1}
>>  @tab @code{Support for target-side breakpoint condition evaluation}
>> @@ -36781,6 +36789,28 @@ Reply:
>>  @table @samp
>>  @item OK
>>  The request succeeded.
>> +
>> +@item QSetWorkingDir:@var{hex-value}
>
> I think it'd be clearer to say @var{directory}, and
> then say below that @var{directory} is an hex-encoded
> string, like you're already doing.  That's what we do
> elsewhere in the manual.

Sure.  Updated

>
>> +@anchor{QSetWorkingDir packet}
>> +@cindex set working directory, remote request
>> +@cindex @samp{QSetWorkingDir} packet
>> +This packet is used to inform @command{gdbserver} of the intended
>
> Ditto re. "gdbserver".

Updated.

>> +current working directory for programs that are going to be executed.
>> +
>> +The packet is composed by @var{hex-value}, an hex encoded
>> +representation of the directory to be entered by @command{gdbserver}.
>> +
>> +This packet is only transmitted when the user issues a @code{set cwd}
>> +command in @value{GDBN} (@pxref{Working Directory, ,Your Program's
>> +Working Directory}).
>
> "This packet is only transmitted when set cwd" suggests to me that
> the packet is sent immediately when the user types "set cwd".
>
>   This packet is only transmitted if the user explicitly
>   specifies a directory with the @kdb{set cwd} command.

Rewrote it.

> note: 
>   s/when/if/.
>   s/@code/@kdb

It's @kbd (from "keyboard").  But I know, our muscle memory wants us to
type "db" :-P.

Even though I slightly disagree here (commands are not keybindings), I
found that this is indeed what GDB uses.  Anyway, using @kbd now.

>> diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
>> index e78ad4faf1..326d01f4d9 100644
>> --- a/gdb/gdbserver/inferiors.c
>> +++ b/gdb/gdbserver/inferiors.c
>> @@ -456,3 +456,12 @@ get_inferior_cwd ()
>>  {
>>    return current_inferior_cwd;
>>  }
>> +
>> +/* See common/common-inferior.h.  */
>> +
>> +void
>> +set_inferior_cwd (const char *cwd)
>> +{
>> +  xfree ((void *) current_inferior_cwd);
>> +  current_inferior_cwd = xstrdup (cwd);
>> +}
>> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
>> index f3eee31052..14f8a732a7 100644
>> --- a/gdb/gdbserver/server.c
>> +++ b/gdb/gdbserver/server.c
>> @@ -869,6 +869,21 @@ handle_general_set (char *own_buf)
>>        return;
>>      }
>>  
>> +  if (startswith (own_buf, "QSetWorkingDir:"))
>> +    {
>> +      const char *p = own_buf + strlen ("QSetWorkingDir:");
>> +      std::string path = hex2str (p);
>> +
>> +      set_inferior_cwd (path.c_str ());
>> +
>> +      if (remote_debug)
>> +	debug_printf (_("[Changed current directory to %s]\n"),
>> +		      path.c_str ());
>
> Please tweak the debug string to be clear that this is the
> inferior's cwd, not gdbserver's.

OK, changed to:

debug_printf (_("[Set the inferior's current directory to %s]\n"),
	      path.c_str ());

>> +      write_ok (own_buf);
>> +
>> +      return;
>> +    }
>> +
>>    /* Otherwise we didn't know what packet it was.  Say we didn't
>>       understand it.  */
>>    own_buf[0] = 0;
>> @@ -2355,7 +2370,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
>>        sprintf (own_buf,
>>  	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
>>  	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
>> -	       "QEnvironmentReset+;QEnvironmentUnset+",
>> +	       "QEnvironmentReset+;QEnvironmentUnset+;"
>> +	       "QSetWorkingDir+",
>>  	       PBUFSIZ - 1);
>>  
>>        if (target_supports_catch_syscall ())
>> diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
>> index cc84d15c2f..62b222d2fa 100644
>> --- a/gdb/gdbserver/win32-low.c
>> +++ b/gdb/gdbserver/win32-low.c
>> @@ -562,10 +562,11 @@ static BOOL
>>  create_process (const char *program, char *args,
>>  		DWORD flags, PROCESS_INFORMATION *pi)
>>  {
>> +  const char *inferior_cwd = get_inferior_cwd ();
>>    BOOL ret;
>>  
>>  #ifdef _WIN32_WCE
>> -  wchar_t *p, *wprogram, *wargs;
>> +  wchar_t *p, *wprogram, *wargs, *wcwd = NULL;
>>    size_t argslen;
>>  
>>    wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
>> @@ -579,6 +580,14 @@ create_process (const char *program, char *args,
>>    wargs = alloca ((argslen + 1) * sizeof (wchar_t));
>>    mbstowcs (wargs, args, argslen + 1);
>>  
>> +  if (inferior_cwd != NULL)
>> +    {
>> +      size_t cwdlen = strlen (inferior_cwd);
>> +
>> +      wcwd = alloca ((cwdlen + 1) * sizeof (wchar_t));
>> +      mbstowcs (wcwd, inferior_cwd, cwdlen + 1);
>> +    }
>> +
>>    ret = CreateProcessW (wprogram, /* image name */
>>  			wargs,    /* command line */
>>  			NULL,     /* security, not supported */
>> @@ -586,7 +595,7 @@ create_process (const char *program, char *args,
>>  			FALSE,    /* inherit handles, not supported */
>>  			flags,    /* start flags */
>>  			NULL,     /* environment, not supported */
>> -			NULL,     /* current directory, not supported */
>> +			wcwd,     /* current directory */
>>  			NULL,     /* start info, not supported */
>>  			pi);      /* proc info */
>>  #else
>> @@ -599,7 +608,7 @@ create_process (const char *program, char *args,
>>  			TRUE,     /* inherit handles */
>>  			flags,    /* start flags */
>>  			NULL,     /* environment */
>> -			NULL,     /* current directory */
>> +			inferior_cwd,     /* current directory */
>>  			&si,      /* start info */
>>  			pi);      /* proc info */
>>  #endif
>> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
>> index 4c5bbfdbf2..f483a33a44 100644
>> --- a/gdb/infcmd.c
>> +++ b/gdb/infcmd.c
>> @@ -250,9 +250,9 @@ show_args_command (struct ui_file *file, int from_tty,
>>    deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
>>  }
>>  
>> -/* Set the inferior current working directory.  */
>> +/* See common/common-inferior.h.  */
>>  
>> -static void
>> +void
>>  set_inferior_cwd (const char *cwd)
>>  {
>>    if (*cwd == '\0')
>> @@ -292,7 +292,8 @@ show_cwd_command (struct ui_file *file, int from_tty,
>>      fprintf_filtered (gdb_stdout,
>>  		      _("\
>>  You have not set the inferior's current working directory.\n\
>> -The inferior will inherit GDB's cwd.\n"));
>> +The inferior will inherit GDB's cwd if native debugging, or gdbserver's\n\
>> +cwd if remote debugging.\n"));
>
> gdbserver -> remote server.

Updated.

>> +static void
>> +extended_remote_set_inferior_cwd (struct remote_state *rs)
>> +{
>> +  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
>> +    {
>> +      const char *inferior_cwd = get_inferior_cwd ();
>> +
>> +      if (inferior_cwd != NULL)
>> +	{
>
> What happens if you do:
>
>  set cwd foo
>  run
>  kill
>  set cwd    # clear
>  run
>
> Do we clear the cwd on the remote end or we do we fail the
> NULL check above?

In this specific version of the patch, which does not have the
implementation to clear out the inferior's cwd, the empty "set cwd"
would actually make the "~" as the current directory for the inferior.
But in the next version (which I'll send), when "inferior_cwd == NULL" I
will send an empty QSetWorkingDir packet (which means I'll extend the
QSetWorkingDir packet to accept empty arguments), and that will clear
things up in the server side.

>
>> +/* See common/common-inferior.h.  */
>> +
>> +void
>> +set_inferior_cwd (const char *cwd)
>> +{
>> +  xfree ((void *) current_inferior_cwd);
>> +  current_inferior_cwd = xstrdup (cwd);
>> +}
>
> This always sets to non-NULL.  So is it really possible
> to get back to the original clear state?  Doesn't look like it?
> Do we have a test for that?

Not in this specific version, no.  This was something decided *after* I
had sent this version.  In my local tree I have code implementing the
"clear up" behaviour, and I'll add a test for that as well.

>
>
>> +	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
>> +					 strlen (inferior_cwd));
>> +
>> +	  xsnprintf (rs->buf, get_remote_packet_size (),
>> +		     "QSetWorkingDir:%s", hexpath.c_str ());
>> +	  putpkt (rs->buf);
>> +	  getpkt (&rs->buf, &rs->buf_size, 0);
>> +	  if (packet_ok (rs->buf,
>> +			 &remote_protocol_packets[PACKET_QSetWorkingDir])
>> +	      != PACKET_OK)
>> +	    error (_("\
>> +Remote replied unexpectedly while changing working directory: %s"),
>> +		   rs->buf);
>
> Again "changing".   Maybe say "setting the inferior's working directory"
> instead.

OK.

>
>
>> +	}
>> +    }
>> +}
>> +
>>  /* In the extended protocol we want to be able to do things like
>>     "run" and have them basically work as expected.  So we need
>>     a special create_inferior function.  We support changing the
>> @@ -9686,6 +9718,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
>>  
>>    extended_remote_environment_support (rs);
>>  
>> +  extended_remote_set_inferior_cwd (rs);
>> +
>>    /* Now restart the remote server.  */
>>    run_worked = extended_remote_run (args) != -1;
>>    if (!run_worked)
>> @@ -14185,6 +14219,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
>>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
>>  			 "QProgramSignals", "program-signals", 0);
>>  
>> +  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
>> +			 "QSetWorkingDir", "set-working-dir", 0);
>> +
>>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
>>  			 "QStartupWithShell", "startup-with-shell", 0);
>>  
>> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
>> index f2700ec44d..32458e384e 100644
>> --- a/gdb/testsuite/gdb.base/set-cwd.exp
>> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
>> @@ -15,11 +15,18 @@
>>  # You should have received a copy of the GNU General Public License
>>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>  
>> -if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
>> -    untested "not implemented on gdbserver"
>> +if { [use_gdb_stub] } {
>> +    untested "not valid on native-gdbserver"
>
> There are many other boards that set use_gdb_stub, not just
> native-gdbserver.  Other testcases say:
>
> untested "skipping tests due to use_gdb_stub"

Hm, OK.

Does this look correct now, though?

>>      return
>>  }
>>  
>> +if { [target_info gdb_protocol] == "remote" } {
>> +    load_lib gdbserver-support.exp
>> +    if { [skip_gdbserver_tests] } {
>> +	return
>> +    }
>> +}
>> +
>
> Please remember to drop this part.

Already did.  Thanks.

>>  standard_testfile
>>  
>>  if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
>> 
>
>
> Thanks,
> Pedro Alves

Thanks,

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

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

* [PATCH v4 0/3] New "set cwd" command
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
                   ` (7 preceding siblings ...)
  2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
@ 2017-09-28  4:10 ` Sergio Durigan Junior
  2017-09-28  4:10   ` [PATCH v4 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
                     ` (2 more replies)
  2017-09-29 22:58 ` [PATCH v5 0/3] New "set cwd" command Sergio Durigan Junior
  9 siblings, 3 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-28  4:10 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii

v1: https://sourceware.org/ml/gdb-patches/2017-09/msg00321.html
v2: https://sourceware.org/ml/gdb-patches/2017-09/msg00458.html
v3: https://sourceware.org/ml/gdb-patches/2017-09/msg00658.html

Changes from v3:

* Patch #1 (former patch #3):

  - Do not s/tilde_expand/gdb_tilde_expand/ on
    gdb/cli/cli-cmds.c:cd_command (leave as a possible cleanup for
    later patches).

  - Use only GLOB_TILDE_CHECK (and not "GLOB_TILDE | GLOB_TILDE_CHECK
    | GLOB_ONLYDIR") when calling "glob", making "gdb_tilde_expand" to
    behave as a general-purpose "tilde-expander" (i.e., don't deal only
    with dirs).

* Patch #2 (former patch #4):

  - Rewrite several parts of the documentation (NEWS, gdb.texinfo,
    commit log, etc.) in order to remove target-dependent sentences
    explaining how GDB deals with the inferior's cwd.

  - Expand documentation to explain what "~" means on Windows.

  - Improve Windows-related code to perform wide-char conversion when
    needed, and mirror slashes of paths provided by the user.  Call
    "gdb_tilde_expand" before passing the path to CreateProcess.

  - Make "set cwd" (without arguments) actually clean up the
    previously set inferior's cwd (i.e., reset it to an empty value),
    instead of defaulting to "~" as "cd" does.  Adjust testsuite and
    code accordingly.

* Patch #3 (former patch #5):

  - Rewrite several parts of the documentation (NEWS, gdb.texinfo,
    commit log, etc.) in order to remove target-dependent sentences
    explaining how GDB deals with the inferior's cwd.

  - s/gdbserver/remote server/ in the manual.

  - s/@code/@kbd/ for writing commands in the manual.

  - Improve debug string on gdb/gdbserver/server.c:handle_general_set
    when dealing with "QSetWorkingDir".

  - Implement the "set cwd"-without-arguments cleanup on gdbserver, by
    making "QSetWorkingDir" accept an empty argument.  This way, we'll
    always send the packet to the remote stub, even when the user
    hasn't set any cwd for the inferior.

  - Improved debug string on gdb/remote.c's code to handle
    "QSetWorkingDir".

  - Improved message when calling "untested" because "[use_gdb_stub]"
    is true.



This patch series is a followup of the discussion that happened at:

  https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html

It implements a new GDB command, "set cwd", which is used to set the
current working directory of the inferior that will be started.  This
command works for both native and remote debugging scenarios.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.

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

* [PATCH v4 1/3] Introduce gdb_tilde_expand
  2017-09-28  4:10 ` [PATCH v4 0/3] New "set cwd" command Sergio Durigan Junior
@ 2017-09-28  4:10   ` Sergio Durigan Junior
  2017-09-29 14:08     ` Pedro Alves
  2017-09-28  4:11   ` [PATCH v4 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
  2017-09-28  4:11   ` [PATCH v4 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-28  4:10 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii, Sergio Durigan Junior

Currently, whenever we want to handle paths provided by the user and
perform tilde expansion on GDB, we rely on "tilde_expand", which comes
from readline.  This was enough for our use cases so far, but the
situation will change when we start dealing with paths on gdbserver as
well, which is what the next patches implement.

Unfortunately it is not possible to use "tilde_expand" in this case
because gdbserver doesn't use readline.  For that reason I decided to
implement a new "gdb_tilde_expand" function, which is basically a
wrapper for "glob" and its GNU extension, GLOB_TILDE_CHECK.  With the
import of the "glob" module from gnulib, this is a no-brainer.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add gdb_tilde_expand.c.
	(HFILES_NO_SRCDIR): Add gdb_tilde_expand.h.
	(COMMON_OBS): Add gdb_tilde_expand.o.
	* common/gdb_tilde_expand.c: New file.
	* common/gdb_tilde_expand.h: Likewise.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add $(srcdir)/common/gdb_tilde_expand.c.
	(OBS): Add gdb_tilde_expand.o.
---
 gdb/Makefile.in               |  3 ++
 gdb/common/gdb_tilde_expand.c | 82 +++++++++++++++++++++++++++++++++++++++++++
 gdb/common/gdb_tilde_expand.h | 27 ++++++++++++++
 gdb/gdbserver/Makefile.in     |  2 ++
 4 files changed, 114 insertions(+)
 create mode 100644 gdb/common/gdb_tilde_expand.c
 create mode 100644 gdb/common/gdb_tilde_expand.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9004b350e4..d60b5d984b 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1246,6 +1246,7 @@ SFILES = \
 	common/filestuff.c \
 	common/format.c \
 	common/job-control.c \
+	common/gdb_tilde_expand.c \
 	common/gdb_vecs.c \
 	common/new-op.c \
 	common/print-utils.c \
@@ -1530,6 +1531,7 @@ HFILES_NO_SRCDIR = \
 	common/fileio.h \
 	common/format.h \
 	common/gdb_assert.h \
+	common/gdb_tilde_expand.h \
 	common/gdb_locale.h \
 	common/gdb_setjmp.h \
 	common/gdb_signals.h \
@@ -1735,6 +1737,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	frame-unwind.o \
 	gcore.o \
 	gdb_bfd.o \
+	gdb_tilde_expand.o \
 	gdb-dlfcn.o \
 	gdb_obstack.o \
 	gdb_regex.o \
diff --git a/gdb/common/gdb_tilde_expand.c b/gdb/common/gdb_tilde_expand.c
new file mode 100644
index 0000000000..8dd94239f9
--- /dev/null
+++ b/gdb/common/gdb_tilde_expand.c
@@ -0,0 +1,82 @@
+/* Perform tilde expansion on paths for GDB and gdbserver.
+
+   Copyright (C) 2017 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 "gdb_tilde_expand.h"
+#include <glob.h>
+
+/* RAII-style class wrapping "glob".  */
+
+class gdb_glob
+{
+public:
+  /* Construct a "gdb_glob" object by calling "glob" with the provided
+     parameters.  This function can throw if "glob" fails.  */
+  gdb_glob (const char *pattern, int flags,
+	    int (*errfunc) (const char *epath, int eerrno))
+  {
+    int ret = glob (pattern, flags, errfunc, &m_glob);
+
+    if (ret != 0)
+      {
+	if (ret == GLOB_NOMATCH)
+	  error (_("Could not find a match for '%s'."), pattern);
+	else
+	  error (_("glob could not process pattern '%s'."),
+		 pattern);
+      }
+  }
+
+  /* Destroy the object and free M_GLOB.  */
+  ~gdb_glob ()
+  {
+    globfree (&m_glob);
+  }
+
+  /* Return the GL_PATHC component of M_GLOB.  */
+  int pathc () const
+  {
+    return m_glob.gl_pathc;
+  }
+
+  /* Return the GL_PATHV component of M_GLOB.  */
+  char **pathv () const
+  {
+    return m_glob.gl_pathv;
+  }
+
+private:
+  /* The actual glob object we're dealing with.  */
+  glob_t m_glob;
+};
+
+/* See common/gdb_tilde_expand.h.  */
+
+std::string
+gdb_tilde_expand (const char *dir)
+{
+  gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
+
+  gdb_assert (glob.pathc () > 0);
+  /* "glob" may return more than one match to the path provided by the
+     user, but we are only interested in the first match.  */
+  std::string expanded_dir = glob.pathv ()[0];
+
+  return expanded_dir;
+}
diff --git a/gdb/common/gdb_tilde_expand.h b/gdb/common/gdb_tilde_expand.h
new file mode 100644
index 0000000000..a5d923d66b
--- /dev/null
+++ b/gdb/common/gdb_tilde_expand.h
@@ -0,0 +1,27 @@
+/* Perform tilde expansion on paths for GDB and gdbserver.
+
+   Copyright (C) 2017 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 HAVE_GDB_TILDE_EXPAND_H
+#define HAVE_GDB_TILDE_EXPAND_H
+
+/* Perform path expansion (i.e., tilde expansion) on DIR, and return
+   the full path.  */
+extern std::string gdb_tilde_expand (const char *dir);
+
+#endif /* ! HAVE_GDB_TILDE_EXPAND_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 1bbe515629..6c931ba952 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -205,6 +205,7 @@ SFILES = \
 	$(srcdir)/common/fileio.c \
 	$(srcdir)/common/filestuff.c \
 	$(srcdir)/common/job-control.c \
+	$(srcdir)/common/gdb_tilde_expand.c \
 	$(srcdir)/common/gdb_vecs.c \
 	$(srcdir)/common/new-op.c \
 	$(srcdir)/common/print-utils.c \
@@ -247,6 +248,7 @@ OBS = \
 	fileio.o \
 	filestuff.o \
 	format.o \
+	gdb_tilde_expand.o \
 	gdb_vecs.o \
 	hostio.o \
 	inferiors.o \
-- 
2.13.3

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

* [PATCH v4 3/3] Extend "set cwd" to work on gdbserver
  2017-09-28  4:10 ` [PATCH v4 0/3] New "set cwd" command Sergio Durigan Junior
  2017-09-28  4:10   ` [PATCH v4 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
@ 2017-09-28  4:11   ` Sergio Durigan Junior
  2017-09-29 15:21     ` Pedro Alves
  2017-09-28  4:11   ` [PATCH v4 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-28  4:11 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii, Sergio Durigan Junior

This is the "natural" extension necessary for the "set cwd" command
(and the whole "set the inferior's cwd" logic) to work on gdbserver.

The idea here is to have a new remote packet, QSetWorkingDir (name
adopted from LLDB's extension to the RSP, as can be seen at
<https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
which sends an hex-encoded string representing the working directory
that the remote inferior will use.  There is a slight difference from
the packet proposed by LLDB: GDB's version will accept empty
arguments, meaning that the user wants to clear the previously set
working directory for the inferior (i.e., "set cwd" without arguments
on GDB).

For UNIX-like targets this feature is already implemented on
nat/fork-inferior.c, and all gdbserver has to do is to basically
implement "set_inferior_cwd" and call it whenever such packet arrives.
For other targets, like Windows, it is possible to use the existing
"get_inferior_cwd" function and do the necessary steps to make sure
that the inferior will use the specified working directory.

Aside from that, the patch consists basically of updates to the
testcase (making it available on remote targets) and the
documentation.

No regressions found.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (Changes since GDB 8.0): Add entry about new
	'set-cwd-on-gdbserver' feature.
	(New remote packets): Add entry for QSetWorkingDir.
	* common/common-inferior.h (set_inferior_cwd): New prototype.
	* infcmd.c (set_inferior_cwd): Remove "static".
	(show_cwd_command): Expand text to include remote debugging.
	* remote.c: Add PACKET_QSetWorkingDir.
	(remote_protocol_features) <QSetWorkingDir>: New entry for
	PACKET_QSetWorkingDir.
	(extended_remote_set_inferior_cwd): New function.
	(extended_remote_create_inferior): Call
	"extended_remote_set_inferior_cwd".
	(_initialize_remote): Call "add_packet_config_cmd" for
	QSetWorkingDir.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (set_inferior_cwd): New function.
	* server.c (handle_general_set): Handle QSetWorkingDir packet.
	(handle_query): Inform that QSetWorkingDir is supported.
	* win32-low.c (create_process): Pass the inferior's cwd to
	CreateProcess.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.exp: Make it available on
	native-extended-gdbserver.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention remote debugging.
	(Working Directory) <Your Program's Working Directory>:
	Likewise.
	(Connecting) <Remote Packet>: Add "set-working-dir"
	and "QSetWorkingDir" to the table.
	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
	packet.
---
 gdb/NEWS                           | 12 +++++++++++
 gdb/common/common-inferior.h       |  4 ++++
 gdb/doc/gdb.texinfo                | 43 +++++++++++++++++++++++++++++++++++---
 gdb/gdbserver/inferiors.c          | 12 +++++++++++
 gdb/gdbserver/server.c             | 30 +++++++++++++++++++++++++-
 gdb/gdbserver/win32-low.c          | 22 ++++++++++++++++---
 gdb/infcmd.c                       |  8 +++----
 gdb/remote.c                       | 43 ++++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/set-cwd.exp |  4 ++--
 9 files changed, 165 insertions(+), 13 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index fcf454833f..d68b3464e7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -26,6 +26,14 @@
 
 * New features in the GDB remote stub, GDBserver
 
+  ** GDBserver is now able to set the inferior's current working
+     directory.
+
+     The user can set the desired working directory to be used by the
+     remote inferior on GDB, using the new "set cwd" command, which
+     will instruct GDB to tell GDBserver about this directory change
+     the next time an inferior is run.
+
   ** New "--selftest" command line option runs some GDBserver self
      tests.  These self tests are disabled in releases.
 
@@ -59,6 +67,10 @@ QEnvironmentReset
 QStartupWithShell
   Indicates whether the inferior must be started with a shell or not.
 
+QSetWorkingDir
+  Tell GDBserver that the inferior to be started should use a specific
+  working directory.
+
 * The "maintenance print c-tdesc" command now takes an optional
   argument which is the file name of XML target description.
 
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 515a8c0f4e..3dcfda3e7b 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -34,4 +34,8 @@ extern char *get_exec_file (int err);
    been set, then return NULL.  */
 extern const char *get_inferior_cwd ();
 
+/* Set the inferior current working directory.  If CWD is NULL, unset
+   the directory.  */
+extern void set_inferior_cwd (const char *cwd);
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0d059603cf..2d041f9819 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
 @item The @emph{working directory.}
 You can set your program's working directory with the command
 @kbd{set cwd}.  If you do not set any working directory with this
-command, your program will inherit @value{GDBN}'s working directory.
-@xref{Working Directory, ,Your Program's Working Directory}.
+command, your program will inherit @value{GDBN}'s working directory if
+native debugging, or the remote server's working directory if remote
+debugging.  @xref{Working Directory, ,Your Program's Working
+Directory}.
 
 @item The @emph{standard input and output.}
 Your program normally uses the same device for standard input and
@@ -2439,7 +2441,9 @@ Each time you start your program with @code{run}, the inferior will be
 initialized with the current working directory specified by the
 @kbd{set cwd} command.  If no directory has been specified by this
 command, then the inferior will inherit @value{GDBN}'s current working
-directory as its working directory.
+directory as its working directory if native debugging, or it will
+inherit the remote server's current working directory if remote
+debugging.
 
 You can also change @value{GDBN}'s current working directory by using
 the @code{cd} command.
@@ -20999,6 +21003,10 @@ are:
 @tab @code{QEnvironmentReset}
 @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
 
+@item @code{set-working-dir}
+@tab @code{QSetWorkingDir}
+@tab @code{set cwd}
+
 @item @code{conditional-breakpoints-packet}
 @tab @code{Z0 and Z1}
 @tab @code{Support for target-side breakpoint condition evaluation}
@@ -36856,6 +36864,35 @@ by supplying an appropriate @samp{qSupported} response
 actually support passing environment variables to the starting
 inferior.
 
+@item QSetWorkingDir:@r{[}@var{directory}@r{]}
+@anchor{QSetWorkingDir packet}
+@cindex set working directory, remote request
+@cindex @samp{QSetWorkingDir} packet
+This packet is used to inform the remote server of the intended
+current working directory for programs that are going to be executed.
+
+The packet is composed by @var{directory}, an hex encoded
+representation of the directory that the remote inferior will use as
+its current working directory.  If @var{directory} is an empty string,
+the remote server should reset the inferior's current working
+directory to its original, empty value.
+
+This packet is always transmitted when the inferior is run.  If the
+user has not explcitly specified a directory with the @kbd{set cwd}
+command, then an empty packet will be sent to the remote server, which
+will have no effect.  Otherwise, the specified inferior's working
+directory will be transmitted (@pxref{Working Directory, ,Your
+Program's Working Directory}).
+
+This packet is only available in extended mode (@pxref{extended
+mode}).
+
+Reply:
+@table @samp
+@item OK
+The request succeeded.
+@end table
+
 @item qfThreadInfo
 @itemx qsThreadInfo
 @cindex list active threads, remote request
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 57d9956ebb..154c167f4c 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -456,3 +456,15 @@ get_inferior_cwd ()
 {
   return current_inferior_cwd;
 }
+
+/* See common/common-inferior.h.  */
+
+void
+set_inferior_cwd (const char *cwd)
+{
+  xfree ((void *) current_inferior_cwd);
+  if (cwd != NULL)
+    current_inferior_cwd = xstrdup (cwd);
+  else
+    current_inferior_cwd = NULL;
+}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index f3eee31052..8e3d30fb53 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -869,6 +869,33 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QSetWorkingDir:"))
+    {
+      const char *p = own_buf + strlen ("QSetWorkingDir:");
+
+      if (*p != '\0')
+	{
+	  std::string path = hex2str (p);
+
+	  set_inferior_cwd (path.c_str ());
+
+	  if (remote_debug)
+	    debug_printf (_("[Set the inferior's current directory to %s]\n"),
+			  path.c_str ());
+	}
+      else
+	{
+	  set_inferior_cwd (NULL);
+
+	  if (remote_debug)
+	    debug_printf (_("\
+[Unset the inferior's current directory; will use gdbserver's cwd]\n"));
+	}
+      write_ok (own_buf);
+
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -2355,7 +2382,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       sprintf (own_buf,
 	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
 	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
-	       "QEnvironmentReset+;QEnvironmentUnset+",
+	       "QEnvironmentReset+;QEnvironmentUnset+;"
+	       "QSetWorkingDir+",
 	       PBUFSIZ - 1);
 
       if (target_supports_catch_syscall ())
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index cc84d15c2f..c11926f7c6 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -32,6 +32,7 @@
 #include <tlhelp32.h>
 #include <psapi.h>
 #include <process.h>
+#include "gdb_tilde_expand.h"
 
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>
@@ -562,10 +563,12 @@ static BOOL
 create_process (const char *program, char *args,
 		DWORD flags, PROCESS_INFORMATION *pi)
 {
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd = gdb_tilde_expand (inferior_cwd);
   BOOL ret;
 
 #ifdef _WIN32_WCE
-  wchar_t *p, *wprogram, *wargs;
+  wchar_t *p, *wprogram, *wargs, *wcwd = NULL;
   size_t argslen;
 
   wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
@@ -579,6 +582,19 @@ create_process (const char *program, char *args,
   wargs = alloca ((argslen + 1) * sizeof (wchar_t));
   mbstowcs (wargs, args, argslen + 1);
 
+  if (inferior_cwd != NULL)
+    {
+      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+		    '/', '\\');
+      wcwd = alloca ((expanded_infcwd.size () + 1) * sizeof (wchar_t));
+      if (mbstowcs (wcwd, expanded_infcwd.c_str (),
+		    expanded_infcwd.size () + 1) == NULL)
+	{
+	  error (_("\
+Could not convert the expanded inferior cwd to wide-char."));
+	}
+    }
+
   ret = CreateProcessW (wprogram, /* image name */
 			wargs,    /* command line */
 			NULL,     /* security, not supported */
@@ -586,7 +602,7 @@ create_process (const char *program, char *args,
 			FALSE,    /* inherit handles, not supported */
 			flags,    /* start flags */
 			NULL,     /* environment, not supported */
-			NULL,     /* current directory, not supported */
+			wcwd,     /* current directory */
 			NULL,     /* start info, not supported */
 			pi);      /* proc info */
 #else
@@ -599,7 +615,7 @@ create_process (const char *program, char *args,
 			TRUE,     /* inherit handles */
 			flags,    /* start flags */
 			NULL,     /* environment */
-			NULL,     /* current directory */
+			expanded_infcwd.c_str (), /* current directory */
 			&si,      /* start info */
 			pi);      /* proc info */
 #endif
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index dbdf273ca5..187c71f344 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -242,10 +242,9 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
-/* Set the inferior current working directory.  If CWD is NULL, unset
-   the directory.  */
+/* See common/common-inferior.h.  */
 
-static void
+void
 set_inferior_cwd (const char *cwd)
 {
   struct inferior *inf = current_inferior ();
@@ -289,7 +288,8 @@ show_cwd_command (struct ui_file *file, int from_tty,
     fprintf_filtered (gdb_stdout,
 		      _("\
 You have not set the inferior's current working directory.\n\
-The inferior will inherit GDB's cwd.\n"));
+The inferior will inherit GDB's cwd if native debugging, or the remote\n\
+server's cwd if remote debugging.\n"));
   else
     fprintf_filtered (gdb_stdout,
 		      _("Current working directory that will be used "
diff --git a/gdb/remote.c b/gdb/remote.c
index d4f06a84da..267646f2ef 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1430,6 +1430,7 @@ enum {
   PACKET_QPassSignals,
   PACKET_QCatchSyscalls,
   PACKET_QProgramSignals,
+  PACKET_QSetWorkingDir,
   PACKET_QStartupWithShell,
   PACKET_QEnvironmentHexEncoded,
   PACKET_QEnvironmentReset,
@@ -4661,6 +4662,8 @@ static const struct protocol_feature remote_protocol_features[] = {
     PACKET_QCatchSyscalls },
   { "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
     PACKET_QProgramSignals },
+  { "QSetWorkingDir", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QSetWorkingDir },
   { "QStartupWithShell", PACKET_DISABLE, remote_supported_packet,
     PACKET_QStartupWithShell },
   { "QEnvironmentHexEncoded", PACKET_DISABLE, remote_supported_packet,
@@ -9640,6 +9643,41 @@ extended_remote_environment_support (struct remote_state *rs)
       send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
 }
 
+/* Helper function to set the current working directory for the
+   inferior in the remote.  */
+
+static void
+extended_remote_set_inferior_cwd (struct remote_state *rs)
+{
+  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
+    {
+      const char *inferior_cwd = get_inferior_cwd ();
+
+      if (inferior_cwd != NULL)
+	{
+	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
+					 strlen (inferior_cwd));
+
+	  xsnprintf (rs->buf, get_remote_packet_size (),
+		     "QSetWorkingDir:%s", hexpath.c_str ());
+	}
+      else
+	xsnprintf (rs->buf, get_remote_packet_size (),
+		   "QSetWorkingDir:");
+
+      putpkt (rs->buf);
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      if (packet_ok (rs->buf,
+		     &remote_protocol_packets[PACKET_QSetWorkingDir])
+	  != PACKET_OK)
+	error (_("\
+Remote replied unexpectedly while setting the inferior's working\n\
+directory: %s"),
+	       rs->buf);
+
+    }
+}
+
 /* In the extended protocol we want to be able to do things like
    "run" and have them basically work as expected.  So we need
    a special create_inferior function.  We support changing the
@@ -9682,6 +9720,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
 
   extended_remote_environment_support (rs);
 
+  extended_remote_set_inferior_cwd (rs);
+
   /* Now restart the remote server.  */
   run_worked = extended_remote_run (args) != -1;
   if (!run_worked)
@@ -14181,6 +14221,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
 			 "QProgramSignals", "program-signals", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
+			 "QSetWorkingDir", "set-working-dir", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
 			 "QStartupWithShell", "startup-with-shell", 0);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
index 3d666ba18d..60eb404c06 100644
--- a/gdb/testsuite/gdb.base/set-cwd.exp
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -15,8 +15,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
-    untested "not implemented on gdbserver"
+if { [use_gdb_stub] } {
+    untested "skipping tests due to use_gdb_stub"
     return
 }
 
-- 
2.13.3

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

* [PATCH v4 2/3] Implement "set cwd" command on GDB
  2017-09-28  4:10 ` [PATCH v4 0/3] New "set cwd" command Sergio Durigan Junior
  2017-09-28  4:10   ` [PATCH v4 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
  2017-09-28  4:11   ` [PATCH v4 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
@ 2017-09-28  4:11   ` Sergio Durigan Junior
  2017-09-29 15:20     ` Pedro Alves
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-28  4:11 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii, Sergio Durigan Junior

This is the actual implementation of the "set/show cwd" commands on
GDB.  The way they work is:

- If the user sets the inferior's cwd by using "set cwd", then this
  directory is saved into current_inferior ()->cwd and is used when
  the inferior is started (see below).

- If the user doesn't set the inferior's cwd by using "set cwd", but
  rather use the "cd" command as before, then this directory is
  inherited by the inferior because GDB will have chdir'd into it.

On Unix-like hosts, the way the directory is changed before the
inferior execution is by expanding the user set directory before the
fork, and then "chdir" after the call to fork/vfork on
"fork_inferior", but before the actual execution.  On Windows, the
inferior cwd set by the user is passed directly to the CreateProcess
call, which takes care of the actual chdir for us.

This way, we'll make sure that GDB's cwd is not affected by the user
set cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (New commands): Mention "set/show cwd".
	* cli/cli-cmds.c (_initialize_cli_cmds): Mention "set cwd" on
	"cd" command's help text.
	* common/common-inferior.h (get_inferior_cwd): New prototype.
	* infcmd.c (inferior_cwd_scratch): New global variable.
	(set_inferior_cwd): New function.
	(get_inferior_cwd): Likewise.
	(set_cwd_command): Likewise.
	(show_cwd_command): Likewise.
	(_initialize_infcmd): Add "set/show cwd" commands.
	* inferior.h (class inferior) <cwd>: New field.
	* nat/fork-inferior.c: Include "gdb_tilde_expand.h".
	(fork_inferior): Change inferior's cwd before its execution.
	* windows-nat.c (windows_create_inferior): Pass inferior's cwd
	to CreateProcess.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (current_inferior_cwd): New global variable.
	(get_inferior_cwd): New function.
	* inferiors.h (struct process_info) <cwd>: New field.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention new "set cwd" command.
	(Working Directory) <Your Program's Working Directory>:
	Rephrase to explain that "set cwd" exists and is the default
	way to change the inferior's cwd.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.c: New file.
	* gdb.base/set-cwd.exp: Likewise.
---
 gdb/NEWS                           |   3 +
 gdb/cli/cli-cmds.c                 |   8 +-
 gdb/common/common-inferior.h       |   4 +
 gdb/doc/gdb.texinfo                |  41 ++++++--
 gdb/gdbserver/inferiors.c          |  11 ++
 gdb/infcmd.c                       |  77 ++++++++++++++
 gdb/inferior.h                     |   4 +
 gdb/nat/fork-inferior.c            |  18 ++++
 gdb/testsuite/gdb.base/set-cwd.c   |  32 ++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 206 +++++++++++++++++++++++++++++++++++++
 gdb/windows-nat.c                  |  16 ++-
 11 files changed, 407 insertions(+), 13 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.c
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 81c21b82cc..fcf454833f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -67,6 +67,9 @@ QStartupWithShell
 
 * New commands
 
+set|show cwd
+  Set and show the current working directory for the inferior.
+
 set|show compile-gcc
   Set and show compilation command used for compiling and injecting code
   with the 'compile' commands.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index dde67ee2b3..dad5ffa42e 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1727,9 +1727,11 @@ The commands below can be used to select other frames by number or address."),
 Print working directory.  This is used for your program as well."));
 
   c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+The debugger's current working directory specifies where scripts and other\n\
+files that can be loaded by GDB are located.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_com ("echo", class_support, echo_command, _("\
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 87c13009ed..515a8c0f4e 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
    otherwise return 0 in that case.  */
 extern char *get_exec_file (int err);
 
+/* Return the inferior's current working directory.  If nothing has
+   been set, then return NULL.  */
+extern const char *get_inferior_cwd ();
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9905ff6513..0d059603cf 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
 your program.  @xref{Environment, ,Your Program's Environment}.
 
 @item The @emph{working directory.}
-Your program inherits its working directory from @value{GDBN}.  You can set
-the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+You can set your program's working directory with the command
+@kbd{set cwd}.  If you do not set any working directory with this
+command, your program will inherit @value{GDBN}'s working directory.
 @xref{Working Directory, ,Your Program's Working Directory}.
 
 @item The @emph{standard input and output.}
@@ -2434,19 +2435,43 @@ variables to files that are only run when you sign on, such as
 @section Your Program's Working Directory
 
 @cindex working directory (of your program)
-Each time you start your program with @code{run}, it inherits its
-working directory from the current working directory of @value{GDBN}.
-The @value{GDBN} working directory is initially whatever it inherited
-from its parent process (typically the shell), but you can specify a new
-working directory in @value{GDBN} with the @code{cd} command.
+Each time you start your program with @code{run}, the inferior will be
+initialized with the current working directory specified by the
+@kbd{set cwd} command.  If no directory has been specified by this
+command, then the inferior will inherit @value{GDBN}'s current working
+directory as its working directory.
+
+You can also change @value{GDBN}'s current working directory by using
+the @code{cd} command.
 
 The @value{GDBN} working directory also serves as a default for the commands
 that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
 Specify Files}.
 
 @table @code
+@kindex set cwd
+@cindex change inferior's working directory
+@item set cwd @r{[}@var{directory}@r{]}
+Set the inferior's working directory to @var{directory}, which will be
+@code{glob}-expanded in order to resolve tildes (@file{~}).  If no
+argument has been specified, the command clears the setting and resets
+it to an empty state.  This setting has no effect on @value{GDBN}'s
+working directory, and it only takes effect the next time you start
+the inferior.  The @file{~} in @var{directory} is a short for the
+@dfn{home directory}, usually pointed to by the @env{HOME} environment
+variable.  On MS-Windows, if @env{HOME} is not defined, @value{GDBN}
+uses the concatenation of @env{HOMEDRIVE} and @env{HOMEPATH} as
+fallback.
+
+@kindex show cwd
+@cindex show inferior's working directory
+@item show cwd
+Show the inferior's working directory.  If no directory has been
+specified by @kbd{set cwd}, then the default inferior's working
+directory is the same as @value{GDBN}'s working directory.
+
 @kindex cd
-@cindex change working directory
+@cindex change @value{GDBN}'s working directory
 @item cd @r{[}@var{directory}@r{]}
 Set the @value{GDBN} working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 3a45959000..57d9956ebb 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -29,6 +29,9 @@ struct thread_info *current_thread;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
 
+/* The current working directory used to start the inferior.  */
+static const char *current_inferior_cwd = NULL;
+
 void
 add_inferior_to_list (struct inferior_list *list,
 		      struct inferior_list_entry *new_inferior)
@@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
   gdb_assert (ptid != minus_one_ptid);
   current_thread = find_thread_ptid (ptid);
 }
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior_cwd;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index da16f5ed6d..dbdf273ca5 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -103,6 +103,10 @@ static void run_command (char *, int);
 
 static char *inferior_args_scratch;
 
+/* Scratch area where the new cwd will be stored by 'set cwd'.  */
+
+static char *inferior_cwd_scratch;
+
 /* Scratch area where 'set inferior-tty' will store user-provided value.
    We'll immediate copy it into per-inferior storage.  */
 
@@ -238,6 +242,60 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
+/* Set the inferior current working directory.  If CWD is NULL, unset
+   the directory.  */
+
+static void
+set_inferior_cwd (const char *cwd)
+{
+  struct inferior *inf = current_inferior ();
+
+  gdb_assert (inf != NULL);
+
+  if (cwd == NULL)
+    inf->cwd.reset ();
+  else
+    inf->cwd.reset (xstrdup (cwd));
+}
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior ()->cwd.get ();
+}
+
+/* Handle the 'set cwd' command.  */
+
+static void
+set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+{
+  if (*inferior_cwd_scratch == '\0')
+    set_inferior_cwd (NULL);
+  else
+    set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command.  */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  const char *cwd = get_inferior_cwd ();
+
+  if (cwd == NULL)
+    fprintf_filtered (gdb_stdout,
+		      _("\
+You have not set the inferior's current working directory.\n\
+The inferior will inherit GDB's cwd.\n"));
+  else
+    fprintf_filtered (gdb_stdout,
+		      _("Current working directory that will be used "
+			"when starting the inferior is \"%s\".\n"), cwd);
+}
+
 \f
 /* Compute command-line string given argument vector.  This does the
    same shell processing as fork_inferior.  */
@@ -3253,6 +3311,25 @@ Follow this command with any number of args, to be passed to the program."),
   gdb_assert (c != NULL);
   set_cmd_completer (c, filename_completer);
 
+  cmd_name = "cwd";
+  add_setshow_string_noescape_cmd (cmd_name, class_run,
+				   &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+				   _("\
+Show the current working directory that is used when the inferior is started."),
+				   _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started.  This setting does not affect GDB's current\n\
+working directory."),
+				   set_cwd_command,
+				   show_cwd_command,
+				   &setlist, &showlist);
+  c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+  gdb_assert (c != NULL);
+  set_cmd_completer (c, filename_completer);
+
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
 With an argument VAR, prints the value of environment variable VAR to\n\
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 7f2d53e5b3..498d74706a 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -355,6 +355,10 @@ public:
      should never be freed.  */
   char **argv = NULL;
 
+  /* The current working directory that will be used when starting
+     this inferior.  */
+  gdb::unique_xmalloc_ptr<char> cwd;
+
   /* The name of terminal device to use for I/O.  */
   char *terminal = NULL;
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 6ff119768c..0ce442f162 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -25,6 +25,7 @@
 #include "common-inferior.h"
 #include "common-gdbthread.h"
 #include "signals-state-save-restore.h"
+#include "gdb_tilde_expand.h"
 #include <vector>
 
 extern char **environ;
@@ -298,6 +299,8 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
   char **save_our_env;
   int i;
   int save_errno;
+  const char *inferior_cwd;
+  std::string expanded_inferior_cwd;
 
   /* If no exec file handed to us, get it from the exec-file command
      -- with a good, common error message if none is specified.  */
@@ -339,6 +342,13 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
      the parent and child flushing the same data after the fork.  */
   gdb_flush_out_err ();
 
+  /* Check if the user wants to set a different working directory for
+     the inferior.  */
+  inferior_cwd = get_inferior_cwd ();
+
+  if (inferior_cwd != NULL)
+    expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
+
   /* If there's any initialization of the target layers that must
      happen to prepare to handle the child we're about fork, do it
      now...  */
@@ -374,6 +384,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
 	 UIs.  */
       close_most_fds ();
 
+      /* Change to the requested working directory if the user
+	 requested it.  */
+      if (inferior_cwd != NULL)
+	{
+	  if (chdir (expanded_inferior_cwd.c_str ()) < 0)
+	    trace_start_error_with_name (expanded_inferior_cwd.c_str ());
+	}
+
       if (debug_fork)
 	sleep (debug_fork);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.c b/gdb/testsuite/gdb.base/set-cwd.c
new file mode 100644
index 0000000000..2a501aa675
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.c
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 Free Software Foundation, Inc.
+
+   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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char dir[4096];
+
+int
+main (int argc, char *argv[])
+{
+  const char *home = getenv ("HOME");
+
+  getcwd (dir, 4096);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
new file mode 100644
index 0000000000..3d666ba18d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -0,0 +1,206 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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/>.
+
+if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
+    untested "not implemented on gdbserver"
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    return -1
+}
+
+# Test that tilde expansion works fine.
+
+proc test_tilde_expansion { } {
+    global decimal gdb_prompt hex
+
+    with_test_prefix "test tilde expansion" {
+	gdb_test_no_output "set cwd ~/" "set inferior cwd to ~/ dir"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test_multiple "print home" "print home var" {
+	    -re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
+		set home $expect_out(1,string)
+	    }
+	    -re "$gdb_prompt $" {
+		untested "could to retrieve home var"
+		return
+	    }
+	    default {
+		untested "could to retrieve home var"
+		return
+	    }
+	}
+
+	if { [string length $home] > 0 } {
+	    gdb_test_multiple "print dir" "print dir var" {
+		-re "\\\$$decimal = \"\(.+\)\"\(, .*repeats.*\)?\r\n$gdb_prompt $" {
+		    set curdir $expect_out(1,string)
+		}
+		-re "$gdb_prompt $" {
+		    fail "failed to retrieve dir var"
+		    return -1
+		}
+		default {
+		    fail "failed to retrieve dir var"
+		    return -1
+		}
+	    }
+
+	    gdb_assert [string equal $curdir $home] \
+		"successfully chdir'd into home"
+	} else {
+	    untested "could not determine value of HOME"
+	    return
+	}
+    }
+}
+
+# The temporary directory that we will use to start the inferior.
+set tmpdir [standard_output_file ""]
+
+# Test that when we "set cwd" the inferior will be started under the
+# correct working directory and GDB will not be affected by this.
+
+proc test_cd_into_dir { } {
+    global decimal gdb_prompt tmpdir
+
+    with_test_prefix "test cd into temp dir" {
+	gdb_test_multiple "pwd" "pwd before run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_before_run $expect_out(1,string)
+	    }
+	    -re ".*$gdb_prompt $" {
+		fail "failed to obtain GDB cwd before run"
+		return -1
+	    }
+	    default {
+		fail "failed to obtain GDB cwd before run"
+		return -1
+	    }
+	}
+
+	# This test only makes sense if $tmpdir != $gdb_cwd_before_run
+	if { ![gdb_assert ![string equal $tmpdir $gdb_cwd_before_run] \
+		   "make sure that tmpdir and GDB's cwd are different"] } {
+	    return -1
+	}
+
+	gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	    "inferior cwd is correctly set"
+
+	gdb_test_multiple "pwd" "pwd after run" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd_after_run $expect_out(1,string)
+	    }
+	    -re ".*$gdb_prompt $" {
+		fail "failed to obtain GDB cwd after run"
+		return -1
+	    }
+	    default {
+		fail "failed to obtain GDB cwd after run"
+		return -1
+	    }
+	}
+
+	gdb_assert [string equal $gdb_cwd_before_run $gdb_cwd_after_run] \
+	    "GDB cwd is unchanged after running inferior"
+    }
+}
+
+# Test that executing "set cwd" without arguments will reset the
+# inferior's cwd setting to its previous state.
+
+proc test_cwd_reset { } {
+    global decimal gdb_prompt tmpdir
+
+    with_test_prefix "test inferior cwd reset" {
+	gdb_test_multiple "pwd" "GDB cwd" {
+	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+		set gdb_cwd $expect_out(1,string)
+	    }
+	    -re ".*$gdb_prompt $" {
+		fail "failed to obtain GDB cwd before run"
+		return -1
+	    }
+	    default {
+		fail "failed to obtain GDB cwd before run"
+		return -1
+	    }
+	}
+
+	# This test only makes sense if $tmpdir != $gdb_cwd
+	# This test only makes sense if $tmpdir != $gdb_cwd
+	if { ![gdb_assert ![string equal $tmpdir $gdb_cwd] \
+		   "make sure that tmpdir and GDB's cwd are different"] } {
+	    return -1
+	}
+
+	gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	    "inferior cwd is correctly set"
+
+	# Reset the inferior's cwd.
+	gdb_test_no_output "set cwd" "resetting inferior cwd"
+
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+
+	gdb_breakpoint [gdb_get_line_number "break-here"]
+	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+	gdb_test "print dir" "\\\$$decimal = \"$gdb_cwd\", .*" \
+	    "inferior cwd got reset correctly"
+    }
+}
+
+test_cd_into_dir
+clean_restart $binfile
+test_tilde_expansion
+clean_restart $binfile
+test_cwd_reset
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 3e1894410d..5144e9f7a6 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -66,6 +66,7 @@
 #include "x86-nat.h"
 #include "complaints.h"
 #include "inf-child.h"
+#include "gdb_tilde_expand.h"
 
 #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
@@ -2432,6 +2433,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   cygwin_buf_t *toexec;
   cygwin_buf_t *cygallargs;
   cygwin_buf_t *args;
+  cygwin_buf_t *infcwd;
   char **old_env = NULL;
   PWCHAR w32_env;
   size_t len;
@@ -2461,6 +2463,8 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   BOOL ret;
   DWORD flags = 0;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd = gdb_tilde_expand (inferior_cwd);
 
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
@@ -2514,6 +2518,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
       flags |= DEBUG_PROCESS;
     }
 
+  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, expanded_infcwd.c_str (),
+			infcwd, expanded_infcwd.size ()) < 0)
+    error (_("Error converting inferior cwd: %d"), errno);
+
 #ifdef __USEWIDE
   args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
 				  * sizeof (wchar_t));
@@ -2574,7 +2582,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 		       TRUE,	/* inherit handles */
 		       flags,	/* start flags */
 		       w32_env,	/* environment */
-		       NULL,	/* current directory */
+		       infcwd,	/* current directory */
 		       &si,
 		       &pi);
   if (w32_env)
@@ -2689,6 +2697,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   /* Final nil string to terminate new env.  */
   *temp = 0;
 
+  /* Mirror slashes on inferior's cwd.  */
+  std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+		'/', '\\');
+
   windows_init_thread_list ();
   ret = CreateProcessA (0,
 			args,	/* command line */
@@ -2697,7 +2709,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 			TRUE,	/* inherit handles */
 			flags,	/* start flags */
 			w32env,	/* environment */
-			NULL,	/* current directory */
+			expanded_infcwd.c_str (), /* current directory */
 			&si,
 			&pi);
   if (tty != INVALID_HANDLE_VALUE)
-- 
2.13.3

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-27 21:48       ` Sergio Durigan Junior
@ 2017-09-29 14:03         ` Pedro Alves
  2017-09-29 18:33           ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-29 14:03 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 09/27/2017 10:48 PM, Sergio Durigan Junior wrote:

>> note: 
>>   s/when/if/.
>>   s/@code/@kdb
> 
> It's @kbd (from "keyboard").  But I know, our muscle memory wants us to
> type "db" :-P.

;-)

> 
> Even though I slightly disagree here (commands are not keybindings), I
> found that this is indeed what GDB uses.  Anyway, using @kbd now.

See discussion starting here:

  https://sourceware.org/ml/gdb-patches/2017-06/msg00592.html

> 
> Not in this specific version, no.  This was something decided *after* I
> had sent this version.  In my local tree I have code implementing the
> "clear up" behaviour, and I'll add a test for that as well.

OK, thanks.  Sorry I got confused.

>> There are many other boards that set use_gdb_stub, not just
>> native-gdbserver.  Other testcases say:
>>
>> untested "skipping tests due to use_gdb_stub"
> 
> Hm, OK.
> 
> Does this look correct now, though?

I don't know; I'll take a look at v4.  We may
still need is_remote checks depending on whether the
tests have assumptions about build==host or host==target.

Thanks,
Pedro Alves

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

* Re: [PATCH v4 1/3] Introduce gdb_tilde_expand
  2017-09-28  4:10   ` [PATCH v4 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
@ 2017-09-29 14:08     ` Pedro Alves
  2017-09-29 17:48       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-29 14:08 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches; +Cc: Eli Zaretskii

On 09/28/2017 05:10 AM, Sergio Durigan Junior wrote:

> --- /dev/null
> +++ b/gdb/common/gdb_tilde_expand.h

> +
> +#ifndef HAVE_GDB_TILDE_EXPAND_H
> +#define HAVE_GDB_TILDE_EXPAND_H

HAVE above should be COMMON_GDB_TILDE_EXPAND_H surely.

OK with that change.

Thanks,
Pedro Alves

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

* Re: [PATCH v4 2/3] Implement "set cwd" command on GDB
  2017-09-28  4:11   ` [PATCH v4 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
@ 2017-09-29 15:20     ` Pedro Alves
  2017-09-29 18:31       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-29 15:20 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches; +Cc: Eli Zaretskii

On 09/28/2017 05:10 AM, Sergio Durigan Junior wrote:
> This is the actual implementation of the "set/show cwd" commands on
> GDB.  The way they work is:

(This is not a huge deal, but note that this is
assuming the reader first read the cover letter, but the
cover letter doesn't make it to git and won't be available
to whoever looks ends up looking at the commit while doing
some archaeology.)

> 
> - If the user sets the inferior's cwd by using "set cwd", then this
>   directory is saved into current_inferior ()->cwd and is used when
>   the inferior is started (see below).
> 
> - If the user doesn't set the inferior's cwd by using "set cwd", but
>   rather use the "cd" command as before, then this directory is
>   inherited by the inferior because GDB will have chdir'd into it.
> 
> On Unix-like hosts, the way the directory is changed before the
> inferior execution is by expanding the user set directory before the
> fork, and then "chdir" after the call to fork/vfork on
> "fork_inferior", but before the actual execution.  On Windows, the
> inferior cwd set by the user is passed directly to the CreateProcess
> call, which takes care of the actual chdir for us.
> 
> This way, we'll make sure that GDB's cwd is not affected by the user
> set cwd.
> 

> @@ -339,6 +342,13 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>       the parent and child flushing the same data after the fork.  */
>    gdb_flush_out_err ();
>  
> +  /* Check if the user wants to set a different working directory for
> +     the inferior.  */
> +  inferior_cwd = get_inferior_cwd ();
> +
> +  if (inferior_cwd != NULL)
> +    expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);

Please add something like:

/* Expand before forking because between fork and exec, the child
   process may only execute async-signal-safe operations.  */

I think it'd look clearer to do:

  inferior_cwd = get_inferior_cwd ();

  if (inferior_cwd != NULL)
    {
      expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
      inferior_cwd = expanded_inferior_cwd.c_str ();
    }

here and ...

> +
>    /* If there's any initialization of the target layers that must
>       happen to prepare to handle the child we're about fork, do it
>       now...  */
> @@ -374,6 +384,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>  	 UIs.  */
>        close_most_fds ();
>  
> +      /* Change to the requested working directory if the user
> +	 requested it.  */
> +      if (inferior_cwd != NULL)
> +	{
> +	  if (chdir (expanded_inferior_cwd.c_str ()) < 0)
> +	    trace_start_error_with_name (expanded_inferior_cwd.c_str ());
> +	}

... then here do:

      if (inferior_cwd != NULL)
	{
	  if (chdir (inferior_cwd) < 0)
	    trace_start_error_with_name (inferior_cwd);
	}

Or even:

      if (inferior_cwd != NULL && chdir (inferior_cwd) < 0)
        trace_start_error_with_name (inferior_cwd);


> +++ b/gdb/testsuite/gdb.base/set-cwd.c
> @@ -0,0 +1,32 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2017 Free Software Foundation, Inc.
> +
> +   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 <stdio.h>

This include doesn't look necessary.

> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +static char dir[4096];
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  const char *home = getenv ("HOME");
> +
> +  getcwd (dir, 4096);
> +
> +  return 0; /* break-here */
> +}
> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
> new file mode 100644
> index 0000000000..3d666ba18d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
> @@ -0,0 +1,206 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 2017 Free Software Foundation, Inc.
> +
> +# 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/>.
> +
> +if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
> +    untested "not implemented on gdbserver"

The untested message still refers to gdbserver.  OK, I see that
you're changing it in the next patch.

> +    return
> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
> +    return -1
> +}
> +
> +# Test that tilde expansion works fine.
> +
> +proc test_tilde_expansion { } {
> +    global decimal gdb_prompt hex
> +
> +    with_test_prefix "test tilde expansion" {

Note you can use proc_with_prefix to avoid having to
write procs with nested scopes.

> +	gdb_test_no_output "set cwd ~/" "set inferior cwd to ~/ dir"
> +
> +	if { ![runto_main] } {
> +	    untested "could not run to main"
> +	    return -1
> +	}
> +
> +	gdb_breakpoint [gdb_get_line_number "break-here"]
> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
> +
> +	gdb_test_multiple "print home" "print home var" {
> +	    -re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
> +		set home $expect_out(1,string)
> +	    }
> +	    -re "$gdb_prompt $" {
> +		untested "could to retrieve home var"
> +		return

"could not" I assume.

> +	    }
> +	    default {
> +		untested "could to retrieve home var"
> +		return
> +	    }
> +	}

I'd rather this was written like this:

        set home ""
	set test "print home var"
	gdb_test_multiple "print home" $test {
	    -re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
		set home $expect_out(1,string)
		pass $test
	    }
	}

        if {$home == ""} {
	  untested "could not retrieve home var"
          return
        }

Because this way, you automatically get the usual:
   FAIL: print home var (timeout)
or:
   FAIL: print home var (eof)

which your version suppresses, followed by:
   UNTESTED: could to retrieve home var

And in spirit of always having matching pass/fails, note
there's a pass call above.

Actually, you can probably just use get_valueof for this:

        set home [get_valueof "" "home" "" "retrieve home var"]
        if {$home == ""} {
	  untested "could not retrieve home var"
          return
        }

> +
> +	if { [string length $home] > 0 } {

This check can then go away.

> +	    gdb_test_multiple "print dir" "print dir var" {
> +		-re "\\\$$decimal = \"\(.+\)\"\(, .*repeats.*\)?\r\n$gdb_prompt $" {
> +		    set curdir $expect_out(1,string)
> +		}
> +		-re "$gdb_prompt $" {
> +		    fail "failed to retrieve dir var"
> +		    return -1
> +		}
> +		default {
> +		    fail "failed to retrieve dir var"
> +		    return -1
> +		}
> +	    }

And here you'd apply the same pattern.



> +
> +	    gdb_assert [string equal $curdir $home] \
> +		"successfully chdir'd into home"
> +	} else {
> +	    untested "could not determine value of HOME"
> +	    return
> +	}
> +    }
> +}
> +
> +# The temporary directory that we will use to start the inferior.
> +set tmpdir [standard_output_file ""]
> +
> +# Test that when we "set cwd" the inferior will be started under the
> +# correct working directory and GDB will not be affected by this.
> +
> +proc test_cd_into_dir { } {
> +    global decimal gdb_prompt tmpdir
> +
> +    with_test_prefix "test cd into temp dir" {
> +	gdb_test_multiple "pwd" "pwd before run" {
> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
> +		set gdb_cwd_before_run $expect_out(1,string)
> +	    }
> +	    -re ".*$gdb_prompt $" {
> +		fail "failed to obtain GDB cwd before run"
> +		return -1
> +	    }
> +	    default {
> +		fail "failed to obtain GDB cwd before run"
> +		return -1
> +	    }
> +	}

Ditto.  (This appears multiple times throughout.)

> +
> +	# This test only makes sense if $tmpdir != $gdb_cwd_before_run
> +	if { ![gdb_assert ![string equal $tmpdir $gdb_cwd_before_run] \
> +		   "make sure that tmpdir and GDB's cwd are different"] } {
> +	    return -1
> +	}
> +
> +	gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
> +
> +	if { ![runto_main] } {
> +	    untested "could not run to main"
> +	    return -1
> +	}
> +
> +	gdb_breakpoint [gdb_get_line_number "break-here"]
> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
> +
> +	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
> +	    "inferior cwd is correctly set"
> +
> +	gdb_test_multiple "pwd" "pwd after run" {
> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
> +		set gdb_cwd_after_run $expect_out(1,string)
> +	    }
> +	    -re ".*$gdb_prompt $" {
> +		fail "failed to obtain GDB cwd after run"
> +		return -1
> +	    }
> +	    default {
> +		fail "failed to obtain GDB cwd after run"
> +		return -1
> +	    }
> +	}
> +
> +	gdb_assert [string equal $gdb_cwd_before_run $gdb_cwd_after_run] \
> +	    "GDB cwd is unchanged after running inferior"
> +    }
> +}
> +
> +# Test that executing "set cwd" without arguments will reset the
> +# inferior's cwd setting to its previous state.
> +
> +proc test_cwd_reset { } {
> +    global decimal gdb_prompt tmpdir
> +
> +    with_test_prefix "test inferior cwd reset" {
> +	gdb_test_multiple "pwd" "GDB cwd" {
> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
> +		set gdb_cwd $expect_out(1,string)
> +	    }
> +	    -re ".*$gdb_prompt $" {
> +		fail "failed to obtain GDB cwd before run"
> +		return -1
> +	    }
> +	    default {
> +		fail "failed to obtain GDB cwd before run"
> +		return -1
> +	    }
> +	}
> +
> +	# This test only makes sense if $tmpdir != $gdb_cwd
> +	# This test only makes sense if $tmpdir != $gdb_cwd

Duplicate comment.  And missing period.

> +	if { ![gdb_assert ![string equal $tmpdir $gdb_cwd] \
> +		   "make sure that tmpdir and GDB's cwd are different"] } {
> +	    return -1
> +	}
> +
> +	gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
> +
> +	if { ![runto_main] } {
> +	    untested "could not run to main"
> +	    return -1
> +	}
> +
> +	gdb_breakpoint [gdb_get_line_number "break-here"]
> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
> +
> +	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
> +	    "inferior cwd is correctly set"
> +
> +	# Reset the inferior's cwd.
> +	gdb_test_no_output "set cwd" "resetting inferior cwd"
> +
> +	if { ![runto_main] } {
> +	    untested "could not run to main"
> +	    return -1
> +	}

Wrap each runto_main invocation in its own with_test_prefix,
so that if any fails we get unique test names in gdb.sum.

> +
> +	gdb_breakpoint [gdb_get_line_number "break-here"]
> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
> +
> +	gdb_test "print dir" "\\\$$decimal = \"$gdb_cwd\", .*" \
> +	    "inferior cwd got reset correctly"
> +    }
> +}
> +
> +test_cd_into_dir
> +clean_restart $binfile
> +test_tilde_expansion
> +clean_restart $binfile
> +test_cwd_reset
> diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
> index 3e1894410d..5144e9f7a6 100644
> --- a/gdb/windows-nat.c
> +++ b/gdb/windows-nat.c
> @@ -66,6 +66,7 @@
>  #include "x86-nat.h"
>  #include "complaints.h"
>  #include "inf-child.h"
> +#include "gdb_tilde_expand.h"
>  
>  #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
>  #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
> @@ -2432,6 +2433,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>    cygwin_buf_t *toexec;
>    cygwin_buf_t *cygallargs;
>    cygwin_buf_t *args;
> +  cygwin_buf_t *infcwd;
>    char **old_env = NULL;
>    PWCHAR w32_env;
>    size_t len;
> @@ -2461,6 +2463,8 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>    BOOL ret;
>    DWORD flags = 0;
>    const char *inferior_io_terminal = get_inferior_io_terminal ();
> +  const char *inferior_cwd = get_inferior_cwd ();
> +  std::string expanded_infcwd = gdb_tilde_expand (inferior_cwd);

Does gdb_tilde_expand work with NULL input ?

>  
>    if (!exec_file)
>      error (_("No executable specified, use `target exec'."));
> @@ -2514,6 +2518,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>        flags |= DEBUG_PROCESS;
>      }
>  
> +  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, expanded_infcwd.c_str (),
> +			infcwd, expanded_infcwd.size ()) < 0)
> +    error (_("Error converting inferior cwd: %d"), errno);

I don't see how this can work.  'infcwd' was never initialized to
point at some buffer?  It's garbage.  I think you're supposed to
call this twice, once to determine the needed size, and then
another to fill in a buffer of that size.

Thanks,
Pedro Alves

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

* Re: [PATCH v4 3/3] Extend "set cwd" to work on gdbserver
  2017-09-28  4:11   ` [PATCH v4 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
@ 2017-09-29 15:21     ` Pedro Alves
  2017-09-29 18:48       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-29 15:21 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches; +Cc: Eli Zaretskii

On 09/28/2017 05:10 AM, Sergio Durigan Junior wrote:
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -26,6 +26,14 @@
>  
>  * New features in the GDB remote stub, GDBserver
>  
> +  ** GDBserver is now able to set the inferior's current working
> +     directory.

That's confusing IMO, because it sounds like you're saying
you can change the inferior's current working directory at
any time, even on inferiors that are already running...

I'd go for:

  ** GDBserver is now able to start inferior processes with a
     specified initial working directory.

> +
> +     The user can set the desired working directory to be used by the
> +     remote inferior on GDB, using the new "set cwd" command, which
> +     will instruct GDB to tell GDBserver about this directory change
> +     the next time an inferior is run.

And instead of the above, say:

     The user can set the desired working directory to be used from GDB
     using the new "set cwd" command.

Note "on" -> "from".  I think that conveys it better.

The "which will instruct" part is distracting and unnecessary
implementation detail, IMO.


> +@item QSetWorkingDir:@r{[}@var{directory}@r{]}
> +@anchor{QSetWorkingDir packet}
> +@cindex set working directory, remote request
> +@cindex @samp{QSetWorkingDir} packet
> +This packet is used to inform the remote server of the intended
> +current working directory for programs that are going to be executed.
> +
> +The packet is composed by @var{directory}, an hex encoded
> +representation of the directory that the remote inferior will use as
> +its current working directory.  If @var{directory} is an empty string,
> +the remote server should reset the inferior's current working
> +directory to its original, empty value.
> +
> +This packet is always transmitted when the inferior is run.  If the
> +user has not explcitly specified a directory with the @kbd{set cwd}

typo: explicitly

> +command, then an empty packet will be sent to the remote server, which

Not an empty packet, and empty directory.  Really-empty packets are 
special in the remote protocol.

> +will have no effect.  

WDYM will have no effect, when just above you've explained that empty
means reset ?  I think you should just remove this paragraph starting
with "This packet is always transmitted".  That's implementation
detail.  GDB could for example not resend the packet if the value
didn't change between runs, no?

> Otherwise, the specified inferior's working
> +directory will be transmitted (@pxref{Working Directory, ,Your
> +Program's Working Directory}).

This too should be tweaked accordingly.

> +
> +This packet is only available in extended mode (@pxref{extended
> +mode}).
> +

Thanks,
Pedro Alves

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-27 14:02                     ` Pedro Alves
@ 2017-09-29 15:31                       ` Eli Zaretskii
  2017-09-29 15:46                         ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-29 15:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: sergiodj, gdb-patches

> Cc: sergiodj@redhat.com, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Wed, 27 Sep 2017 15:01:58 +0100
> 
> Let's say that GDB keeps track of the desired cwd for the inferior
> as a single string, like Sergio's patch is doing.  Say the user does:
> 
>  $ gdb
>  (gdb) file program
>  (gdb) set cwd ~
> 
> At this point, GDB it not "connected" to any target yet.  However,
> if the user types "run", GDB automatically uses the native
> target to run the inferior.  So typing "run" after the above is
> equivalent to:
> 
>  $ gdb
>  (gdb) file program
>  (gdb) set cwd ~
>  (gdb) target native
>  (gdb) run
> 
> OK, now the question is, when to expand that '~'.  If it is
> expanded immediately at "set cwd" time, then we end up expanding
> it incorrectly in case the user actually wanted to debug remotely:

How about expanding it as part of "target FOO"?

> If GDB does not expand the set cwd path ever except internally
> when starting the inferior, then the problems shown just above
> never happen.

But that's an illusory advantage, isn't it?  Because we then keep "~",
but it expands to something different for every target, and the user
has no way of knowing what that will do on another target.  Moreover,
the user might not even want to have a different expansion for each
target.

>  $ gdb
>  (gdb) file program
>  (gdb) set cwd ~
>  (gdb) show cwd
>  cwd is: ~   
>  expands to /home/pedro on current target
>  (gdb) start
>  (gdb) show cwd
>  cwd is: ~   
>  expands to /home/pedro on current target
>  (gdb) kill
>  (gdb) target extended-remote foo:12345
>  (gdb) show cwd
>  cwd is: ~
>  expands to /mnt/home/palves on current target
>  (gdb) disconnect
>  (gdb) target extended-remote bar:12345
>  (gdb) show cwd
>  cwd is: ~   
>  expands to /nfs/homes/pedro on current target
> 
> I'm not sure it's worth the trouble to show the
> expansions like this.  But if we make GDB _not_ expand
> the "set cwd" setting's value itself, as I was proposing,
> then we can always come back and improve GDB's output like
> above, to inform the user what the setting expands to,
> as extra info.

Maybe making "show cwd" expand in the right context would be a good
middle-ground.

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-29 15:31                       ` Eli Zaretskii
@ 2017-09-29 15:46                         ` Pedro Alves
  2017-09-29 17:51                           ` Eli Zaretskii
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-09-29 15:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sergiodj, gdb-patches

On 09/29/2017 04:31 PM, Eli Zaretskii wrote:

> But that's an illusory advantage, isn't it?  

I don't think it is.

> Because we then keep "~",
> but it expands to something different for every target, and the user
> has no way of knowing what that will do on another target. 

If the user types "~" then surely they want the home directory,
whatever it is on the machine.  That's the point of "~" existing,
IMO.

> Moreover,
> the user might not even want to have a different expansion for each
> target.

If the user does not want a different expansion for each
target then they can simply specify an expanded path
like "/home/joe" or whatever without the "~".

Thanks,
Pedro Alves

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

* Re: [PATCH v4 1/3] Introduce gdb_tilde_expand
  2017-09-29 14:08     ` Pedro Alves
@ 2017-09-29 17:48       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 17:48 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Friday, September 29 2017, Pedro Alves wrote:

> On 09/28/2017 05:10 AM, Sergio Durigan Junior wrote:
>
>> --- /dev/null
>> +++ b/gdb/common/gdb_tilde_expand.h
>
>> +
>> +#ifndef HAVE_GDB_TILDE_EXPAND_H
>> +#define HAVE_GDB_TILDE_EXPAND_H
>
> HAVE above should be COMMON_GDB_TILDE_EXPAND_H surely.

Actually no.  It should be GDB_TILDE_EXPAND_H, because that's how the
other gdb/common/gdb_*.h files are named.  But thanks for spotting
this.  Fixed.

> OK with that change.

Thanks.  I'll wait until the other patches are approved before I push
this one.

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

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

* Re: [PATCH v3 4/5] Implement "set cwd" command on GDB
  2017-09-29 15:46                         ` Pedro Alves
@ 2017-09-29 17:51                           ` Eli Zaretskii
  0 siblings, 0 replies; 131+ messages in thread
From: Eli Zaretskii @ 2017-09-29 17:51 UTC (permalink / raw)
  To: Pedro Alves; +Cc: sergiodj, gdb-patches

> Cc: sergiodj@redhat.com, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 29 Sep 2017 16:46:13 +0100
> 
> > Because we then keep "~",
> > but it expands to something different for every target, and the user
> > has no way of knowing what that will do on another target. 
> 
> If the user types "~" then surely they want the home directory,
> whatever it is on the machine.  That's the point of "~" existing,
> IMO.

Users might not be aware the same "~" will get re-expanded for each
target.

Anyway, I talked enough about this.  It's your call wrt what to do
with this.

Thanks.

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

* Re: [PATCH v4 2/3] Implement "set cwd" command on GDB
  2017-09-29 15:20     ` Pedro Alves
@ 2017-09-29 18:31       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 18:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Friday, September 29 2017, Pedro Alves wrote:

> On 09/28/2017 05:10 AM, Sergio Durigan Junior wrote:
>> This is the actual implementation of the "set/show cwd" commands on
>> GDB.  The way they work is:
>
> (This is not a huge deal, but note that this is
> assuming the reader first read the cover letter, but the
> cover letter doesn't make it to git and won't be available
> to whoever looks ends up looking at the commit while doing
> some archaeology.)

I can improve the message here, and add more context.

>> - If the user sets the inferior's cwd by using "set cwd", then this
>>   directory is saved into current_inferior ()->cwd and is used when
>>   the inferior is started (see below).
>> 
>> - If the user doesn't set the inferior's cwd by using "set cwd", but
>>   rather use the "cd" command as before, then this directory is
>>   inherited by the inferior because GDB will have chdir'd into it.
>> 
>> On Unix-like hosts, the way the directory is changed before the
>> inferior execution is by expanding the user set directory before the
>> fork, and then "chdir" after the call to fork/vfork on
>> "fork_inferior", but before the actual execution.  On Windows, the
>> inferior cwd set by the user is passed directly to the CreateProcess
>> call, which takes care of the actual chdir for us.
>> 
>> This way, we'll make sure that GDB's cwd is not affected by the user
>> set cwd.
>> 
>
>> @@ -339,6 +342,13 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>>       the parent and child flushing the same data after the fork.  */
>>    gdb_flush_out_err ();
>>  
>> +  /* Check if the user wants to set a different working directory for
>> +     the inferior.  */
>> +  inferior_cwd = get_inferior_cwd ();
>> +
>> +  if (inferior_cwd != NULL)
>> +    expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
>
> Please add something like:
>
> /* Expand before forking because between fork and exec, the child
>    process may only execute async-signal-safe operations.  */
>
> I think it'd look clearer to do:
>
>   inferior_cwd = get_inferior_cwd ();
>
>   if (inferior_cwd != NULL)
>     {
>       expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
>       inferior_cwd = expanded_inferior_cwd.c_str ();
>     }

Added the comment and assigned to inferior_cwd.

> here and ...
>
>> +
>>    /* If there's any initialization of the target layers that must
>>       happen to prepare to handle the child we're about fork, do it
>>       now...  */
>> @@ -374,6 +384,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>>  	 UIs.  */
>>        close_most_fds ();
>>  
>> +      /* Change to the requested working directory if the user
>> +	 requested it.  */
>> +      if (inferior_cwd != NULL)
>> +	{
>> +	  if (chdir (expanded_inferior_cwd.c_str ()) < 0)
>> +	    trace_start_error_with_name (expanded_inferior_cwd.c_str ());
>> +	}
>
> ... then here do:
>
>       if (inferior_cwd != NULL)
> 	{
> 	  if (chdir (inferior_cwd) < 0)
> 	    trace_start_error_with_name (inferior_cwd);
> 	}

I prefer this way, so I updated the code to look like this.

> Or even:
>
>       if (inferior_cwd != NULL && chdir (inferior_cwd) < 0)
>         trace_start_error_with_name (inferior_cwd);
>
>
>> +++ b/gdb/testsuite/gdb.base/set-cwd.c
>> @@ -0,0 +1,32 @@
>> +/* This testcase is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2017 Free Software Foundation, Inc.
>> +
>> +   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 <stdio.h>
>
> This include doesn't look necessary.

Hm.  Removed.

>> +#include <stdlib.h>
>> +#include <unistd.h>
>> +
>> +static char dir[4096];
>> +
>> +int
>> +main (int argc, char *argv[])
>> +{
>> +  const char *home = getenv ("HOME");
>> +
>> +  getcwd (dir, 4096);
>> +
>> +  return 0; /* break-here */
>> +}
>> diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
>> new file mode 100644
>> index 0000000000..3d666ba18d
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/set-cwd.exp
>> @@ -0,0 +1,206 @@
>> +# This testcase is part of GDB, the GNU debugger.
>> +
>> +# Copyright 2017 Free Software Foundation, Inc.
>> +
>> +# 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/>.
>> +
>> +if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
>> +    untested "not implemented on gdbserver"
>
> The untested message still refers to gdbserver.  OK, I see that
> you're changing it in the next patch.

I'll change it to say "not implemented on remote servers".

>> +    return
>> +}
>> +
>> +standard_testfile
>> +
>> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
>> +    return -1
>> +}
>> +
>> +# Test that tilde expansion works fine.
>> +
>> +proc test_tilde_expansion { } {
>> +    global decimal gdb_prompt hex
>> +
>> +    with_test_prefix "test tilde expansion" {
>
> Note you can use proc_with_prefix to avoid having to
> write procs with nested scopes.

Didn't know about that.  Thanks.

>> +	gdb_test_no_output "set cwd ~/" "set inferior cwd to ~/ dir"
>> +
>> +	if { ![runto_main] } {
>> +	    untested "could not run to main"
>> +	    return -1
>> +	}
>> +
>> +	gdb_breakpoint [gdb_get_line_number "break-here"]
>> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>> +
>> +	gdb_test_multiple "print home" "print home var" {
>> +	    -re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
>> +		set home $expect_out(1,string)
>> +	    }
>> +	    -re "$gdb_prompt $" {
>> +		untested "could to retrieve home var"
>> +		return
>
> "could not" I assume.

Ops, yes.  Fixed.

>> +	    }
>> +	    default {
>> +		untested "could to retrieve home var"
>> +		return
>> +	    }
>> +	}
>
> I'd rather this was written like this:
>
>         set home ""
> 	set test "print home var"
> 	gdb_test_multiple "print home" $test {
> 	    -re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
> 		set home $expect_out(1,string)
> 		pass $test
> 	    }
> 	}
>
>         if {$home == ""} {
> 	  untested "could not retrieve home var"
>           return
>         }
>
> Because this way, you automatically get the usual:
>    FAIL: print home var (timeout)
> or:
>    FAIL: print home var (eof)
>
> which your version suppresses, followed by:
>    UNTESTED: could to retrieve home var
>
> And in spirit of always having matching pass/fails, note
> there's a pass call above.

Hm, OK.  Changed the code to reflect the proposed changes.

> Actually, you can probably just use get_valueof for this:
>
>         set home [get_valueof "" "home" "" "retrieve home var"]
>         if {$home == ""} {
> 	  untested "could not retrieve home var"
>           return
>         }

I had tried using "get_valueof" even before I submitted the first
version of the patch, but it doesn't really work "out of the box".  For
example, the output of "print home" (or "print/s home") is:

  (gdb) print home
  $1 = 0x7fffffffe703 "/home/sergio"

And "get_valueof" doesn't handle the address part very well, so $home
ends up with the value '0x7fffffffe703 "/home/sergio"'.  A similar
situation happens with the "dir" variable, which is printed as:

  (gdb) print dir
  $1 = "/home/sergio/work/src/git/binutils-gdb/set-cwd-command/build-64", '\000' <repeats 4032 times>

I remember being able to workaround these limitations with
"get_valueof", but in the end I decided it was better to just use
"gdb_test_multiple".

>> +
>> +	if { [string length $home] > 0 } {
>
> This check can then go away.

Done.

>> +	    gdb_test_multiple "print dir" "print dir var" {
>> +		-re "\\\$$decimal = \"\(.+\)\"\(, .*repeats.*\)?\r\n$gdb_prompt $" {
>> +		    set curdir $expect_out(1,string)
>> +		}
>> +		-re "$gdb_prompt $" {
>> +		    fail "failed to retrieve dir var"
>> +		    return -1
>> +		}
>> +		default {
>> +		    fail "failed to retrieve dir var"
>> +		    return -1
>> +		}
>> +	    }
>
> And here you'd apply the same pattern.

Done.

>
>
>> +
>> +	    gdb_assert [string equal $curdir $home] \
>> +		"successfully chdir'd into home"
>> +	} else {
>> +	    untested "could not determine value of HOME"
>> +	    return
>> +	}
>> +    }
>> +}
>> +
>> +# The temporary directory that we will use to start the inferior.
>> +set tmpdir [standard_output_file ""]
>> +
>> +# Test that when we "set cwd" the inferior will be started under the
>> +# correct working directory and GDB will not be affected by this.
>> +
>> +proc test_cd_into_dir { } {
>> +    global decimal gdb_prompt tmpdir
>> +
>> +    with_test_prefix "test cd into temp dir" {
>> +	gdb_test_multiple "pwd" "pwd before run" {
>> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
>> +		set gdb_cwd_before_run $expect_out(1,string)
>> +	    }
>> +	    -re ".*$gdb_prompt $" {
>> +		fail "failed to obtain GDB cwd before run"
>> +		return -1
>> +	    }
>> +	    default {
>> +		fail "failed to obtain GDB cwd before run"
>> +		return -1
>> +	    }
>> +	}
>
> Ditto.  (This appears multiple times throughout.)

Updated this and the other instance of this pattern.

>> +
>> +	# This test only makes sense if $tmpdir != $gdb_cwd_before_run
>> +	if { ![gdb_assert ![string equal $tmpdir $gdb_cwd_before_run] \
>> +		   "make sure that tmpdir and GDB's cwd are different"] } {
>> +	    return -1
>> +	}
>> +
>> +	gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
>> +
>> +	if { ![runto_main] } {
>> +	    untested "could not run to main"
>> +	    return -1
>> +	}
>> +
>> +	gdb_breakpoint [gdb_get_line_number "break-here"]
>> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>> +
>> +	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
>> +	    "inferior cwd is correctly set"
>> +
>> +	gdb_test_multiple "pwd" "pwd after run" {
>> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
>> +		set gdb_cwd_after_run $expect_out(1,string)
>> +	    }
>> +	    -re ".*$gdb_prompt $" {
>> +		fail "failed to obtain GDB cwd after run"
>> +		return -1
>> +	    }
>> +	    default {
>> +		fail "failed to obtain GDB cwd after run"
>> +		return -1
>> +	    }
>> +	}
>> +
>> +	gdb_assert [string equal $gdb_cwd_before_run $gdb_cwd_after_run] \
>> +	    "GDB cwd is unchanged after running inferior"
>> +    }
>> +}
>> +
>> +# Test that executing "set cwd" without arguments will reset the
>> +# inferior's cwd setting to its previous state.
>> +
>> +proc test_cwd_reset { } {
>> +    global decimal gdb_prompt tmpdir
>> +
>> +    with_test_prefix "test inferior cwd reset" {
>> +	gdb_test_multiple "pwd" "GDB cwd" {
>> +	    -re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
>> +		set gdb_cwd $expect_out(1,string)
>> +	    }
>> +	    -re ".*$gdb_prompt $" {
>> +		fail "failed to obtain GDB cwd before run"
>> +		return -1
>> +	    }
>> +	    default {
>> +		fail "failed to obtain GDB cwd before run"
>> +		return -1
>> +	    }
>> +	}
>> +
>> +	# This test only makes sense if $tmpdir != $gdb_cwd
>> +	# This test only makes sense if $tmpdir != $gdb_cwd
>
> Duplicate comment.  And missing period.

Fixed.

>> +	if { ![gdb_assert ![string equal $tmpdir $gdb_cwd] \
>> +		   "make sure that tmpdir and GDB's cwd are different"] } {
>> +	    return -1
>> +	}
>> +
>> +	gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
>> +
>> +	if { ![runto_main] } {
>> +	    untested "could not run to main"
>> +	    return -1
>> +	}
>> +
>> +	gdb_breakpoint [gdb_get_line_number "break-here"]
>> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>> +
>> +	gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
>> +	    "inferior cwd is correctly set"
>> +
>> +	# Reset the inferior's cwd.
>> +	gdb_test_no_output "set cwd" "resetting inferior cwd"
>> +
>> +	if { ![runto_main] } {
>> +	    untested "could not run to main"
>> +	    return -1
>> +	}
>
> Wrap each runto_main invocation in its own with_test_prefix,
> so that if any fails we get unique test names in gdb.sum.

OK.

>> +
>> +	gdb_breakpoint [gdb_get_line_number "break-here"]
>> +	gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>> +
>> +	gdb_test "print dir" "\\\$$decimal = \"$gdb_cwd\", .*" \
>> +	    "inferior cwd got reset correctly"
>> +    }
>> +}
>> +
>> +test_cd_into_dir
>> +clean_restart $binfile
>> +test_tilde_expansion
>> +clean_restart $binfile
>> +test_cwd_reset
>> diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
>> index 3e1894410d..5144e9f7a6 100644
>> --- a/gdb/windows-nat.c
>> +++ b/gdb/windows-nat.c
>> @@ -66,6 +66,7 @@
>>  #include "x86-nat.h"
>>  #include "complaints.h"
>>  #include "inf-child.h"
>> +#include "gdb_tilde_expand.h"
>>  
>>  #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
>>  #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
>> @@ -2432,6 +2433,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>    cygwin_buf_t *toexec;
>>    cygwin_buf_t *cygallargs;
>>    cygwin_buf_t *args;
>> +  cygwin_buf_t *infcwd;
>>    char **old_env = NULL;
>>    PWCHAR w32_env;
>>    size_t len;
>> @@ -2461,6 +2463,8 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>    BOOL ret;
>>    DWORD flags = 0;
>>    const char *inferior_io_terminal = get_inferior_io_terminal ();
>> +  const char *inferior_cwd = get_inferior_cwd ();
>> +  std::string expanded_infcwd = gdb_tilde_expand (inferior_cwd);
>
> Does gdb_tilde_expand work with NULL input ?

You're right, I should check for NULL here as well.

>>  
>>    if (!exec_file)
>>      error (_("No executable specified, use `target exec'."));
>> @@ -2514,6 +2518,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>        flags |= DEBUG_PROCESS;
>>      }
>>  
>> +  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, expanded_infcwd.c_str (),
>> +			infcwd, expanded_infcwd.size ()) < 0)
>> +    error (_("Error converting inferior cwd: %d"), errno);
>
> I don't see how this can work.  'infcwd' was never initialized to
> point at some buffer?  It's garbage.  I think you're supposed to
> call this twice, once to determine the needed size, and then
> another to fill in a buffer of that size.

You're right.  I see that there are other paths being declared in this
function:

  ...
  cygwin_buf_t real_path[__PMAX];
  cygwin_buf_t shell[__PMAX]; /* Path to shell */
  ...

So I think a better way is to follow the convention and declare "infcwd"
with "__PMAX" size.  That's what I did.

Thanks,

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

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

* Re: [PATCH v3 5/5] Extend "set cwd" to work on gdbserver
  2017-09-29 14:03         ` Pedro Alves
@ 2017-09-29 18:33           ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 18:33 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Friday, September 29 2017, Pedro Alves wrote:

>> It's @kbd (from "keyboard").  But I know, our muscle memory wants us to
>> type "db" :-P.
>
> ;-)
>
>> 
>> Even though I slightly disagree here (commands are not keybindings), I
>> found that this is indeed what GDB uses.  Anyway, using @kbd now.
>
> See discussion starting here:
>
>   https://sourceware.org/ml/gdb-patches/2017-06/msg00592.html

Aha.  Thanks for the reference.

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

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

* Re: [PATCH v4 3/3] Extend "set cwd" to work on gdbserver
  2017-09-29 15:21     ` Pedro Alves
@ 2017-09-29 18:48       ` Sergio Durigan Junior
  2017-10-03 15:13         ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 18:48 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Friday, September 29 2017, Pedro Alves wrote:

> On 09/28/2017 05:10 AM, Sergio Durigan Junior wrote:
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -26,6 +26,14 @@
>>  
>>  * New features in the GDB remote stub, GDBserver
>>  
>> +  ** GDBserver is now able to set the inferior's current working
>> +     directory.
>
> That's confusing IMO, because it sounds like you're saying
> you can change the inferior's current working directory at
> any time, even on inferiors that are already running...
>
> I'd go for:
>
>   ** GDBserver is now able to start inferior processes with a
>      specified initial working directory.

OK, changed.

>> +
>> +     The user can set the desired working directory to be used by the
>> +     remote inferior on GDB, using the new "set cwd" command, which
>> +     will instruct GDB to tell GDBserver about this directory change
>> +     the next time an inferior is run.
>
> And instead of the above, say:
>
>      The user can set the desired working directory to be used from GDB
>      using the new "set cwd" command.
>
> Note "on" -> "from".  I think that conveys it better.
>
> The "which will instruct" part is distracting and unnecessary
> implementation detail, IMO.

Done.

>
>> +@item QSetWorkingDir:@r{[}@var{directory}@r{]}
>> +@anchor{QSetWorkingDir packet}
>> +@cindex set working directory, remote request
>> +@cindex @samp{QSetWorkingDir} packet
>> +This packet is used to inform the remote server of the intended
>> +current working directory for programs that are going to be executed.
>> +
>> +The packet is composed by @var{directory}, an hex encoded
>> +representation of the directory that the remote inferior will use as
>> +its current working directory.  If @var{directory} is an empty string,
>> +the remote server should reset the inferior's current working
>> +directory to its original, empty value.
>> +
>> +This packet is always transmitted when the inferior is run.  If the
>> +user has not explcitly specified a directory with the @kbd{set cwd}
>
> typo: explicitly

Fixed.

>> +command, then an empty packet will be sent to the remote server, which
>
> Not an empty packet, and empty directory.  Really-empty packets are 
> special in the remote protocol.
>
>> +will have no effect.  
>
> WDYM will have no effect, when just above you've explained that empty
> means reset ?  I think you should just remove this paragraph starting
> with "This packet is always transmitted".  That's implementation
> detail.  GDB could for example not resend the packet if the value
> didn't change between runs, no?

What I tried to say is that if the user doesn't make use of the "set
cwd" command in a GDB session, the packet will be transmitted anyway.  I
think I should have been clearer here.

I will remove the paragraph as requested.

>> Otherwise, the specified inferior's working
>> +directory will be transmitted (@pxref{Working Directory, ,Your
>> +Program's Working Directory}).
>
> This too should be tweaked accordingly.

Since the whole paragraph has been removed, then this comment doesn't
apply anymore, I assume.

Thanks,

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

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

* [PATCH v5 0/3] New "set cwd" command
  2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
                   ` (8 preceding siblings ...)
  2017-09-28  4:10 ` [PATCH v4 0/3] New "set cwd" command Sergio Durigan Junior
@ 2017-09-29 22:58 ` Sergio Durigan Junior
  2017-09-29 22:59   ` [PATCH v5 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
                     ` (2 more replies)
  9 siblings, 3 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 22:58 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii

v1: https://sourceware.org/ml/gdb-patches/2017-09/msg00321.html
v2: https://sourceware.org/ml/gdb-patches/2017-09/msg00458.html
v3: https://sourceware.org/ml/gdb-patches/2017-09/msg00658.html
v4: https://sourceware.org/ml/gdb-patches/2017-09/msg00846.html

Changes from v4:

* Patch #1:

  - s/HAVE_GDB_TILDE_EXPAND_H/GDB_TILDE_EXPAND_H/ on
    gdb/common/gdb_tilde_expand.h.

* Patch #2:

  - Include more rationale/details about the "set/show cwd" commands
    in the commit log.

  - Improve set cwd code flow on fork_inferior.

  - Remove <stdio.h> inclusion from gdb.base/set-cwd.c

  - Don't mention "gdbserver" on "untested" message at
    gdb/set-cwd.exp.  Instead, say "remote server".

  - s/proc + with_test_prefix/proc_with_prefix/

  - Fix typos.

  - Rewrite certain tests to take timeout scenarios into account.

  - Uniquefy "runto_main" messages.

  - Rewrite parts of Windows code in order to (a) take into account
    when "inferior_cwd" is NULL, and (b) create a proper buffer to be
    filled by "cygwin_conv_path".

* Patch #3:

  - Rewrite gdb/NEWS entry in order to remove the confusion about when
    gdbserver is able to change the inferior's cwd.

  - Fix typos.

  - Rewrite/remove paragraph explaining when the "QSetWorkingDir"
    packet is sent by GDB.


This patch series is a followup of the discussion that happened at:

  https://sourceware.org/ml/gdb-patches/2017-09/msg00160.html

It implements a new GDB command, "set cwd", which is used to set the
current working directory of the inferior that will be started.  This
command works for both native and remote debugging scenarios.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.

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

* [PATCH v5 3/3] Extend "set cwd" to work on gdbserver
  2017-09-29 22:58 ` [PATCH v5 0/3] New "set cwd" command Sergio Durigan Junior
@ 2017-09-29 22:59   ` Sergio Durigan Junior
  2017-10-03 15:15     ` Pedro Alves
  2017-09-29 22:59   ` [PATCH v5 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
  2017-09-29 22:59   ` [PATCH v5 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii, Sergio Durigan Junior

This is the "natural" extension necessary for the "set cwd" command
(and the whole "set the inferior's cwd" logic) to work on gdbserver.

The idea here is to have a new remote packet, QSetWorkingDir (name
adopted from LLDB's extension to the RSP, as can be seen at
<https://raw.githubusercontent.com/llvm-mirror/lldb/master/docs/lldb-gdb-remote.txt>),
which sends an hex-encoded string representing the working directory
that the remote inferior will use.  There is a slight difference from
the packet proposed by LLDB: GDB's version will accept empty
arguments, meaning that the user wants to clear the previously set
working directory for the inferior (i.e., "set cwd" without arguments
on GDB).

For UNIX-like targets this feature is already implemented on
nat/fork-inferior.c, and all gdbserver has to do is to basically
implement "set_inferior_cwd" and call it whenever such packet arrives.
For other targets, like Windows, it is possible to use the existing
"get_inferior_cwd" function and do the necessary steps to make sure
that the inferior will use the specified working directory.

Aside from that, the patch consists basically of updates to the
testcase (making it available on remote targets) and the
documentation.

No regressions found.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (Changes since GDB 8.0): Add entry about new
	'set-cwd-on-gdbserver' feature.
	(New remote packets): Add entry for QSetWorkingDir.
	* common/common-inferior.h (set_inferior_cwd): New prototype.
	* infcmd.c (set_inferior_cwd): Remove "static".
	(show_cwd_command): Expand text to include remote debugging.
	* remote.c: Add PACKET_QSetWorkingDir.
	(remote_protocol_features) <QSetWorkingDir>: New entry for
	PACKET_QSetWorkingDir.
	(extended_remote_set_inferior_cwd): New function.
	(extended_remote_create_inferior): Call
	"extended_remote_set_inferior_cwd".
	(_initialize_remote): Call "add_packet_config_cmd" for
	QSetWorkingDir.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (set_inferior_cwd): New function.
	* server.c (handle_general_set): Handle QSetWorkingDir packet.
	(handle_query): Inform that QSetWorkingDir is supported.
	* win32-low.c (create_process): Pass the inferior's cwd to
	CreateProcess.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.exp: Make it available on
	native-extended-gdbserver.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention remote debugging.
	(Working Directory) <Your Program's Working Directory>:
	Likewise.
	(Connecting) <Remote Packet>: Add "set-working-dir"
	and "QSetWorkingDir" to the table.
	(Remote Protocol) <QSetWorkingDir>: New item, explaining the
	packet.
---
 gdb/NEWS                           | 10 ++++++++
 gdb/common/common-inferior.h       |  4 ++++
 gdb/doc/gdb.texinfo                | 36 ++++++++++++++++++++++++++---
 gdb/gdbserver/inferiors.c          | 12 ++++++++++
 gdb/gdbserver/server.c             | 32 +++++++++++++++++++++++++-
 gdb/gdbserver/win32-low.c          | 22 +++++++++++++++---
 gdb/infcmd.c                       |  8 +++----
 gdb/remote.c                       | 47 ++++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/set-cwd.exp |  4 ++--
 9 files changed, 162 insertions(+), 13 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index fcf454833f..2bad096a86 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -26,6 +26,12 @@
 
 * New features in the GDB remote stub, GDBserver
 
+  ** GDBserver is now able to start inferior processes with a
+     specified initial working directory.
+
+     The user can set the desired working directory to be used from
+     GDB using the new "set cwd" command.
+
   ** New "--selftest" command line option runs some GDBserver self
      tests.  These self tests are disabled in releases.
 
@@ -59,6 +65,10 @@ QEnvironmentReset
 QStartupWithShell
   Indicates whether the inferior must be started with a shell or not.
 
+QSetWorkingDir
+  Tell GDBserver that the inferior to be started should use a specific
+  working directory.
+
 * The "maintenance print c-tdesc" command now takes an optional
   argument which is the file name of XML target description.
 
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 515a8c0f4e..3dcfda3e7b 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -34,4 +34,8 @@ extern char *get_exec_file (int err);
    been set, then return NULL.  */
 extern const char *get_inferior_cwd ();
 
+/* Set the inferior current working directory.  If CWD is NULL, unset
+   the directory.  */
+extern void set_inferior_cwd (const char *cwd);
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0d059603cf..cf7e51a0db 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2059,8 +2059,10 @@ your program.  @xref{Environment, ,Your Program's Environment}.
 @item The @emph{working directory.}
 You can set your program's working directory with the command
 @kbd{set cwd}.  If you do not set any working directory with this
-command, your program will inherit @value{GDBN}'s working directory.
-@xref{Working Directory, ,Your Program's Working Directory}.
+command, your program will inherit @value{GDBN}'s working directory if
+native debugging, or the remote server's working directory if remote
+debugging.  @xref{Working Directory, ,Your Program's Working
+Directory}.
 
 @item The @emph{standard input and output.}
 Your program normally uses the same device for standard input and
@@ -2439,7 +2441,9 @@ Each time you start your program with @code{run}, the inferior will be
 initialized with the current working directory specified by the
 @kbd{set cwd} command.  If no directory has been specified by this
 command, then the inferior will inherit @value{GDBN}'s current working
-directory as its working directory.
+directory as its working directory if native debugging, or it will
+inherit the remote server's current working directory if remote
+debugging.
 
 You can also change @value{GDBN}'s current working directory by using
 the @code{cd} command.
@@ -20999,6 +21003,10 @@ are:
 @tab @code{QEnvironmentReset}
 @tab @code{Reset the inferior environment (i.e., unset user-set variables)}
 
+@item @code{set-working-dir}
+@tab @code{QSetWorkingDir}
+@tab @code{set cwd}
+
 @item @code{conditional-breakpoints-packet}
 @tab @code{Z0 and Z1}
 @tab @code{Support for target-side breakpoint condition evaluation}
@@ -36856,6 +36864,28 @@ by supplying an appropriate @samp{qSupported} response
 actually support passing environment variables to the starting
 inferior.
 
+@item QSetWorkingDir:@r{[}@var{directory}@r{]}
+@anchor{QSetWorkingDir packet}
+@cindex set working directory, remote request
+@cindex @samp{QSetWorkingDir} packet
+This packet is used to inform the remote server of the intended
+current working directory for programs that are going to be executed.
+
+The packet is composed by @var{directory}, an hex encoded
+representation of the directory that the remote inferior will use as
+its current working directory.  If @var{directory} is an empty string,
+the remote server should reset the inferior's current working
+directory to its original, empty value.
+
+This packet is only available in extended mode (@pxref{extended
+mode}).
+
+Reply:
+@table @samp
+@item OK
+The request succeeded.
+@end table
+
 @item qfThreadInfo
 @itemx qsThreadInfo
 @cindex list active threads, remote request
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 57d9956ebb..154c167f4c 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -456,3 +456,15 @@ get_inferior_cwd ()
 {
   return current_inferior_cwd;
 }
+
+/* See common/common-inferior.h.  */
+
+void
+set_inferior_cwd (const char *cwd)
+{
+  xfree ((void *) current_inferior_cwd);
+  if (cwd != NULL)
+    current_inferior_cwd = xstrdup (cwd);
+  else
+    current_inferior_cwd = NULL;
+}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index c4f1e8dde6..a95973547c 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -869,6 +869,35 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QSetWorkingDir:"))
+    {
+      const char *p = own_buf + strlen ("QSetWorkingDir:");
+
+      if (*p != '\0')
+	{
+	  std::string path = hex2str (p);
+
+	  set_inferior_cwd (path.c_str ());
+
+	  if (remote_debug)
+	    debug_printf (_("[Set the inferior's current directory to %s]\n"),
+			  path.c_str ());
+	}
+      else
+	{
+	  /* An empty argument means that we should clear out any
+	     previously set cwd for the inferior.  */
+	  set_inferior_cwd (NULL);
+
+	  if (remote_debug)
+	    debug_printf (_("\
+[Unset the inferior's current directory; will use gdbserver's cwd]\n"));
+	}
+      write_ok (own_buf);
+
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -2351,7 +2380,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       sprintf (own_buf,
 	       "PacketSize=%x;QPassSignals+;QProgramSignals+;"
 	       "QStartupWithShell+;QEnvironmentHexEncoded+;"
-	       "QEnvironmentReset+;QEnvironmentUnset+",
+	       "QEnvironmentReset+;QEnvironmentUnset+;"
+	       "QSetWorkingDir+",
 	       PBUFSIZ - 1);
 
       if (target_supports_catch_syscall ())
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index cc84d15c2f..c11926f7c6 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -32,6 +32,7 @@
 #include <tlhelp32.h>
 #include <psapi.h>
 #include <process.h>
+#include "gdb_tilde_expand.h"
 
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>
@@ -562,10 +563,12 @@ static BOOL
 create_process (const char *program, char *args,
 		DWORD flags, PROCESS_INFORMATION *pi)
 {
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd = gdb_tilde_expand (inferior_cwd);
   BOOL ret;
 
 #ifdef _WIN32_WCE
-  wchar_t *p, *wprogram, *wargs;
+  wchar_t *p, *wprogram, *wargs, *wcwd = NULL;
   size_t argslen;
 
   wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
@@ -579,6 +582,19 @@ create_process (const char *program, char *args,
   wargs = alloca ((argslen + 1) * sizeof (wchar_t));
   mbstowcs (wargs, args, argslen + 1);
 
+  if (inferior_cwd != NULL)
+    {
+      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+		    '/', '\\');
+      wcwd = alloca ((expanded_infcwd.size () + 1) * sizeof (wchar_t));
+      if (mbstowcs (wcwd, expanded_infcwd.c_str (),
+		    expanded_infcwd.size () + 1) == NULL)
+	{
+	  error (_("\
+Could not convert the expanded inferior cwd to wide-char."));
+	}
+    }
+
   ret = CreateProcessW (wprogram, /* image name */
 			wargs,    /* command line */
 			NULL,     /* security, not supported */
@@ -586,7 +602,7 @@ create_process (const char *program, char *args,
 			FALSE,    /* inherit handles, not supported */
 			flags,    /* start flags */
 			NULL,     /* environment, not supported */
-			NULL,     /* current directory, not supported */
+			wcwd,     /* current directory */
 			NULL,     /* start info, not supported */
 			pi);      /* proc info */
 #else
@@ -599,7 +615,7 @@ create_process (const char *program, char *args,
 			TRUE,     /* inherit handles */
 			flags,    /* start flags */
 			NULL,     /* environment */
-			NULL,     /* current directory */
+			expanded_infcwd.c_str (), /* current directory */
 			&si,      /* start info */
 			pi);      /* proc info */
 #endif
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index dbdf273ca5..187c71f344 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -242,10 +242,9 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
-/* Set the inferior current working directory.  If CWD is NULL, unset
-   the directory.  */
+/* See common/common-inferior.h.  */
 
-static void
+void
 set_inferior_cwd (const char *cwd)
 {
   struct inferior *inf = current_inferior ();
@@ -289,7 +288,8 @@ show_cwd_command (struct ui_file *file, int from_tty,
     fprintf_filtered (gdb_stdout,
 		      _("\
 You have not set the inferior's current working directory.\n\
-The inferior will inherit GDB's cwd.\n"));
+The inferior will inherit GDB's cwd if native debugging, or the remote\n\
+server's cwd if remote debugging.\n"));
   else
     fprintf_filtered (gdb_stdout,
 		      _("Current working directory that will be used "
diff --git a/gdb/remote.c b/gdb/remote.c
index 54d810f054..fc27ffd790 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1430,6 +1430,7 @@ enum {
   PACKET_QPassSignals,
   PACKET_QCatchSyscalls,
   PACKET_QProgramSignals,
+  PACKET_QSetWorkingDir,
   PACKET_QStartupWithShell,
   PACKET_QEnvironmentHexEncoded,
   PACKET_QEnvironmentReset,
@@ -4662,6 +4663,8 @@ static const struct protocol_feature remote_protocol_features[] = {
     PACKET_QCatchSyscalls },
   { "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
     PACKET_QProgramSignals },
+  { "QSetWorkingDir", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QSetWorkingDir },
   { "QStartupWithShell", PACKET_DISABLE, remote_supported_packet,
     PACKET_QStartupWithShell },
   { "QEnvironmentHexEncoded", PACKET_DISABLE, remote_supported_packet,
@@ -9641,6 +9644,45 @@ extended_remote_environment_support (struct remote_state *rs)
       send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
 }
 
+/* Helper function to set the current working directory for the
+   inferior in the remote.  */
+
+static void
+extended_remote_set_inferior_cwd (struct remote_state *rs)
+{
+  if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
+    {
+      const char *inferior_cwd = get_inferior_cwd ();
+
+      if (inferior_cwd != NULL)
+	{
+	  std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
+					 strlen (inferior_cwd));
+
+	  xsnprintf (rs->buf, get_remote_packet_size (),
+		     "QSetWorkingDir:%s", hexpath.c_str ());
+	}
+      else
+	{
+	  /* An empty inferior_cwd means that the user wants us to
+	     reset the remote server's inferior's cwd.  */
+	  xsnprintf (rs->buf, get_remote_packet_size (),
+		     "QSetWorkingDir:");
+	}
+
+      putpkt (rs->buf);
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      if (packet_ok (rs->buf,
+		     &remote_protocol_packets[PACKET_QSetWorkingDir])
+	  != PACKET_OK)
+	error (_("\
+Remote replied unexpectedly while setting the inferior's working\n\
+directory: %s"),
+	       rs->buf);
+
+    }
+}
+
 /* In the extended protocol we want to be able to do things like
    "run" and have them basically work as expected.  So we need
    a special create_inferior function.  We support changing the
@@ -9683,6 +9725,8 @@ Remote replied unexpectedly while setting startup-with-shell: %s"),
 
   extended_remote_environment_support (rs);
 
+  extended_remote_set_inferior_cwd (rs);
+
   /* Now restart the remote server.  */
   run_worked = extended_remote_run (args) != -1;
   if (!run_worked)
@@ -14190,6 +14234,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
 			 "QProgramSignals", "program-signals", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QSetWorkingDir],
+			 "QSetWorkingDir", "set-working-dir", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartupWithShell],
 			 "QStartupWithShell", "startup-with-shell", 0);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
index bbb8d006a4..64462704c9 100644
--- a/gdb/testsuite/gdb.base/set-cwd.exp
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -15,8 +15,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
-    untested "not implemented on remote servers"
+if { [use_gdb_stub] } {
+    untested "skipping tests due to use_gdb_stub"
     return
 }
 
-- 
2.13.3

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

* [PATCH v5 1/3] Introduce gdb_tilde_expand
  2017-09-29 22:58 ` [PATCH v5 0/3] New "set cwd" command Sergio Durigan Junior
  2017-09-29 22:59   ` [PATCH v5 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
  2017-09-29 22:59   ` [PATCH v5 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
@ 2017-09-29 22:59   ` Sergio Durigan Junior
  2017-10-03 15:15     ` Pedro Alves
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii, Sergio Durigan Junior

Currently, whenever we want to handle paths provided by the user and
perform tilde expansion on GDB, we rely on "tilde_expand", which comes
from readline.  This was enough for our use cases so far, but the
situation will change when we start dealing with paths on gdbserver as
well, which is what the next patches implement.

Unfortunately it is not possible to use "tilde_expand" in this case
because gdbserver doesn't use readline.  For that reason I decided to
implement a new "gdb_tilde_expand" function, which is basically a
wrapper for "glob" and its GNU extension, GLOB_TILDE_CHECK.  With the
import of the "glob" module from gnulib, this is a no-brainer.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add gdb_tilde_expand.c.
	(HFILES_NO_SRCDIR): Add gdb_tilde_expand.h.
	(COMMON_OBS): Add gdb_tilde_expand.o.
	* common/gdb_tilde_expand.c: New file.
	* common/gdb_tilde_expand.h: Likewise.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* Makefile.in (SFILES): Add $(srcdir)/common/gdb_tilde_expand.c.
	(OBS): Add gdb_tilde_expand.o.
---
 gdb/Makefile.in               |  3 ++
 gdb/common/gdb_tilde_expand.c | 82 +++++++++++++++++++++++++++++++++++++++++++
 gdb/common/gdb_tilde_expand.h | 27 ++++++++++++++
 gdb/gdbserver/Makefile.in     |  2 ++
 4 files changed, 114 insertions(+)
 create mode 100644 gdb/common/gdb_tilde_expand.c
 create mode 100644 gdb/common/gdb_tilde_expand.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index f3f1d404ba..9454e3a62f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1248,6 +1248,7 @@ SFILES = \
 	common/filestuff.c \
 	common/format.c \
 	common/job-control.c \
+	common/gdb_tilde_expand.c \
 	common/gdb_vecs.c \
 	common/new-op.c \
 	common/print-utils.c \
@@ -1532,6 +1533,7 @@ HFILES_NO_SRCDIR = \
 	common/fileio.h \
 	common/format.h \
 	common/gdb_assert.h \
+	common/gdb_tilde_expand.h \
 	common/gdb_locale.h \
 	common/gdb_setjmp.h \
 	common/gdb_signals.h \
@@ -1737,6 +1739,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	frame-unwind.o \
 	gcore.o \
 	gdb_bfd.o \
+	gdb_tilde_expand.o \
 	gdb-dlfcn.o \
 	gdb_obstack.o \
 	gdb_regex.o \
diff --git a/gdb/common/gdb_tilde_expand.c b/gdb/common/gdb_tilde_expand.c
new file mode 100644
index 0000000000..8dd94239f9
--- /dev/null
+++ b/gdb/common/gdb_tilde_expand.c
@@ -0,0 +1,82 @@
+/* Perform tilde expansion on paths for GDB and gdbserver.
+
+   Copyright (C) 2017 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 "gdb_tilde_expand.h"
+#include <glob.h>
+
+/* RAII-style class wrapping "glob".  */
+
+class gdb_glob
+{
+public:
+  /* Construct a "gdb_glob" object by calling "glob" with the provided
+     parameters.  This function can throw if "glob" fails.  */
+  gdb_glob (const char *pattern, int flags,
+	    int (*errfunc) (const char *epath, int eerrno))
+  {
+    int ret = glob (pattern, flags, errfunc, &m_glob);
+
+    if (ret != 0)
+      {
+	if (ret == GLOB_NOMATCH)
+	  error (_("Could not find a match for '%s'."), pattern);
+	else
+	  error (_("glob could not process pattern '%s'."),
+		 pattern);
+      }
+  }
+
+  /* Destroy the object and free M_GLOB.  */
+  ~gdb_glob ()
+  {
+    globfree (&m_glob);
+  }
+
+  /* Return the GL_PATHC component of M_GLOB.  */
+  int pathc () const
+  {
+    return m_glob.gl_pathc;
+  }
+
+  /* Return the GL_PATHV component of M_GLOB.  */
+  char **pathv () const
+  {
+    return m_glob.gl_pathv;
+  }
+
+private:
+  /* The actual glob object we're dealing with.  */
+  glob_t m_glob;
+};
+
+/* See common/gdb_tilde_expand.h.  */
+
+std::string
+gdb_tilde_expand (const char *dir)
+{
+  gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
+
+  gdb_assert (glob.pathc () > 0);
+  /* "glob" may return more than one match to the path provided by the
+     user, but we are only interested in the first match.  */
+  std::string expanded_dir = glob.pathv ()[0];
+
+  return expanded_dir;
+}
diff --git a/gdb/common/gdb_tilde_expand.h b/gdb/common/gdb_tilde_expand.h
new file mode 100644
index 0000000000..2ec0563d9a
--- /dev/null
+++ b/gdb/common/gdb_tilde_expand.h
@@ -0,0 +1,27 @@
+/* Perform tilde expansion on paths for GDB and gdbserver.
+
+   Copyright (C) 2017 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 GDB_TILDE_EXPAND_H
+#define GDB_TILDE_EXPAND_H
+
+/* Perform path expansion (i.e., tilde expansion) on DIR, and return
+   the full path.  */
+extern std::string gdb_tilde_expand (const char *dir);
+
+#endif /* ! GDB_TILDE_EXPAND_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 1bbe515629..6c931ba952 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -205,6 +205,7 @@ SFILES = \
 	$(srcdir)/common/fileio.c \
 	$(srcdir)/common/filestuff.c \
 	$(srcdir)/common/job-control.c \
+	$(srcdir)/common/gdb_tilde_expand.c \
 	$(srcdir)/common/gdb_vecs.c \
 	$(srcdir)/common/new-op.c \
 	$(srcdir)/common/print-utils.c \
@@ -247,6 +248,7 @@ OBS = \
 	fileio.o \
 	filestuff.o \
 	format.o \
+	gdb_tilde_expand.o \
 	gdb_vecs.o \
 	hostio.o \
 	inferiors.o \
-- 
2.13.3

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

* [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-09-29 22:58 ` [PATCH v5 0/3] New "set cwd" command Sergio Durigan Junior
  2017-09-29 22:59   ` [PATCH v5 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
@ 2017-09-29 22:59   ` Sergio Durigan Junior
  2017-10-03 15:15     ` Pedro Alves
  2017-09-29 22:59   ` [PATCH v5 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
  2 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-09-29 22:59 UTC (permalink / raw)
  To: GDB Patches; +Cc: Pedro Alves, Eli Zaretskii, Sergio Durigan Junior

This is the actual implementation of the "set/show cwd" commands,
which are used to set/show the current working directory of the
inferior that will be started.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.

"set cwd" works in the following way:

- If the user sets the inferior's cwd by using "set cwd", then this
  directory is saved into current_inferior ()->cwd and is used when
  the inferior is started (see below).

- If the user doesn't set the inferior's cwd by using "set cwd", but
  rather use the "cd" command as before, then this directory is
  inherited by the inferior because GDB will have chdir'd into it.

On Unix-like hosts, the way the directory is changed before the
inferior execution is by expanding the user set directory before the
fork, and then "chdir" after the call to fork/vfork on
"fork_inferior", but before the actual execution.  On Windows, the
inferior cwd set by the user is passed directly to the CreateProcess
call, which takes care of the actual chdir for us.

This way, we'll make sure that GDB's cwd is not affected by the user
set cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (New commands): Mention "set/show cwd".
	* cli/cli-cmds.c (_initialize_cli_cmds): Mention "set cwd" on
	"cd" command's help text.
	* common/common-inferior.h (get_inferior_cwd): New prototype.
	* infcmd.c (inferior_cwd_scratch): New global variable.
	(set_inferior_cwd): New function.
	(get_inferior_cwd): Likewise.
	(set_cwd_command): Likewise.
	(show_cwd_command): Likewise.
	(_initialize_infcmd): Add "set/show cwd" commands.
	* inferior.h (class inferior) <cwd>: New field.
	* nat/fork-inferior.c: Include "gdb_tilde_expand.h".
	(fork_inferior): Change inferior's cwd before its execution.
	* windows-nat.c (windows_create_inferior): Pass inferior's cwd
	to CreateProcess.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (current_inferior_cwd): New global variable.
	(get_inferior_cwd): New function.
	* inferiors.h (struct process_info) <cwd>: New field.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention new "set cwd" command.
	(Working Directory) <Your Program's Working Directory>:
	Rephrase to explain that "set cwd" exists and is the default
	way to change the inferior's cwd.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.c: New file.
	* gdb.base/set-cwd.exp: Likewise.
---
 gdb/NEWS                           |   3 +
 gdb/cli/cli-cmds.c                 |   8 +-
 gdb/common/common-inferior.h       |   4 +
 gdb/doc/gdb.texinfo                |  41 ++++++--
 gdb/gdbserver/inferiors.c          |  11 +++
 gdb/infcmd.c                       |  77 +++++++++++++++
 gdb/inferior.h                     |   4 +
 gdb/nat/fork-inferior.c            |  23 +++++
 gdb/testsuite/gdb.base/set-cwd.c   |  31 ++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 198 +++++++++++++++++++++++++++++++++++++
 gdb/windows-nat.c                  |  21 +++-
 11 files changed, 408 insertions(+), 13 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.c
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 81c21b82cc..fcf454833f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -67,6 +67,9 @@ QStartupWithShell
 
 * New commands
 
+set|show cwd
+  Set and show the current working directory for the inferior.
+
 set|show compile-gcc
   Set and show compilation command used for compiling and injecting code
   with the 'compile' commands.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index dde67ee2b3..dad5ffa42e 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1727,9 +1727,11 @@ The commands below can be used to select other frames by number or address."),
 Print working directory.  This is used for your program as well."));
 
   c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+The debugger's current working directory specifies where scripts and other\n\
+files that can be loaded by GDB are located.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_com ("echo", class_support, echo_command, _("\
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 87c13009ed..515a8c0f4e 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
    otherwise return 0 in that case.  */
 extern char *get_exec_file (int err);
 
+/* Return the inferior's current working directory.  If nothing has
+   been set, then return NULL.  */
+extern const char *get_inferior_cwd ();
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9905ff6513..0d059603cf 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
 your program.  @xref{Environment, ,Your Program's Environment}.
 
 @item The @emph{working directory.}
-Your program inherits its working directory from @value{GDBN}.  You can set
-the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+You can set your program's working directory with the command
+@kbd{set cwd}.  If you do not set any working directory with this
+command, your program will inherit @value{GDBN}'s working directory.
 @xref{Working Directory, ,Your Program's Working Directory}.
 
 @item The @emph{standard input and output.}
@@ -2434,19 +2435,43 @@ variables to files that are only run when you sign on, such as
 @section Your Program's Working Directory
 
 @cindex working directory (of your program)
-Each time you start your program with @code{run}, it inherits its
-working directory from the current working directory of @value{GDBN}.
-The @value{GDBN} working directory is initially whatever it inherited
-from its parent process (typically the shell), but you can specify a new
-working directory in @value{GDBN} with the @code{cd} command.
+Each time you start your program with @code{run}, the inferior will be
+initialized with the current working directory specified by the
+@kbd{set cwd} command.  If no directory has been specified by this
+command, then the inferior will inherit @value{GDBN}'s current working
+directory as its working directory.
+
+You can also change @value{GDBN}'s current working directory by using
+the @code{cd} command.
 
 The @value{GDBN} working directory also serves as a default for the commands
 that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
 Specify Files}.
 
 @table @code
+@kindex set cwd
+@cindex change inferior's working directory
+@item set cwd @r{[}@var{directory}@r{]}
+Set the inferior's working directory to @var{directory}, which will be
+@code{glob}-expanded in order to resolve tildes (@file{~}).  If no
+argument has been specified, the command clears the setting and resets
+it to an empty state.  This setting has no effect on @value{GDBN}'s
+working directory, and it only takes effect the next time you start
+the inferior.  The @file{~} in @var{directory} is a short for the
+@dfn{home directory}, usually pointed to by the @env{HOME} environment
+variable.  On MS-Windows, if @env{HOME} is not defined, @value{GDBN}
+uses the concatenation of @env{HOMEDRIVE} and @env{HOMEPATH} as
+fallback.
+
+@kindex show cwd
+@cindex show inferior's working directory
+@item show cwd
+Show the inferior's working directory.  If no directory has been
+specified by @kbd{set cwd}, then the default inferior's working
+directory is the same as @value{GDBN}'s working directory.
+
 @kindex cd
-@cindex change working directory
+@cindex change @value{GDBN}'s working directory
 @item cd @r{[}@var{directory}@r{]}
 Set the @value{GDBN} working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 3a45959000..57d9956ebb 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -29,6 +29,9 @@ struct thread_info *current_thread;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
 
+/* The current working directory used to start the inferior.  */
+static const char *current_inferior_cwd = NULL;
+
 void
 add_inferior_to_list (struct inferior_list *list,
 		      struct inferior_list_entry *new_inferior)
@@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
   gdb_assert (ptid != minus_one_ptid);
   current_thread = find_thread_ptid (ptid);
 }
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior_cwd;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index da16f5ed6d..dbdf273ca5 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -103,6 +103,10 @@ static void run_command (char *, int);
 
 static char *inferior_args_scratch;
 
+/* Scratch area where the new cwd will be stored by 'set cwd'.  */
+
+static char *inferior_cwd_scratch;
+
 /* Scratch area where 'set inferior-tty' will store user-provided value.
    We'll immediate copy it into per-inferior storage.  */
 
@@ -238,6 +242,60 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
+/* Set the inferior current working directory.  If CWD is NULL, unset
+   the directory.  */
+
+static void
+set_inferior_cwd (const char *cwd)
+{
+  struct inferior *inf = current_inferior ();
+
+  gdb_assert (inf != NULL);
+
+  if (cwd == NULL)
+    inf->cwd.reset ();
+  else
+    inf->cwd.reset (xstrdup (cwd));
+}
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior ()->cwd.get ();
+}
+
+/* Handle the 'set cwd' command.  */
+
+static void
+set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+{
+  if (*inferior_cwd_scratch == '\0')
+    set_inferior_cwd (NULL);
+  else
+    set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command.  */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  const char *cwd = get_inferior_cwd ();
+
+  if (cwd == NULL)
+    fprintf_filtered (gdb_stdout,
+		      _("\
+You have not set the inferior's current working directory.\n\
+The inferior will inherit GDB's cwd.\n"));
+  else
+    fprintf_filtered (gdb_stdout,
+		      _("Current working directory that will be used "
+			"when starting the inferior is \"%s\".\n"), cwd);
+}
+
 \f
 /* Compute command-line string given argument vector.  This does the
    same shell processing as fork_inferior.  */
@@ -3253,6 +3311,25 @@ Follow this command with any number of args, to be passed to the program."),
   gdb_assert (c != NULL);
   set_cmd_completer (c, filename_completer);
 
+  cmd_name = "cwd";
+  add_setshow_string_noescape_cmd (cmd_name, class_run,
+				   &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+				   _("\
+Show the current working directory that is used when the inferior is started."),
+				   _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started.  This setting does not affect GDB's current\n\
+working directory."),
+				   set_cwd_command,
+				   show_cwd_command,
+				   &setlist, &showlist);
+  c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+  gdb_assert (c != NULL);
+  set_cmd_completer (c, filename_completer);
+
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
 With an argument VAR, prints the value of environment variable VAR to\n\
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 7f2d53e5b3..498d74706a 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -355,6 +355,10 @@ public:
      should never be freed.  */
   char **argv = NULL;
 
+  /* The current working directory that will be used when starting
+     this inferior.  */
+  gdb::unique_xmalloc_ptr<char> cwd;
+
   /* The name of terminal device to use for I/O.  */
   char *terminal = NULL;
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 6ff119768c..1480be4961 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -25,6 +25,7 @@
 #include "common-inferior.h"
 #include "common-gdbthread.h"
 #include "signals-state-save-restore.h"
+#include "gdb_tilde_expand.h"
 #include <vector>
 
 extern char **environ;
@@ -298,6 +299,8 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
   char **save_our_env;
   int i;
   int save_errno;
+  const char *inferior_cwd;
+  std::string expanded_inferior_cwd;
 
   /* If no exec file handed to us, get it from the exec-file command
      -- with a good, common error message if none is specified.  */
@@ -339,6 +342,18 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
      the parent and child flushing the same data after the fork.  */
   gdb_flush_out_err ();
 
+  /* Check if the user wants to set a different working directory for
+     the inferior.  */
+  inferior_cwd = get_inferior_cwd ();
+
+  if (inferior_cwd != NULL)
+    {
+      /* Expand before forking because between fork and exec, the child
+	 process may only execute async-signal-safe operations.  */
+      expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
+      inferior_cwd = expanded_inferior_cwd.c_str ();
+    }
+
   /* If there's any initialization of the target layers that must
      happen to prepare to handle the child we're about fork, do it
      now...  */
@@ -374,6 +389,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
 	 UIs.  */
       close_most_fds ();
 
+      /* Change to the requested working directory if the user
+	 requested it.  */
+      if (inferior_cwd != NULL)
+	{
+	  if (chdir (inferior_cwd) < 0)
+	    trace_start_error_with_name (expanded_inferior_cwd.c_str ());
+	}
+
       if (debug_fork)
 	sleep (debug_fork);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.c b/gdb/testsuite/gdb.base/set-cwd.c
new file mode 100644
index 0000000000..58738830d6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 Free Software Foundation, Inc.
+
+   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 <stdlib.h>
+#include <unistd.h>
+
+static char dir[4096];
+
+int
+main (int argc, char *argv[])
+{
+  const char *home = getenv ("HOME");
+
+  getcwd (dir, 4096);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
new file mode 100644
index 0000000000..bbb8d006a4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -0,0 +1,198 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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/>.
+
+if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
+    untested "not implemented on remote servers"
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    return -1
+}
+
+# Test that tilde expansion works fine.
+
+proc_with_prefix test_tilde_expansion { } {
+    global decimal gdb_prompt hex
+
+    gdb_test_no_output "set cwd ~/" "set inferior cwd to ~/ dir"
+
+    if { ![runto_main] } {
+	untested "could not run to main"
+	return -1
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    set home ""
+    set test "print home var"
+    gdb_test_multiple "print home" $test {
+    	-re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
+    	    set home $expect_out(1,string)
+    	    pass $test
+    	}
+    }
+
+    if { $home == "" } {
+    	untested "could not retrieve home var"
+    	return
+    }
+
+    set curdir ""
+    set test "print dir var"
+    gdb_test_multiple "print dir" $test {
+	-re "\\\$$decimal = \"\(.+\)\"\(, .*repeats.*\)?\r\n$gdb_prompt $" {
+	    set curdir $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $curdir == "" } {
+	untested "could not retrieve dir var"
+	return
+    }
+
+    gdb_assert [string equal $curdir $home] \
+	"successfully chdir'd into home"
+}
+
+# The temporary directory that we will use to start the inferior.
+set tmpdir [standard_output_file ""]
+
+# Test that when we "set cwd" the inferior will be started under the
+# correct working directory and GDB will not be affected by this.
+
+proc_with_prefix test_cd_into_dir { } {
+    global decimal gdb_prompt tmpdir
+
+    set gdb_cwd_before_run ""
+    set test "pwd before run"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd_before_run $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $gdb_cwd_before_run == "" } {
+	untested "could not obtain GDB cwd before run"
+	return
+    }
+
+    # This test only makes sense if $tmpdir != $gdb_cwd_before_run
+    if { ![gdb_assert ![string equal $tmpdir $gdb_cwd_before_run] \
+	       "make sure that tmpdir and GDB's cwd are different"] } {
+	return -1
+    }
+
+    gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+    if { ![runto_main] } {
+	untested "could not run to main"
+	return -1
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	"inferior cwd is correctly set"
+
+    set gdb_cwd_after_run ""
+    set test "pwd after run"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd_after_run $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $gdb_cwd_after_run == "" } {
+	untested "could not obtain GDB cwd after run"
+	return
+    }
+
+    gdb_assert [string equal $gdb_cwd_before_run $gdb_cwd_after_run] \
+	"GDB cwd is unchanged after running inferior"
+}
+
+# Test that executing "set cwd" without arguments will reset the
+# inferior's cwd setting to its previous state.
+
+proc_with_prefix test_cwd_reset { } {
+    global decimal gdb_prompt tmpdir
+
+    gdb_test_multiple "pwd" "GDB cwd" {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd $expect_out(1,string)
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "failed to obtain GDB cwd before run"
+	    return -1
+	}
+	default {
+	    fail "failed to obtain GDB cwd before run"
+	    return -1
+	}
+    }
+
+    # This test only makes sense if $tmpdir != $gdb_cwd.
+    if { ![gdb_assert ![string equal $tmpdir $gdb_cwd] \
+	       "make sure that tmpdir and GDB's cwd are different"] } {
+	return -1
+    }
+
+    gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+    with_test_prefix "running with set cwd" {
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	"inferior cwd is correctly set"
+
+    # Reset the inferior's cwd.
+    gdb_test_no_output "set cwd" "resetting inferior cwd"
+
+    with_test_prefix "running without set cwd" {
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$gdb_cwd\", .*" \
+	"inferior cwd got reset correctly"
+}
+
+test_cd_into_dir
+clean_restart $binfile
+test_tilde_expansion
+clean_restart $binfile
+test_cwd_reset
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 3e1894410d..6b590fdca5 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -66,6 +66,7 @@
 #include "x86-nat.h"
 #include "complaints.h"
 #include "inf-child.h"
+#include "gdb_tilde_expand.h"
 
 #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
@@ -2428,6 +2429,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 #ifdef __CYGWIN__
   cygwin_buf_t real_path[__PMAX];
   cygwin_buf_t shell[__PMAX]; /* Path to shell */
+  cygwin_buf_t infcwd[__PMAX];
   const char *sh;
   cygwin_buf_t *toexec;
   cygwin_buf_t *cygallargs;
@@ -2465,6 +2467,17 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
 
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd;
+  if (inferior_cwd != NULL)
+    {
+      expanded_infcwd = gdb_tilde_expand (inferior_cwd);
+      /* Mirror slashes on inferior's cwd.  */
+      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+		    '/', '\\');
+      inferior_cwd = expanded_infcwd.c_str ();
+    }
+
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
 
@@ -2514,6 +2527,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
       flags |= DEBUG_PROCESS;
     }
 
+  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
+			infcwd, strlen (inferior_cwd)) < 0)
+    error (_("Error converting inferior cwd: %d"), errno);
+
 #ifdef __USEWIDE
   args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
 				  * sizeof (wchar_t));
@@ -2574,7 +2591,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 		       TRUE,	/* inherit handles */
 		       flags,	/* start flags */
 		       w32_env,	/* environment */
-		       NULL,	/* current directory */
+		       infcwd,	/* current directory */
 		       &si,
 		       &pi);
   if (w32_env)
@@ -2697,7 +2714,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 			TRUE,	/* inherit handles */
 			flags,	/* start flags */
 			w32env,	/* environment */
-			NULL,	/* current directory */
+			inferior_cwd, /* current directory */
 			&si,
 			&pi);
   if (tty != INVALID_HANDLE_VALUE)
-- 
2.13.3

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

* Re: [PATCH v4 3/3] Extend "set cwd" to work on gdbserver
  2017-09-29 18:48       ` Sergio Durigan Junior
@ 2017-10-03 15:13         ` Pedro Alves
  0 siblings, 0 replies; 131+ messages in thread
From: Pedro Alves @ 2017-10-03 15:13 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches, Eli Zaretskii

On 09/29/2017 07:48 PM, Sergio Durigan Junior wrote:

>>> +command, then an empty packet will be sent to the remote server, which
>>
>> Not an empty packet, and empty directory.  Really-empty packets are 
>> special in the remote protocol.
>>
>>> +will have no effect.  
>>
>> WDYM will have no effect, when just above you've explained that empty
>> means reset ?  I think you should just remove this paragraph starting
>> with "This packet is always transmitted".  That's implementation
>> detail.  GDB could for example not resend the packet if the value
>> didn't change between runs, no?
> 
> What I tried to say is that if the user doesn't make use of the "set
> cwd" command in a GDB session, the packet will be transmitted anyway.  I
> think I should have been clearer here.
> 
> I will remove the paragraph as requested.

This part of the manual is a specification of the remote protocol
packets, not of how GDB implements them currently; it shouldn't
really talk about current GDB implementation details unless
it makes a real difference, because those details should be free
to change within the bounds of the specification.

Thanks,
Pedro Alves

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-09-29 22:59   ` [PATCH v5 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
@ 2017-10-03 15:15     ` Pedro Alves
  2017-10-03 16:39       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-10-03 15:15 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches; +Cc: Eli Zaretskii

Hi Sergio,

This looks largely OK to me now, though I still have a couple
comments.

On 09/29/2017 11:58 PM, Sergio Durigan Junior wrote:
> @@ -2434,19 +2435,43 @@ variables to files that are only run when you sign on, such as
>  @section Your Program's Working Directory
>  
>  @cindex working directory (of your program)
> -Each time you start your program with @code{run}, it inherits its
> -working directory from the current working directory of @value{GDBN}.
> -The @value{GDBN} working directory is initially whatever it inherited
> -from its parent process (typically the shell), but you can specify a new
> -working directory in @value{GDBN} with the @code{cd} command.
> +Each time you start your program with @code{run}, the inferior will be
> +initialized with the current working directory specified by the
> +@kbd{set cwd} command.  If no directory has been specified by this
> +command, then the inferior will inherit @value{GDBN}'s current working
> +directory as its working directory.
> +
> +You can also change @value{GDBN}'s current working directory by using
> +the @code{cd} command.
>  
>  The @value{GDBN} working directory also serves as a default for the commands
>  that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
>  Specify Files}.

Rereading this, I think that this paragraph ("The GDB working directory
also serves...") would be better moved below, where "cd" is
documented (with the "also" probably dropped).  Maybe add an xref here taking
users there.

>  @kindex cd
> -@cindex change working directory
> +@cindex change @value{GDBN}'s working directory
>  @item cd @r{[}@var{directory}@r{]}
>  Set the @value{GDBN} working directory to @var{directory}.  If not
>  given, @var{directory} uses @file{'~'}.

Above I meant, move that paragraph here, where "cd" is documented.
This is where I'd expect to see info about what does the command
affect.  Maybe also add an xref to "set cwd" here.

> @@ -374,6 +389,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>  	 UIs.  */
>        close_most_fds ();
>  
> +      /* Change to the requested working directory if the user
> +	 requested it.  */
> +      if (inferior_cwd != NULL)
> +	{
> +	  if (chdir (inferior_cwd) < 0)
> +	    trace_start_error_with_name (expanded_inferior_cwd.c_str ());

Please also update the trace_start... statement:

    trace_start_error_with_name (expanded_inferior);


> +proc_with_prefix test_cwd_reset { } {
> +    global decimal gdb_prompt tmpdir
> +
> +    gdb_test_multiple "pwd" "GDB cwd" {
> +	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
> +	    set gdb_cwd $expect_out(1,string)
> +	}
> +	-re ".*$gdb_prompt $" {
> +	    fail "failed to obtain GDB cwd before run"
> +	    return -1
> +	}
> +	default {
> +	    fail "failed to obtain GDB cwd before run"
> +	    return -1
> +	}
> +    }

Any reason you didn't update this one?

>  
> +  const char *inferior_cwd = get_inferior_cwd ();
> +  std::string expanded_infcwd;
> +  if (inferior_cwd != NULL)
> +    {
> +      expanded_infcwd = gdb_tilde_expand (inferior_cwd);
> +      /* Mirror slashes on inferior's cwd.  */
> +      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
> +		    '/', '\\');
> +      inferior_cwd = expanded_infcwd.c_str ();
> +    }
> +

But what if inferior_cwd _is_ NULL, when ...


>    memset (&si, 0, sizeof (si));
>    si.cb = sizeof (si);
>  
> @@ -2514,6 +2527,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>        flags |= DEBUG_PROCESS;
>      }
>  
> +  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
> +			infcwd, strlen (inferior_cwd)) < 0)
> +    error (_("Error converting inferior cwd: %d"), errno);

... we get here?  It looks to me like this conversion should
skipped here then, and ...

> +
>  #ifdef __USEWIDE
>    args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
>  				  * sizeof (wchar_t));
> @@ -2574,7 +2591,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>  		       TRUE,	/* inherit handles */
>  		       flags,	/* start flags */
>  		       w32_env,	/* environment */
> -		       NULL,	/* current directory */
> +		       infcwd,	/* current directory */

... here still pass NULL.

>  		       &si,
>  		       &pi);
>    if (w32_env)
> @@ -2697,7 +2714,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>  			TRUE,	/* inherit handles */
>  			flags,	/* start flags */
>  			w32env,	/* environment */
> -			NULL,	/* current directory */
> +			inferior_cwd, /* current directory */
>  			&si,
>  			&pi);
>    if (tty != INVALID_HANDLE_VALUE)
> 

Thanks,
Pedro Alves

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

* Re: [PATCH v5 1/3] Introduce gdb_tilde_expand
  2017-09-29 22:59   ` [PATCH v5 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
@ 2017-10-03 15:15     ` Pedro Alves
  2017-10-04  6:09       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-10-03 15:15 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches; +Cc: Eli Zaretskii

On 09/29/2017 11:58 PM, Sergio Durigan Junior wrote:
> Currently, whenever we want to handle paths provided by the user and
> perform tilde expansion on GDB, we rely on "tilde_expand", which comes
> from readline.  This was enough for our use cases so far, but the
> situation will change when we start dealing with paths on gdbserver as
> well, which is what the next patches implement.
> 
> Unfortunately it is not possible to use "tilde_expand" in this case
> because gdbserver doesn't use readline.  For that reason I decided to
> implement a new "gdb_tilde_expand" function, which is basically a
> wrapper for "glob" and its GNU extension, GLOB_TILDE_CHECK.  With the
> import of the "glob" module from gnulib, this is a no-brainer.
> 

OK.

Thanks,
Pedro Alves

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

* Re: [PATCH v5 3/3] Extend "set cwd" to work on gdbserver
  2017-09-29 22:59   ` [PATCH v5 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
@ 2017-10-03 15:15     ` Pedro Alves
  2017-10-03 16:45       ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-10-03 15:15 UTC (permalink / raw)
  To: Sergio Durigan Junior, GDB Patches; +Cc: Eli Zaretskii

This version looks good to me, with one tiny nit below.

On 09/29/2017 11:58 PM, Sergio Durigan Junior wrote:

> +/* Helper function to set the current working directory for the
> +   inferior in the remote.  */

"in the remote" sounds a bit odd.  Missing word?
Maybe "remote target."?

> +
> +static void
> +extended_remote_set_inferior_cwd (struct remote_state *rs)
> +{

Thanks,
Pedro Alves

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-03 15:15     ` Pedro Alves
@ 2017-10-03 16:39       ` Sergio Durigan Junior
  2017-10-03 16:44         ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-03 16:39 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Tuesday, October 03 2017, Pedro Alves wrote:

> Hi Sergio,
>
> This looks largely OK to me now, though I still have a couple
> comments.
>
> On 09/29/2017 11:58 PM, Sergio Durigan Junior wrote:
>> @@ -2434,19 +2435,43 @@ variables to files that are only run when you sign on, such as
>>  @section Your Program's Working Directory
>>  
>>  @cindex working directory (of your program)
>> -Each time you start your program with @code{run}, it inherits its
>> -working directory from the current working directory of @value{GDBN}.
>> -The @value{GDBN} working directory is initially whatever it inherited
>> -from its parent process (typically the shell), but you can specify a new
>> -working directory in @value{GDBN} with the @code{cd} command.
>> +Each time you start your program with @code{run}, the inferior will be
>> +initialized with the current working directory specified by the
>> +@kbd{set cwd} command.  If no directory has been specified by this
>> +command, then the inferior will inherit @value{GDBN}'s current working
>> +directory as its working directory.
>> +
>> +You can also change @value{GDBN}'s current working directory by using
>> +the @code{cd} command.
>>  
>>  The @value{GDBN} working directory also serves as a default for the commands
>>  that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
>>  Specify Files}.
>
> Rereading this, I think that this paragraph ("The GDB working directory
> also serves...") would be better moved below, where "cd" is
> documented (with the "also" probably dropped).  Maybe add an xref here taking
> users there.

Done.

>>  @kindex cd
>> -@cindex change working directory
>> +@cindex change @value{GDBN}'s working directory
>>  @item cd @r{[}@var{directory}@r{]}
>>  Set the @value{GDBN} working directory to @var{directory}.  If not
>>  given, @var{directory} uses @file{'~'}.
>
> Above I meant, move that paragraph here, where "cd" is documented.
> This is where I'd expect to see info about what does the command
> affect.  Maybe also add an xref to "set cwd" here.

Done.

>> @@ -374,6 +389,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
>>  	 UIs.  */
>>        close_most_fds ();
>>  
>> +      /* Change to the requested working directory if the user
>> +	 requested it.  */
>> +      if (inferior_cwd != NULL)
>> +	{
>> +	  if (chdir (inferior_cwd) < 0)
>> +	    trace_start_error_with_name (expanded_inferior_cwd.c_str ());
>
> Please also update the trace_start... statement:
>
>     trace_start_error_with_name (expanded_inferior);
>

I could swear I had updated this.  Anyway, did that now.

>
>> +proc_with_prefix test_cwd_reset { } {
>> +    global decimal gdb_prompt tmpdir
>> +
>> +    gdb_test_multiple "pwd" "GDB cwd" {
>> +	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
>> +	    set gdb_cwd $expect_out(1,string)
>> +	}
>> +	-re ".*$gdb_prompt $" {
>> +	    fail "failed to obtain GDB cwd before run"
>> +	    return -1
>> +	}
>> +	default {
>> +	    fail "failed to obtain GDB cwd before run"
>> +	    return -1
>> +	}
>> +    }
>
> Any reason you didn't update this one?

That's strange.  I also could swear I updated this one.  I'm starting to
use a new tool to manage my git repos, so maybe I made a confusion and
reverted some changes.

Updated.

>>  
>> +  const char *inferior_cwd = get_inferior_cwd ();
>> +  std::string expanded_infcwd;
>> +  if (inferior_cwd != NULL)
>> +    {
>> +      expanded_infcwd = gdb_tilde_expand (inferior_cwd);
>> +      /* Mirror slashes on inferior's cwd.  */
>> +      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
>> +		    '/', '\\');
>> +      inferior_cwd = expanded_infcwd.c_str ();
>> +    }
>> +
>
> But what if inferior_cwd _is_ NULL, when ...
>
>
>>    memset (&si, 0, sizeof (si));
>>    si.cb = sizeof (si);
>>  
>> @@ -2514,6 +2527,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>        flags |= DEBUG_PROCESS;
>>      }
>>  
>> +  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
>> +			infcwd, strlen (inferior_cwd)) < 0)
>> +    error (_("Error converting inferior cwd: %d"), errno);
>
> ... we get here?  It looks to me like this conversion should
> skipped here then, and ...

You're right, this should be skipped.

>> +
>>  #ifdef __USEWIDE
>>    args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
>>  				  * sizeof (wchar_t));
>> @@ -2574,7 +2591,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>  		       TRUE,	/* inherit handles */
>>  		       flags,	/* start flags */
>>  		       w32_env,	/* environment */
>> -		       NULL,	/* current directory */
>> +		       infcwd,	/* current directory */
>
> ... here still pass NULL.

Here we pass NULL because that was the old behaviour when we did not
care about the inferior's cwd.  This is the same approach that we use on
fork_inferior: if the user hasn't provided any paths via "set cwd", then
we don't do anything.

>>  		       &si,
>>  		       &pi);
>>    if (w32_env)
>> @@ -2697,7 +2714,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>  			TRUE,	/* inherit handles */
>>  			flags,	/* start flags */
>>  			w32env,	/* environment */
>> -			NULL,	/* current directory */
>> +			inferior_cwd, /* current directory */
>>  			&si,
>>  			&pi);
>>    if (tty != INVALID_HANDLE_VALUE)
>> 

Thanks,

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

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-03 16:39       ` Sergio Durigan Junior
@ 2017-10-03 16:44         ` Pedro Alves
  2017-10-03 16:47           ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-10-03 16:44 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches, Eli Zaretskii

On 10/03/2017 05:39 PM, Sergio Durigan Junior wrote:

>> But what if inferior_cwd _is_ NULL, when ...
>>
>>
>>>    memset (&si, 0, sizeof (si));
>>>    si.cb = sizeof (si);
>>>  
>>> @@ -2514,6 +2527,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>>        flags |= DEBUG_PROCESS;
>>>      }
>>>  
>>> +  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
>>> +			infcwd, strlen (inferior_cwd)) < 0)
>>> +    error (_("Error converting inferior cwd: %d"), errno);
>>
>> ... we get here?  It looks to me like this conversion should
>> skipped here then, and ...
> 
> You're right, this should be skipped.
> 
>>> +
>>>  #ifdef __USEWIDE
>>>    args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
>>>  				  * sizeof (wchar_t));
>>> @@ -2574,7 +2591,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>>  		       TRUE,	/* inherit handles */
>>>  		       flags,	/* start flags */
>>>  		       w32_env,	/* environment */
>>> -		       NULL,	/* current directory */
>>> +		       infcwd,	/* current directory */
>>
>> ... here still pass NULL.
> 
> Here we pass NULL because that was the old behaviour when we did not
> care about the inferior's cwd.  This is the same approach that we use on
> fork_inferior: if the user hasn't provided any paths via "set cwd", then
> we don't do anything.

Exactly, I'm saying that you _should_ pass NULL iff
inferior_cwd is NULL.  That's what msdn's documentation of
CreateProcess says you should pass in order to have the
process inherit its parent's cwd.

Thanks,
Pedro Alves

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

* Re: [PATCH v5 3/3] Extend "set cwd" to work on gdbserver
  2017-10-03 15:15     ` Pedro Alves
@ 2017-10-03 16:45       ` Sergio Durigan Junior
  2017-10-04  6:09         ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-03 16:45 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Tuesday, October 03 2017, Pedro Alves wrote:

> This version looks good to me, with one tiny nit below.
>
> On 09/29/2017 11:58 PM, Sergio Durigan Junior wrote:
>
>> +/* Helper function to set the current working directory for the
>> +   inferior in the remote.  */
>
> "in the remote" sounds a bit odd.  Missing word?
> Maybe "remote target."?

Indeed, thanks.  Added the word.

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

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-03 16:44         ` Pedro Alves
@ 2017-10-03 16:47           ` Sergio Durigan Junior
  2017-10-03 16:58             ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-03 16:47 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Tuesday, October 03 2017, Pedro Alves wrote:

> On 10/03/2017 05:39 PM, Sergio Durigan Junior wrote:
>
>>> But what if inferior_cwd _is_ NULL, when ...
>>>
>>>
>>>>    memset (&si, 0, sizeof (si));
>>>>    si.cb = sizeof (si);
>>>>  
>>>> @@ -2514,6 +2527,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>>>        flags |= DEBUG_PROCESS;
>>>>      }
>>>>  
>>>> +  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
>>>> +			infcwd, strlen (inferior_cwd)) < 0)
>>>> +    error (_("Error converting inferior cwd: %d"), errno);
>>>
>>> ... we get here?  It looks to me like this conversion should
>>> skipped here then, and ...
>> 
>> You're right, this should be skipped.
>> 
>>>> +
>>>>  #ifdef __USEWIDE
>>>>    args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
>>>>  				  * sizeof (wchar_t));
>>>> @@ -2574,7 +2591,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>>>  		       TRUE,	/* inherit handles */
>>>>  		       flags,	/* start flags */
>>>>  		       w32_env,	/* environment */
>>>> -		       NULL,	/* current directory */
>>>> +		       infcwd,	/* current directory */
>>>
>>> ... here still pass NULL.
>> 
>> Here we pass NULL because that was the old behaviour when we did not
>> care about the inferior's cwd.  This is the same approach that we use on
>> fork_inferior: if the user hasn't provided any paths via "set cwd", then
>> we don't do anything.
>
> Exactly, I'm saying that you _should_ pass NULL iff
> inferior_cwd is NULL.  That's what msdn's documentation of
> CreateProcess says you should pass in order to have the
> process inherit its parent's cwd.

Oh, right, sorry, I mistakenly thought we were talking about the code
below, which uses "inferior_cwd" directly.  Indeed, this part should
pass NULL, and I've fixed it locally to do that.  Thanks,

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

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-03 16:47           ` Sergio Durigan Junior
@ 2017-10-03 16:58             ` Sergio Durigan Junior
  2017-10-03 20:09               ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-03 16:58 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Tuesday, October 03 2017, I wrote:

> On Tuesday, October 03 2017, Pedro Alves wrote:
>
>> On 10/03/2017 05:39 PM, Sergio Durigan Junior wrote:
>>
>>>> But what if inferior_cwd _is_ NULL, when ...
>>>>
>>>>
>>>>>    memset (&si, 0, sizeof (si));
>>>>>    si.cb = sizeof (si);
>>>>>  
>>>>> @@ -2514,6 +2527,10 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>>>>        flags |= DEBUG_PROCESS;
>>>>>      }
>>>>>  
>>>>> +  if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
>>>>> +			infcwd, strlen (inferior_cwd)) < 0)
>>>>> +    error (_("Error converting inferior cwd: %d"), errno);
>>>>
>>>> ... we get here?  It looks to me like this conversion should
>>>> skipped here then, and ...
>>> 
>>> You're right, this should be skipped.
>>> 
>>>>> +
>>>>>  #ifdef __USEWIDE
>>>>>    args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
>>>>>  				  * sizeof (wchar_t));
>>>>> @@ -2574,7 +2591,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
>>>>>  		       TRUE,	/* inherit handles */
>>>>>  		       flags,	/* start flags */
>>>>>  		       w32_env,	/* environment */
>>>>> -		       NULL,	/* current directory */
>>>>> +		       infcwd,	/* current directory */
>>>>
>>>> ... here still pass NULL.
>>> 
>>> Here we pass NULL because that was the old behaviour when we did not
>>> care about the inferior's cwd.  This is the same approach that we use on
>>> fork_inferior: if the user hasn't provided any paths via "set cwd", then
>>> we don't do anything.
>>
>> Exactly, I'm saying that you _should_ pass NULL iff
>> inferior_cwd is NULL.  That's what msdn's documentation of
>> CreateProcess says you should pass in order to have the
>> process inherit its parent's cwd.
>
> Oh, right, sorry, I mistakenly thought we were talking about the code
> below, which uses "inferior_cwd" directly.  Indeed, this part should
> pass NULL, and I've fixed it locally to do that.  Thanks,

In order to avoid yet-another-version, here's the updated patch with all
your comments addressed.

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

From 3018993a8467ebcc15532b1679e85fd8ac0fb081 Mon Sep 17 00:00:00 2001
From: Sergio Durigan Junior <sergiodj@redhat.com>
Date: Mon, 11 Sep 2017 01:13:50 -0400
Subject: [PATCH v6 2/3] Implement "set cwd" command on GDB

This commit adds new "set/show cwd" commands, which are used to
set/show the current working directory of the inferior that will be
started.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.

"set cwd" works in the following way:

- If the user sets the inferior's cwd by using "set cwd", then this
  directory is saved into current_inferior ()->cwd and is used when
  the inferior is started (see below).

- If the user doesn't set the inferior's cwd by using "set cwd", but
  rather use the "cd" command as before, then this directory is
  inherited by the inferior because GDB will have chdir'd into it.

On Unix-like hosts, the way the directory is changed before the
inferior execution is by expanding the user set directory before the
fork, and then "chdir" after the call to fork/vfork on
"fork_inferior", but before the actual execution.  On Windows, the
inferior cwd set by the user is passed directly to the CreateProcess
call, which takes care of the actual chdir for us.

This way, we'll make sure that GDB's cwd is not affected by the user
set cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (New commands): Mention "set/show cwd".
	* cli/cli-cmds.c (_initialize_cli_cmds): Mention "set cwd" on
	"cd" command's help text.
	* common/common-inferior.h (get_inferior_cwd): New prototype.
	* infcmd.c (inferior_cwd_scratch): New global variable.
	(set_inferior_cwd): New function.
	(get_inferior_cwd): Likewise.
	(set_cwd_command): Likewise.
	(show_cwd_command): Likewise.
	(_initialize_infcmd): Add "set/show cwd" commands.
	* inferior.h (class inferior) <cwd>: New field.
	* nat/fork-inferior.c: Include "gdb_tilde_expand.h".
	(fork_inferior): Change inferior's cwd before its execution.
	* windows-nat.c (windows_create_inferior): Pass inferior's cwd
	to CreateProcess.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (current_inferior_cwd): New global variable.
	(get_inferior_cwd): New function.
	* inferiors.h (struct process_info) <cwd>: New field.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention new "set cwd" command.
	(Working Directory) <Your Program's Working Directory>:
	Rephrase to explain that "set cwd" exists and is the default
	way to change the inferior's cwd.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.c: New file.
	* gdb.base/set-cwd.exp: Likewise.
---
 gdb/NEWS                           |   3 +
 gdb/cli/cli-cmds.c                 |   8 +-
 gdb/common/common-inferior.h       |   4 +
 gdb/doc/gdb.texinfo                |  45 +++++++--
 gdb/gdbserver/inferiors.c          |  11 +++
 gdb/infcmd.c                       |  77 +++++++++++++++
 gdb/inferior.h                     |   4 +
 gdb/nat/fork-inferior.c            |  23 +++++
 gdb/testsuite/gdb.base/set-cwd.c   |  31 ++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 197 +++++++++++++++++++++++++++++++++++++
 gdb/windows-nat.c                  |  23 ++++-
 11 files changed, 413 insertions(+), 13 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.c
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 81c21b82cc..fcf454833f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -67,6 +67,9 @@ QStartupWithShell
 
 * New commands
 
+set|show cwd
+  Set and show the current working directory for the inferior.
+
 set|show compile-gcc
   Set and show compilation command used for compiling and injecting code
   with the 'compile' commands.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index dde67ee2b3..dad5ffa42e 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1727,9 +1727,11 @@ The commands below can be used to select other frames by number or address."),
 Print working directory.  This is used for your program as well."));
 
   c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+The debugger's current working directory specifies where scripts and other\n\
+files that can be loaded by GDB are located.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_com ("echo", class_support, echo_command, _("\
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 87c13009ed..515a8c0f4e 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
    otherwise return 0 in that case.  */
 extern char *get_exec_file (int err);
 
+/* Return the inferior's current working directory.  If nothing has
+   been set, then return NULL.  */
+extern const char *get_inferior_cwd ();
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9905ff6513..5dac965c73 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
 your program.  @xref{Environment, ,Your Program's Environment}.
 
 @item The @emph{working directory.}
-Your program inherits its working directory from @value{GDBN}.  You can set
-the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+You can set your program's working directory with the command
+@kbd{set cwd}.  If you do not set any working directory with this
+command, your program will inherit @value{GDBN}'s working directory.
 @xref{Working Directory, ,Your Program's Working Directory}.
 
 @item The @emph{standard input and output.}
@@ -2434,23 +2435,51 @@ variables to files that are only run when you sign on, such as
 @section Your Program's Working Directory
 
 @cindex working directory (of your program)
-Each time you start your program with @code{run}, it inherits its
-working directory from the current working directory of @value{GDBN}.
-The @value{GDBN} working directory is initially whatever it inherited
-from its parent process (typically the shell), but you can specify a new
-working directory in @value{GDBN} with the @code{cd} command.
+Each time you start your program with @code{run}, the inferior will be
+initialized with the current working directory specified by the
+@kbd{set cwd} command.  If no directory has been specified by this
+command, then the inferior will inherit @value{GDBN}'s current working
+directory as its working directory.
 
 The @value{GDBN} working directory also serves as a default for the commands
 that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
 Specify Files}.
 
 @table @code
+@kindex set cwd
+@cindex change inferior's working directory
+@anchor{set cwd command}
+@item set cwd @r{[}@var{directory}@r{]}
+Set the inferior's working directory to @var{directory}, which will be
+@code{glob}-expanded in order to resolve tildes (@file{~}).  If no
+argument has been specified, the command clears the setting and resets
+it to an empty state.  This setting has no effect on @value{GDBN}'s
+working directory, and it only takes effect the next time you start
+the inferior.  The @file{~} in @var{directory} is a short for the
+@dfn{home directory}, usually pointed to by the @env{HOME} environment
+variable.  On MS-Windows, if @env{HOME} is not defined, @value{GDBN}
+uses the concatenation of @env{HOMEDRIVE} and @env{HOMEPATH} as
+fallback.
+@xref{cd command}
+
+@kindex show cwd
+@cindex show inferior's working directory
+@item show cwd
+Show the inferior's working directory.  If no directory has been
+specified by @kbd{set cwd}, then the default inferior's working
+directory is the same as @value{GDBN}'s working directory.
+
 @kindex cd
-@cindex change working directory
+@cindex change @value{GDBN}'s working directory
+@anchor{cd command}
 @item cd @r{[}@var{directory}@r{]}
 Set the @value{GDBN} working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.
 
+You can change @value{GDBN}'s current working directory by using
+the @code{cd} command.
+@xref{set cwd command}
+
 @kindex pwd
 @item pwd
 Print the @value{GDBN} working directory.
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 3a45959000..57d9956ebb 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -29,6 +29,9 @@ struct thread_info *current_thread;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
 
+/* The current working directory used to start the inferior.  */
+static const char *current_inferior_cwd = NULL;
+
 void
 add_inferior_to_list (struct inferior_list *list,
 		      struct inferior_list_entry *new_inferior)
@@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
   gdb_assert (ptid != minus_one_ptid);
   current_thread = find_thread_ptid (ptid);
 }
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior_cwd;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index da16f5ed6d..dbdf273ca5 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -103,6 +103,10 @@ static void run_command (char *, int);
 
 static char *inferior_args_scratch;
 
+/* Scratch area where the new cwd will be stored by 'set cwd'.  */
+
+static char *inferior_cwd_scratch;
+
 /* Scratch area where 'set inferior-tty' will store user-provided value.
    We'll immediate copy it into per-inferior storage.  */
 
@@ -238,6 +242,60 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
+/* Set the inferior current working directory.  If CWD is NULL, unset
+   the directory.  */
+
+static void
+set_inferior_cwd (const char *cwd)
+{
+  struct inferior *inf = current_inferior ();
+
+  gdb_assert (inf != NULL);
+
+  if (cwd == NULL)
+    inf->cwd.reset ();
+  else
+    inf->cwd.reset (xstrdup (cwd));
+}
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior ()->cwd.get ();
+}
+
+/* Handle the 'set cwd' command.  */
+
+static void
+set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+{
+  if (*inferior_cwd_scratch == '\0')
+    set_inferior_cwd (NULL);
+  else
+    set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command.  */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  const char *cwd = get_inferior_cwd ();
+
+  if (cwd == NULL)
+    fprintf_filtered (gdb_stdout,
+		      _("\
+You have not set the inferior's current working directory.\n\
+The inferior will inherit GDB's cwd.\n"));
+  else
+    fprintf_filtered (gdb_stdout,
+		      _("Current working directory that will be used "
+			"when starting the inferior is \"%s\".\n"), cwd);
+}
+
 \f
 /* Compute command-line string given argument vector.  This does the
    same shell processing as fork_inferior.  */
@@ -3253,6 +3311,25 @@ Follow this command with any number of args, to be passed to the program."),
   gdb_assert (c != NULL);
   set_cmd_completer (c, filename_completer);
 
+  cmd_name = "cwd";
+  add_setshow_string_noescape_cmd (cmd_name, class_run,
+				   &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+				   _("\
+Show the current working directory that is used when the inferior is started."),
+				   _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started.  This setting does not affect GDB's current\n\
+working directory."),
+				   set_cwd_command,
+				   show_cwd_command,
+				   &setlist, &showlist);
+  c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+  gdb_assert (c != NULL);
+  set_cmd_completer (c, filename_completer);
+
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
 With an argument VAR, prints the value of environment variable VAR to\n\
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 7f2d53e5b3..498d74706a 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -355,6 +355,10 @@ public:
      should never be freed.  */
   char **argv = NULL;
 
+  /* The current working directory that will be used when starting
+     this inferior.  */
+  gdb::unique_xmalloc_ptr<char> cwd;
+
   /* The name of terminal device to use for I/O.  */
   char *terminal = NULL;
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 6ff119768c..ee1340b832 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -25,6 +25,7 @@
 #include "common-inferior.h"
 #include "common-gdbthread.h"
 #include "signals-state-save-restore.h"
+#include "gdb_tilde_expand.h"
 #include <vector>
 
 extern char **environ;
@@ -298,6 +299,8 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
   char **save_our_env;
   int i;
   int save_errno;
+  const char *inferior_cwd;
+  std::string expanded_inferior_cwd;
 
   /* If no exec file handed to us, get it from the exec-file command
      -- with a good, common error message if none is specified.  */
@@ -339,6 +342,18 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
      the parent and child flushing the same data after the fork.  */
   gdb_flush_out_err ();
 
+  /* Check if the user wants to set a different working directory for
+     the inferior.  */
+  inferior_cwd = get_inferior_cwd ();
+
+  if (inferior_cwd != NULL)
+    {
+      /* Expand before forking because between fork and exec, the child
+	 process may only execute async-signal-safe operations.  */
+      expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
+      inferior_cwd = expanded_inferior_cwd.c_str ();
+    }
+
   /* If there's any initialization of the target layers that must
      happen to prepare to handle the child we're about fork, do it
      now...  */
@@ -374,6 +389,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
 	 UIs.  */
       close_most_fds ();
 
+      /* Change to the requested working directory if the user
+	 requested it.  */
+      if (inferior_cwd != NULL)
+	{
+	  if (chdir (inferior_cwd) < 0)
+	    trace_start_error_with_name (inferior_cwd);
+	}
+
       if (debug_fork)
 	sleep (debug_fork);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.c b/gdb/testsuite/gdb.base/set-cwd.c
new file mode 100644
index 0000000000..58738830d6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 Free Software Foundation, Inc.
+
+   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 <stdlib.h>
+#include <unistd.h>
+
+static char dir[4096];
+
+int
+main (int argc, char *argv[])
+{
+  const char *home = getenv ("HOME");
+
+  getcwd (dir, 4096);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
new file mode 100644
index 0000000000..0d536488e4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -0,0 +1,197 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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/>.
+
+if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
+    untested "not implemented on remote servers"
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    return -1
+}
+
+# Test that tilde expansion works fine.
+
+proc_with_prefix test_tilde_expansion { } {
+    global decimal gdb_prompt hex
+
+    gdb_test_no_output "set cwd ~/" "set inferior cwd to ~/ dir"
+
+    if { ![runto_main] } {
+	untested "could not run to main"
+	return -1
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    set home ""
+    set test "print home var"
+    gdb_test_multiple "print home" $test {
+    	-re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
+    	    set home $expect_out(1,string)
+    	    pass $test
+    	}
+    }
+
+    if { $home == "" } {
+    	untested "could not retrieve home var"
+    	return
+    }
+
+    set curdir ""
+    set test "print dir var"
+    gdb_test_multiple "print dir" $test {
+	-re "\\\$$decimal = \"\(.+\)\"\(, .*repeats.*\)?\r\n$gdb_prompt $" {
+	    set curdir $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $curdir == "" } {
+	untested "could not retrieve dir var"
+	return
+    }
+
+    gdb_assert [string equal $curdir $home] \
+	"successfully chdir'd into home"
+}
+
+# The temporary directory that we will use to start the inferior.
+set tmpdir [standard_output_file ""]
+
+# Test that when we "set cwd" the inferior will be started under the
+# correct working directory and GDB will not be affected by this.
+
+proc_with_prefix test_cd_into_dir { } {
+    global decimal gdb_prompt tmpdir
+
+    set gdb_cwd_before_run ""
+    set test "pwd before run"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd_before_run $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $gdb_cwd_before_run == "" } {
+	untested "could not obtain GDB cwd before run"
+	return
+    }
+
+    # This test only makes sense if $tmpdir != $gdb_cwd_before_run
+    if { ![gdb_assert ![string equal $tmpdir $gdb_cwd_before_run] \
+	       "make sure that tmpdir and GDB's cwd are different"] } {
+	return -1
+    }
+
+    gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+    if { ![runto_main] } {
+	untested "could not run to main"
+	return -1
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	"inferior cwd is correctly set"
+
+    set gdb_cwd_after_run ""
+    set test "pwd after run"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd_after_run $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $gdb_cwd_after_run == "" } {
+	untested "could not obtain GDB cwd after run"
+	return
+    }
+
+    gdb_assert [string equal $gdb_cwd_before_run $gdb_cwd_after_run] \
+	"GDB cwd is unchanged after running inferior"
+}
+
+# Test that executing "set cwd" without arguments will reset the
+# inferior's cwd setting to its previous state.
+
+proc_with_prefix test_cwd_reset { } {
+    global decimal gdb_prompt tmpdir
+
+    set gdb_cwd ""
+    set test "GDB cwd"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd $expect_out(1,string)
+	}
+    }
+
+    if { $gdb_cwd == "" } {
+	untested "could not obtain GDB cwd"
+	return
+    }
+
+    # This test only makes sense if $tmpdir != $gdb_cwd.
+    if { ![gdb_assert ![string equal $tmpdir $gdb_cwd] \
+	       "make sure that tmpdir and GDB's cwd are different"] } {
+	return -1
+    }
+
+    gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+    with_test_prefix "running with set cwd" {
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	"inferior cwd is correctly set"
+
+    # Reset the inferior's cwd.
+    gdb_test_no_output "set cwd" "resetting inferior cwd"
+
+    with_test_prefix "running without set cwd" {
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$gdb_cwd\", .*" \
+	"inferior cwd got reset correctly"
+}
+
+test_cd_into_dir
+clean_restart $binfile
+test_tilde_expansion
+clean_restart $binfile
+test_cwd_reset
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 3e1894410d..1ef38fb32b 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -66,6 +66,7 @@
 #include "x86-nat.h"
 #include "complaints.h"
 #include "inf-child.h"
+#include "gdb_tilde_expand.h"
 
 #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
@@ -2428,6 +2429,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 #ifdef __CYGWIN__
   cygwin_buf_t real_path[__PMAX];
   cygwin_buf_t shell[__PMAX]; /* Path to shell */
+  cygwin_buf_t infcwd[__PMAX];
   const char *sh;
   cygwin_buf_t *toexec;
   cygwin_buf_t *cygallargs;
@@ -2465,6 +2467,17 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
 
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd;
+  if (inferior_cwd != NULL)
+    {
+      expanded_infcwd = gdb_tilde_expand (inferior_cwd);
+      /* Mirror slashes on inferior's cwd.  */
+      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+		    '/', '\\');
+      inferior_cwd = expanded_infcwd.c_str ();
+    }
+
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
 
@@ -2514,6 +2527,11 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
       flags |= DEBUG_PROCESS;
     }
 
+  if (inferior_cwd != NULL
+      && cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
+			   infcwd, strlen (inferior_cwd)) < 0)
+    error (_("Error converting inferior cwd: %d"), errno);
+
 #ifdef __USEWIDE
   args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
 				  * sizeof (wchar_t));
@@ -2574,7 +2592,8 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 		       TRUE,	/* inherit handles */
 		       flags,	/* start flags */
 		       w32_env,	/* environment */
-		       NULL,	/* current directory */
+		       inferior_cwd != NULL ? infcwd : NULL, /* current
+								directory */
 		       &si,
 		       &pi);
   if (w32_env)
@@ -2697,7 +2716,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 			TRUE,	/* inherit handles */
 			flags,	/* start flags */
 			w32env,	/* environment */
-			NULL,	/* current directory */
+			inferior_cwd, /* current directory */
 			&si,
 			&pi);
   if (tty != INVALID_HANDLE_VALUE)
-- 
2.13.3

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-03 16:58             ` Sergio Durigan Junior
@ 2017-10-03 20:09               ` Sergio Durigan Junior
  2017-10-03 21:29                 ` Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-03 20:09 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Tuesday, October 03 2017, I wrote:

> In order to avoid yet-another-version, here's the updated patch with all
> your comments addressed.

Well, Pedro kindly pinged me on IRC to let me know that I had totally
misinterpreted his request to move a paragraph from the "set cwd"
section on gdb.texinfo to the "cd command" section.  Anyway, here's the
updated patch.

Sorry about that.

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

From 0104263e08631b8eefb4efefdd65dbbd0b9cd4ef Mon Sep 17 00:00:00 2001
From: Sergio Durigan Junior <sergiodj@redhat.com>
Date: Mon, 11 Sep 2017 01:13:50 -0400
Subject: [PATCH v6 2/3] Implement "set cwd" command on GDB

This commit adds new "set/show cwd" commands, which are used to
set/show the current working directory of the inferior that will be
started.

The idea here is that "set cwd" will become the de facto way of
setting the inferior's cwd.  Currently, the user can use "cd" for
that, but there are side effects: with "cd", GDB also switches to
another directory, and that can impact the loading of scripts and
other files.  With "set cwd", we separate the logic into a new
command.

To maintain backward compatibility, if the user issues a "cd" command
but doesn't use "set cwd", then the inferior's cwd will still be
changed according to what the user specified.  However, "set cwd" has
precedence over "cd", so it can always be used to override it.

"set cwd" works in the following way:

- If the user sets the inferior's cwd by using "set cwd", then this
  directory is saved into current_inferior ()->cwd and is used when
  the inferior is started (see below).

- If the user doesn't set the inferior's cwd by using "set cwd", but
  rather use the "cd" command as before, then this directory is
  inherited by the inferior because GDB will have chdir'd into it.

On Unix-like hosts, the way the directory is changed before the
inferior execution is by expanding the user set directory before the
fork, and then "chdir" after the call to fork/vfork on
"fork_inferior", but before the actual execution.  On Windows, the
inferior cwd set by the user is passed directly to the CreateProcess
call, which takes care of the actual chdir for us.

This way, we'll make sure that GDB's cwd is not affected by the user
set cwd.

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS (New commands): Mention "set/show cwd".
	* cli/cli-cmds.c (_initialize_cli_cmds): Mention "set cwd" on
	"cd" command's help text.
	* common/common-inferior.h (get_inferior_cwd): New prototype.
	* infcmd.c (inferior_cwd_scratch): New global variable.
	(set_inferior_cwd): New function.
	(get_inferior_cwd): Likewise.
	(set_cwd_command): Likewise.
	(show_cwd_command): Likewise.
	(_initialize_infcmd): Add "set/show cwd" commands.
	* inferior.h (class inferior) <cwd>: New field.
	* nat/fork-inferior.c: Include "gdb_tilde_expand.h".
	(fork_inferior): Change inferior's cwd before its execution.
	* windows-nat.c (windows_create_inferior): Pass inferior's cwd
	to CreateProcess.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* inferiors.c (current_inferior_cwd): New global variable.
	(get_inferior_cwd): New function.
	* inferiors.h (struct process_info) <cwd>: New field.

gdb/doc/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Starting your Program) <The working directory.>:
	Mention new "set cwd" command.
	(Working Directory) <Your Program's Working Directory>:
	Rephrase to explain that "set cwd" exists and is the default
	way to change the inferior's cwd.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/set-cwd.c: New file.
	* gdb.base/set-cwd.exp: Likewise.
---
 gdb/NEWS                           |   3 +
 gdb/cli/cli-cmds.c                 |   8 +-
 gdb/common/common-inferior.h       |   4 +
 gdb/doc/gdb.texinfo                |  55 ++++++++---
 gdb/gdbserver/inferiors.c          |  11 +++
 gdb/infcmd.c                       |  77 +++++++++++++++
 gdb/inferior.h                     |   4 +
 gdb/nat/fork-inferior.c            |  23 +++++
 gdb/testsuite/gdb.base/set-cwd.c   |  31 ++++++
 gdb/testsuite/gdb.base/set-cwd.exp | 197 +++++++++++++++++++++++++++++++++++++
 gdb/windows-nat.c                  |  23 ++++-
 11 files changed, 418 insertions(+), 18 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.c
 create mode 100644 gdb/testsuite/gdb.base/set-cwd.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 81c21b82cc..fcf454833f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -67,6 +67,9 @@ QStartupWithShell
 
 * New commands
 
+set|show cwd
+  Set and show the current working directory for the inferior.
+
 set|show compile-gcc
   Set and show compilation command used for compiling and injecting code
   with the 'compile' commands.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index dde67ee2b3..dad5ffa42e 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1727,9 +1727,11 @@ The commands below can be used to select other frames by number or address."),
 Print working directory.  This is used for your program as well."));
 
   c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+The debugger's current working directory specifies where scripts and other\n\
+files that can be loaded by GDB are located.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_com ("echo", class_support, echo_command, _("\
diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
index 87c13009ed..515a8c0f4e 100644
--- a/gdb/common/common-inferior.h
+++ b/gdb/common/common-inferior.h
@@ -30,4 +30,8 @@ extern const char *get_exec_wrapper ();
    otherwise return 0 in that case.  */
 extern char *get_exec_file (int err);
 
+/* Return the inferior's current working directory.  If nothing has
+   been set, then return NULL.  */
+extern const char *get_inferior_cwd ();
+
 #endif /* ! COMMON_INFERIOR_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9905ff6513..a68107dddb 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -2057,8 +2057,9 @@ environment} to change parts of the environment that affect
 your program.  @xref{Environment, ,Your Program's Environment}.
 
 @item The @emph{working directory.}
-Your program inherits its working directory from @value{GDBN}.  You can set
-the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+You can set your program's working directory with the command
+@kbd{set cwd}.  If you do not set any working directory with this
+command, your program will inherit @value{GDBN}'s working directory.
 @xref{Working Directory, ,Your Program's Working Directory}.
 
 @item The @emph{standard input and output.}
@@ -2434,23 +2435,51 @@ variables to files that are only run when you sign on, such as
 @section Your Program's Working Directory
 
 @cindex working directory (of your program)
-Each time you start your program with @code{run}, it inherits its
-working directory from the current working directory of @value{GDBN}.
-The @value{GDBN} working directory is initially whatever it inherited
-from its parent process (typically the shell), but you can specify a new
-working directory in @value{GDBN} with the @code{cd} command.
-
-The @value{GDBN} working directory also serves as a default for the commands
-that specify files for @value{GDBN} to operate on.  @xref{Files, ,Commands to
-Specify Files}.
+Each time you start your program with @code{run}, the inferior will be
+initialized with the current working directory specified by the
+@kbd{set cwd} command.  If no directory has been specified by this
+command, then the inferior will inherit @value{GDBN}'s current working
+directory as its working directory.
+
+@table @code
+@kindex set cwd
+@cindex change inferior's working directory
+@anchor{set cwd command}
+@item set cwd @r{[}@var{directory}@r{]}
+Set the inferior's working directory to @var{directory}, which will be
+@code{glob}-expanded in order to resolve tildes (@file{~}).  If no
+argument has been specified, the command clears the setting and resets
+it to an empty state.  This setting has no effect on @value{GDBN}'s
+working directory, and it only takes effect the next time you start
+the inferior.  The @file{~} in @var{directory} is a short for the
+@dfn{home directory}, usually pointed to by the @env{HOME} environment
+variable.  On MS-Windows, if @env{HOME} is not defined, @value{GDBN}
+uses the concatenation of @env{HOMEDRIVE} and @env{HOMEPATH} as
+fallback.
+
+You can also change @value{GDBN}'s current working directory by using
+the @code{cd} command.
+@xref{cd command}
+
+@kindex show cwd
+@cindex show inferior's working directory
+@item show cwd
+Show the inferior's working directory.  If no directory has been
+specified by @kbd{set cwd}, then the default inferior's working
+directory is the same as @value{GDBN}'s working directory.
 
-@table @code
 @kindex cd
-@cindex change working directory
+@cindex change @value{GDBN}'s working directory
+@anchor{cd command}
 @item cd @r{[}@var{directory}@r{]}
 Set the @value{GDBN} working directory to @var{directory}.  If not
 given, @var{directory} uses @file{'~'}.
 
+The @value{GDBN} working directory serves as a default for the
+commands that specify files for @value{GDBN} to operate on.
+@xref{Files, ,Commands to Specify Files}.
+@xref{set cwd command}
+
 @kindex pwd
 @item pwd
 Print the @value{GDBN} working directory.
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 3a45959000..57d9956ebb 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -29,6 +29,9 @@ struct thread_info *current_thread;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
 
+/* The current working directory used to start the inferior.  */
+static const char *current_inferior_cwd = NULL;
+
 void
 add_inferior_to_list (struct inferior_list *list,
 		      struct inferior_list_entry *new_inferior)
@@ -445,3 +448,11 @@ switch_to_thread (ptid_t ptid)
   gdb_assert (ptid != minus_one_ptid);
   current_thread = find_thread_ptid (ptid);
 }
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior_cwd;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index da16f5ed6d..dbdf273ca5 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -103,6 +103,10 @@ static void run_command (char *, int);
 
 static char *inferior_args_scratch;
 
+/* Scratch area where the new cwd will be stored by 'set cwd'.  */
+
+static char *inferior_cwd_scratch;
+
 /* Scratch area where 'set inferior-tty' will store user-provided value.
    We'll immediate copy it into per-inferior storage.  */
 
@@ -238,6 +242,60 @@ show_args_command (struct ui_file *file, int from_tty,
   deprecated_show_value_hack (file, from_tty, c, get_inferior_args ());
 }
 
+/* Set the inferior current working directory.  If CWD is NULL, unset
+   the directory.  */
+
+static void
+set_inferior_cwd (const char *cwd)
+{
+  struct inferior *inf = current_inferior ();
+
+  gdb_assert (inf != NULL);
+
+  if (cwd == NULL)
+    inf->cwd.reset ();
+  else
+    inf->cwd.reset (xstrdup (cwd));
+}
+
+/* See common/common-inferior.h.  */
+
+const char *
+get_inferior_cwd ()
+{
+  return current_inferior ()->cwd.get ();
+}
+
+/* Handle the 'set cwd' command.  */
+
+static void
+set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+{
+  if (*inferior_cwd_scratch == '\0')
+    set_inferior_cwd (NULL);
+  else
+    set_inferior_cwd (inferior_cwd_scratch);
+}
+
+/* Handle the 'show cwd' command.  */
+
+static void
+show_cwd_command (struct ui_file *file, int from_tty,
+		  struct cmd_list_element *c, const char *value)
+{
+  const char *cwd = get_inferior_cwd ();
+
+  if (cwd == NULL)
+    fprintf_filtered (gdb_stdout,
+		      _("\
+You have not set the inferior's current working directory.\n\
+The inferior will inherit GDB's cwd.\n"));
+  else
+    fprintf_filtered (gdb_stdout,
+		      _("Current working directory that will be used "
+			"when starting the inferior is \"%s\".\n"), cwd);
+}
+
 \f
 /* Compute command-line string given argument vector.  This does the
    same shell processing as fork_inferior.  */
@@ -3253,6 +3311,25 @@ Follow this command with any number of args, to be passed to the program."),
   gdb_assert (c != NULL);
   set_cmd_completer (c, filename_completer);
 
+  cmd_name = "cwd";
+  add_setshow_string_noescape_cmd (cmd_name, class_run,
+				   &inferior_cwd_scratch, _("\
+Set the current working directory to be used when the inferior is started.\n\
+Changing this setting does not have any effect on inferiors that are\n\
+already running."),
+				   _("\
+Show the current working directory that is used when the inferior is started."),
+				   _("\
+Use this command to change the current working directory that will be used\n\
+when the inferior is started.  This setting does not affect GDB's current\n\
+working directory."),
+				   set_cwd_command,
+				   show_cwd_command,
+				   &setlist, &showlist);
+  c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+  gdb_assert (c != NULL);
+  set_cmd_completer (c, filename_completer);
+
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
 With an argument VAR, prints the value of environment variable VAR to\n\
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 7f2d53e5b3..498d74706a 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -355,6 +355,10 @@ public:
      should never be freed.  */
   char **argv = NULL;
 
+  /* The current working directory that will be used when starting
+     this inferior.  */
+  gdb::unique_xmalloc_ptr<char> cwd;
+
   /* The name of terminal device to use for I/O.  */
   char *terminal = NULL;
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index 6ff119768c..ee1340b832 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -25,6 +25,7 @@
 #include "common-inferior.h"
 #include "common-gdbthread.h"
 #include "signals-state-save-restore.h"
+#include "gdb_tilde_expand.h"
 #include <vector>
 
 extern char **environ;
@@ -298,6 +299,8 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
   char **save_our_env;
   int i;
   int save_errno;
+  const char *inferior_cwd;
+  std::string expanded_inferior_cwd;
 
   /* If no exec file handed to us, get it from the exec-file command
      -- with a good, common error message if none is specified.  */
@@ -339,6 +342,18 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
      the parent and child flushing the same data after the fork.  */
   gdb_flush_out_err ();
 
+  /* Check if the user wants to set a different working directory for
+     the inferior.  */
+  inferior_cwd = get_inferior_cwd ();
+
+  if (inferior_cwd != NULL)
+    {
+      /* Expand before forking because between fork and exec, the child
+	 process may only execute async-signal-safe operations.  */
+      expanded_inferior_cwd = gdb_tilde_expand (inferior_cwd);
+      inferior_cwd = expanded_inferior_cwd.c_str ();
+    }
+
   /* If there's any initialization of the target layers that must
      happen to prepare to handle the child we're about fork, do it
      now...  */
@@ -374,6 +389,14 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
 	 UIs.  */
       close_most_fds ();
 
+      /* Change to the requested working directory if the user
+	 requested it.  */
+      if (inferior_cwd != NULL)
+	{
+	  if (chdir (inferior_cwd) < 0)
+	    trace_start_error_with_name (inferior_cwd);
+	}
+
       if (debug_fork)
 	sleep (debug_fork);
 
diff --git a/gdb/testsuite/gdb.base/set-cwd.c b/gdb/testsuite/gdb.base/set-cwd.c
new file mode 100644
index 0000000000..58738830d6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 Free Software Foundation, Inc.
+
+   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 <stdlib.h>
+#include <unistd.h>
+
+static char dir[4096];
+
+int
+main (int argc, char *argv[])
+{
+  const char *home = getenv ("HOME");
+
+  getcwd (dir, 4096);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/set-cwd.exp b/gdb/testsuite/gdb.base/set-cwd.exp
new file mode 100644
index 0000000000..0d536488e4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/set-cwd.exp
@@ -0,0 +1,197 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2017 Free Software Foundation, Inc.
+
+# 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/>.
+
+if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
+    untested "not implemented on remote servers"
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    return -1
+}
+
+# Test that tilde expansion works fine.
+
+proc_with_prefix test_tilde_expansion { } {
+    global decimal gdb_prompt hex
+
+    gdb_test_no_output "set cwd ~/" "set inferior cwd to ~/ dir"
+
+    if { ![runto_main] } {
+	untested "could not run to main"
+	return -1
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    set home ""
+    set test "print home var"
+    gdb_test_multiple "print home" $test {
+    	-re "\\\$$decimal = $hex \"\(.+\)\"\r\n$gdb_prompt $" {
+    	    set home $expect_out(1,string)
+    	    pass $test
+    	}
+    }
+
+    if { $home == "" } {
+    	untested "could not retrieve home var"
+    	return
+    }
+
+    set curdir ""
+    set test "print dir var"
+    gdb_test_multiple "print dir" $test {
+	-re "\\\$$decimal = \"\(.+\)\"\(, .*repeats.*\)?\r\n$gdb_prompt $" {
+	    set curdir $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $curdir == "" } {
+	untested "could not retrieve dir var"
+	return
+    }
+
+    gdb_assert [string equal $curdir $home] \
+	"successfully chdir'd into home"
+}
+
+# The temporary directory that we will use to start the inferior.
+set tmpdir [standard_output_file ""]
+
+# Test that when we "set cwd" the inferior will be started under the
+# correct working directory and GDB will not be affected by this.
+
+proc_with_prefix test_cd_into_dir { } {
+    global decimal gdb_prompt tmpdir
+
+    set gdb_cwd_before_run ""
+    set test "pwd before run"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd_before_run $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $gdb_cwd_before_run == "" } {
+	untested "could not obtain GDB cwd before run"
+	return
+    }
+
+    # This test only makes sense if $tmpdir != $gdb_cwd_before_run
+    if { ![gdb_assert ![string equal $tmpdir $gdb_cwd_before_run] \
+	       "make sure that tmpdir and GDB's cwd are different"] } {
+	return -1
+    }
+
+    gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+    if { ![runto_main] } {
+	untested "could not run to main"
+	return -1
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	"inferior cwd is correctly set"
+
+    set gdb_cwd_after_run ""
+    set test "pwd after run"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd_after_run $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $gdb_cwd_after_run == "" } {
+	untested "could not obtain GDB cwd after run"
+	return
+    }
+
+    gdb_assert [string equal $gdb_cwd_before_run $gdb_cwd_after_run] \
+	"GDB cwd is unchanged after running inferior"
+}
+
+# Test that executing "set cwd" without arguments will reset the
+# inferior's cwd setting to its previous state.
+
+proc_with_prefix test_cwd_reset { } {
+    global decimal gdb_prompt tmpdir
+
+    set gdb_cwd ""
+    set test "GDB cwd"
+    gdb_test_multiple "pwd" $test {
+	-re "Working directory \(.*\)\.\r\n$gdb_prompt $" {
+	    set gdb_cwd $expect_out(1,string)
+	}
+    }
+
+    if { $gdb_cwd == "" } {
+	untested "could not obtain GDB cwd"
+	return
+    }
+
+    # This test only makes sense if $tmpdir != $gdb_cwd.
+    if { ![gdb_assert ![string equal $tmpdir $gdb_cwd] \
+	       "make sure that tmpdir and GDB's cwd are different"] } {
+	return -1
+    }
+
+    gdb_test_no_output "set cwd $tmpdir" "set inferior cwd to temp dir"
+
+    with_test_prefix "running with set cwd" {
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$tmpdir\", .*" \
+	"inferior cwd is correctly set"
+
+    # Reset the inferior's cwd.
+    gdb_test_no_output "set cwd" "resetting inferior cwd"
+
+    with_test_prefix "running without set cwd" {
+	if { ![runto_main] } {
+	    untested "could not run to main"
+	    return -1
+	}
+    }
+
+    gdb_breakpoint [gdb_get_line_number "break-here"]
+    gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+    gdb_test "print dir" "\\\$$decimal = \"$gdb_cwd\", .*" \
+	"inferior cwd got reset correctly"
+}
+
+test_cd_into_dir
+clean_restart $binfile
+test_tilde_expansion
+clean_restart $binfile
+test_cwd_reset
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 3e1894410d..1ef38fb32b 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -66,6 +66,7 @@
 #include "x86-nat.h"
 #include "complaints.h"
 #include "inf-child.h"
+#include "gdb_tilde_expand.h"
 
 #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
@@ -2428,6 +2429,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 #ifdef __CYGWIN__
   cygwin_buf_t real_path[__PMAX];
   cygwin_buf_t shell[__PMAX]; /* Path to shell */
+  cygwin_buf_t infcwd[__PMAX];
   const char *sh;
   cygwin_buf_t *toexec;
   cygwin_buf_t *cygallargs;
@@ -2465,6 +2467,17 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
 
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd;
+  if (inferior_cwd != NULL)
+    {
+      expanded_infcwd = gdb_tilde_expand (inferior_cwd);
+      /* Mirror slashes on inferior's cwd.  */
+      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+		    '/', '\\');
+      inferior_cwd = expanded_infcwd.c_str ();
+    }
+
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
 
@@ -2514,6 +2527,11 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
       flags |= DEBUG_PROCESS;
     }
 
+  if (inferior_cwd != NULL
+      && cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
+			   infcwd, strlen (inferior_cwd)) < 0)
+    error (_("Error converting inferior cwd: %d"), errno);
+
 #ifdef __USEWIDE
   args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
 				  * sizeof (wchar_t));
@@ -2574,7 +2592,8 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 		       TRUE,	/* inherit handles */
 		       flags,	/* start flags */
 		       w32_env,	/* environment */
-		       NULL,	/* current directory */
+		       inferior_cwd != NULL ? infcwd : NULL, /* current
+								directory */
 		       &si,
 		       &pi);
   if (w32_env)
@@ -2697,7 +2716,7 @@ windows_create_inferior (struct target_ops *ops, const char *exec_file,
 			TRUE,	/* inherit handles */
 			flags,	/* start flags */
 			w32env,	/* environment */
-			NULL,	/* current directory */
+			inferior_cwd, /* current directory */
 			&si,
 			&pi);
   if (tty != INVALID_HANDLE_VALUE)
-- 
2.13.3

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-03 20:09               ` Sergio Durigan Junior
@ 2017-10-03 21:29                 ` Pedro Alves
  2017-10-04  5:40                   ` Eli Zaretskii
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-10-03 21:29 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches, Eli Zaretskii

On 10/03/2017 09:08 PM, Sergio Durigan Junior wrote:
> On Tuesday, October 03 2017, I wrote:
> 
>> In order to avoid yet-another-version, here's the updated patch with all
>> your comments addressed.
> 
> Well, Pedro kindly pinged me on IRC to let me know that I had totally
> misinterpreted his request to move a paragraph from the "set cwd"
> section on gdb.texinfo to the "cd command" section.  Anyway, here's the
> updated patch.

Thanks, this version looks good to me, but please give Eli a chance
to take a look too.

> Sorry about that.

No worries.

Thanks,
Pedro Alves

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-03 21:29                 ` Pedro Alves
@ 2017-10-04  5:40                   ` Eli Zaretskii
  2017-10-04  6:10                     ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: Eli Zaretskii @ 2017-10-04  5:40 UTC (permalink / raw)
  To: Pedro Alves; +Cc: sergiodj, gdb-patches

> Cc: GDB Patches <gdb-patches@sourceware.org>, Eli Zaretskii <eliz@gnu.org>
> From: Pedro Alves <palves@redhat.com>
> Date: Tue, 3 Oct 2017 22:29:27 +0100
> 
> > Well, Pedro kindly pinged me on IRC to let me know that I had totally
> > misinterpreted his request to move a paragraph from the "set cwd"
> > section on gdb.texinfo to the "cd command" section.  Anyway, here's the
> > updated patch.
> 
> Thanks, this version looks good to me, but please give Eli a chance
> to take a look too.

LGTM, thanks.

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

* Re: [PATCH v5 3/3] Extend "set cwd" to work on gdbserver
  2017-10-03 16:45       ` Sergio Durigan Junior
@ 2017-10-04  6:09         ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-04  6:09 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Tuesday, October 03 2017, I wrote:

> On Tuesday, October 03 2017, Pedro Alves wrote:
>
>> This version looks good to me, with one tiny nit below.
>>
>> On 09/29/2017 11:58 PM, Sergio Durigan Junior wrote:
>>
>>> +/* Helper function to set the current working directory for the
>>> +   inferior in the remote.  */
>>
>> "in the remote" sounds a bit odd.  Missing word?
>> Maybe "remote target."?
>
> Indeed, thanks.  Added the word.

Pushed.

d092c5a2465ece3435131ae6fef1ccb6e70986cb

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

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

* Re: [PATCH v5 1/3] Introduce gdb_tilde_expand
  2017-10-03 15:15     ` Pedro Alves
@ 2017-10-04  6:09       ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-04  6:09 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches, Eli Zaretskii

On Tuesday, October 03 2017, Pedro Alves wrote:

> On 09/29/2017 11:58 PM, Sergio Durigan Junior wrote:
>> Currently, whenever we want to handle paths provided by the user and
>> perform tilde expansion on GDB, we rely on "tilde_expand", which comes
>> from readline.  This was enough for our use cases so far, but the
>> situation will change when we start dealing with paths on gdbserver as
>> well, which is what the next patches implement.
>> 
>> Unfortunately it is not possible to use "tilde_expand" in this case
>> because gdbserver doesn't use readline.  For that reason I decided to
>> implement a new "gdb_tilde_expand" function, which is basically a
>> wrapper for "glob" and its GNU extension, GLOB_TILDE_CHECK.  With the
>> import of the "glob" module from gnulib, this is a no-brainer.
>> 
>
> OK.

Thanks, pushed.

7da0a8867419fc4a2a64d49cc71a14bd145cebff

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

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-04  5:40                   ` Eli Zaretskii
@ 2017-10-04  6:10                     ` Sergio Durigan Junior
  2017-10-06  2:37                       ` asmwarrior
  0 siblings, 1 reply; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-04  6:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Pedro Alves, gdb-patches

On Wednesday, October 04 2017, Eli Zaretskii wrote:

>> Cc: GDB Patches <gdb-patches@sourceware.org>, Eli Zaretskii <eliz@gnu.org>
>> From: Pedro Alves <palves@redhat.com>
>> Date: Tue, 3 Oct 2017 22:29:27 +0100
>> 
>> > Well, Pedro kindly pinged me on IRC to let me know that I had totally
>> > misinterpreted his request to move a paragraph from the "set cwd"
>> > section on gdb.texinfo to the "cd command" section.  Anyway, here's the
>> > updated patch.
>> 
>> Thanks, this version looks good to me, but please give Eli a chance
>> to take a look too.
>
> LGTM, thanks.

Thanks, pushed.

bc3b087de2401c65c02730d346e8bea4dc0504ae

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

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

* Re: [PATCH v5 2/3] Implement "set cwd" command on GDB
  2017-10-04  6:10                     ` Sergio Durigan Junior
@ 2017-10-06  2:37                       ` asmwarrior
  2017-10-06 10:54                         ` [pushed] Fix GDB build under msys+mingw gcc 32bit (Re: [PATCH v5 2/3] Implement "set cwd" command on GDB) Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: asmwarrior @ 2017-10-06  2:37 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: gdb-patches

On 10/4/2017 2:10 PM, Sergio Durigan Junior wrote:
> On Wednesday, October 04 2017, Eli Zaretskii wrote:
> 
>>> Cc: GDB Patches <gdb-patches@sourceware.org>, Eli Zaretskii <eliz@gnu.org>
>>> From: Pedro Alves <palves@redhat.com>
>>> Date: Tue, 3 Oct 2017 22:29:27 +0100
>>>
>>>> Well, Pedro kindly pinged me on IRC to let me know that I had totally
>>>> misinterpreted his request to move a paragraph from the "set cwd"
>>>> section on gdb.texinfo to the "cd command" section.  Anyway, here's the
>>>> updated patch.
>>>
>>> Thanks, this version looks good to me, but please give Eli a chance
>>> to take a look too.
>>
>> LGTM, thanks.
> 
> Thanks, pushed.
> 
> bc3b087de2401c65c02730d346e8bea4dc0504ae
> 

I see a build error when building GDB under msys+mingw gcc 32bit.

g++ -x c++ -std=gnu++11 -g -O2    -I. -I../../../binutils-gdb/gdb/gdbserver -I../../../binutils-gdb/gdb/gdbserver/../common -I../../../binutils-gdb/gdb/gdbserver/../regformats -I../../../binutils-gdb/gdb/gdbserver/.. -I../../../binutils-gdb/gdb/gdbserver/../../include -I../../../binutils-gdb/gdb/gdbserver/../gnulib/import -Ibuild-gnulib-gdbserver/import  -Wall -Wpointer-arith -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wempty-body -Wunused-but-set-parameter -Wunused-but-set-variable -Wno-sign-compare -Wno-narrowing -Wno-error=maybe-uninitialized -Wno-format -Werror -DGDBSERVER -c -o win32-low.o -MT win32-low.o -MMD -MP -MF .deps/win32-low.Tpo ../../../binutils-gdb/gdb/gdbserver/win32-low.c
../../../binutils-gdb/gdb/gdbserver/win32-low.c: In function 'BOOL create_process(const char*, char*, DWORD, PROCESS_INFORMATION*)':
../../../binutils-gdb/gdb/gdbserver/win32-low.c:566:48: error: 'get_inferior_cwd' was not declared in this scope
   const char *inferior_cwd = get_inferior_cwd ();
                                                ^
make[4]: *** [win32-low.o] Error 1

It can be simply fixed by adding the header file:

 gdb/gdbserver/win32-low.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index c11926f7c6..f9c890f164 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -33,6 +33,7 @@
 #include <psapi.h>
 #include <process.h>
 #include "gdb_tilde_expand.h"
+#include "common-inferior.h"
 
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>


Thanks

Yuanhui Zhang

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

* [pushed] Fix GDB build under msys+mingw gcc 32bit (Re: [PATCH v5 2/3] Implement "set cwd" command on GDB)
  2017-10-06  2:37                       ` asmwarrior
@ 2017-10-06 10:54                         ` Pedro Alves
  2017-10-06 11:06                           ` [pushed] Fix more GDB build breakage on mingw32 " Pedro Alves
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-10-06 10:54 UTC (permalink / raw)
  To: asmwarrior, Sergio Durigan Junior; +Cc: gdb-patches

On 10/06/2017 03:37 AM, asmwarrior wrote:

> I see a build error when building GDB under msys+mingw gcc 32bit.
> 
> g++ -x c++ -std=gnu++11 -g -O2    -I. -I../../../binutils-gdb/gdb/gdbserver -I../../../binutils-gdb/gdb/gdbserver/../common -I../../../binutils-gdb/gdb/gdbserver/../regformats -I../../../binutils-gdb/gdb/gdbserver/.. -I../../../binutils-gdb/gdb/gdbserver/../../include -I../../../binutils-gdb/gdb/gdbserver/../gnulib/import -Ibuild-gnulib-gdbserver/import  -Wall -Wpointer-arith -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wempty-body -Wunused-but-set-parameter -Wunused-but-set-variable -Wno-sign-compare -Wno-narrowing -Wno-error=maybe-uninitialized -Wno-format -Werror -DGDBSERVER -c -o win32-low.o -MT win32-low.o -MMD -MP -MF .deps/win32-low.Tpo ../../../binutils-gdb/gdb/gdbserver/win32-low.c
> ../../../binutils-gdb/gdb/gdbserver/win32-low.c: In function 'BOOL create_process(const char*, char*, DWORD, PROCESS_INFORMATION*)':
> ../../../binutils-gdb/gdb/gdbserver/win32-low.c:566:48: error: 'get_inferior_cwd' was not declared in this scope
>    const char *inferior_cwd = get_inferior_cwd ();
>                                                 ^
> make[4]: *** [win32-low.o] Error 1
> 
> It can be simply fixed by adding the header file:

Pushed as below.  Thanks.

From b79f7801a2c555ee4ff4bc3050141e83158f66d4 Mon Sep 17 00:00:00 2001
From: Yuanhui Zhang <asmwarrior@gmail.com>
Date: Fri, 6 Oct 2017 11:44:54 +0100
Subject: [PATCH] Fix GDB build under msys+mingw gcc 32bit

I see a build error when building GDB under msys+mingw gcc 32bit:

 g++ -x c++ -std=gnu++11 -g -O2    -I. -I../../../binutils-gdb/gdb/gdbserver -I../../../binutils-gdb/gdb/gdbserver/../common -I../../../binutils-gdb/gdb/gdbserver/../regformats -I../../../binutils-gdb/gdb/gdbserver/.. -I../../../binutils-gdb/gdb/gdbserver/../../include -I../../../binutils-gdb/gdb/gdbserver/../gnulib/import -Ibuild-gnulib-gdbserver/import  -Wall -Wpointer-arith -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wempty-body -Wunused-but-set-parameter -Wunused-but-set-variable -Wno-sign-compare -Wno-narrowing -Wno-error=maybe-uninitialized -Wno-format -Werror -DGDBSERVER -c -o win32-low.o -MT win32-low.o -MMD -MP -MF .deps/win32-low.Tpo ../../../binutils-gdb/gdb/gdbserver/win32-low.c
 ../../../binutils-gdb/gdb/gdbserver/win32-low.c: In function 'BOOL create_process(const char*, char*, DWORD, PROCESS_INFORMATION*)':
 ../../../binutils-gdb/gdb/gdbserver/win32-low.c:566:48: error: 'get_inferior_cwd' was not declared in this scope
    const char *inferior_cwd = get_inferior_cwd ();
						 ^
 make[4]: *** [win32-low.o] Error 1

It can be fixed by simply including the right header file.

gdb/gdbserver/ChangeLog:
2017-10-06  Yuanhui Zhang  <asmwarrior@gmail.com>

	* win32-low.c: Include "common-inferior.h".
---
 gdb/gdbserver/ChangeLog   | 4 ++++
 gdb/gdbserver/win32-low.c | 1 +
 2 files changed, 5 insertions(+)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 0bdeaba..5bcd717 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,7 @@
+2017-10-06  Yuanhui Zhang  <asmwarrior@gmail.com>
+
+	* win32-low.c: Include "common-inferior.h".
+
 2017-10-04  Sergio Durigan Junior  <sergiodj@redhat.com>
 
 	* inferiors.c (set_inferior_cwd): New function.
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index c11926f..f9c890f 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -33,6 +33,7 @@
 #include <psapi.h>
 #include <process.h>
 #include "gdb_tilde_expand.h"
+#include "common-inferior.h"
 
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>
-- 
2.5.5


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

* [pushed] Fix more GDB build breakage on mingw32 (Re: [PATCH v5 2/3] Implement "set cwd" command on GDB)
  2017-10-06 10:54                         ` [pushed] Fix GDB build under msys+mingw gcc 32bit (Re: [PATCH v5 2/3] Implement "set cwd" command on GDB) Pedro Alves
@ 2017-10-06 11:06                           ` Pedro Alves
  2017-10-06 11:15                             ` asmwarrior
  0 siblings, 1 reply; 131+ messages in thread
From: Pedro Alves @ 2017-10-06 11:06 UTC (permalink / raw)
  To: asmwarrior, Sergio Durigan Junior; +Cc: gdb-patches

On 10/06/2017 11:54 AM, Pedro Alves wrote:

> Pushed as below.  Thanks.

Pushed this as well.

From a1b85d282f408dfd18a27539874846197f7e4044 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Fri, 6 Oct 2017 11:58:56 +0100
Subject: [PATCH] Fix more GDB build breakage on mingw32

With F23's mingw gcc 5.3.0, I'm seeing:

 i686-w64-mingw32-g++ -x c++ -std=gnu++11 -g3 -O0   -I. -I../../src/gdb -I../../src/gdb/common -I../../src/gdb/config -DLOCALEDIR="\"/usr/local/share/locale\"" -DHAVE_CONFIG_H -I../../src/gdb/../include/opcode -I../../src/gdb/../opcodes/.. -I../../src/gdb/../readline/.. -I../../src/gdb/../zlib -I../bfd -I../../src/gdb/../bfd -I../../src/gdb/../include -I../libdecnumber -I../../src/gdb/../libdecnumber  -I../../src/gdb/gnulib/import -Ibuild-gnulib/import   -I/home/pedro/src/expat/install-win32//include   -Wall -Wpointer-arith -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wempty-body -Wunused-but-set-parameter -Wunused-but-set-variable -Wno-sign-compare -Wno-narrowing -Wno-error=maybe-uninitialized -Wno-format -Werror -c -o windows-nat.o -MT windows-nat.o -MMD -MP -MF ./.deps/windows-nat.o.Tpo ../../src/gdb/windows-nat.c
 ../../src/gdb/windows-nat.c: In function 'void windows_create_inferior(target_ops*, const char*, const string&, char**, int)':
 ../../src/gdb/windows-nat.c:2476:7: error: 'replace' is not a member of 'std'
	std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
	^

gdb/Changelog:
2017-10-06  Pedro Alves  <palves@redhat.com>

	* windows-nat.c: Include <algorithm>.
---
 gdb/ChangeLog     | 4 ++++
 gdb/windows-nat.c | 1 +
 2 files changed, 5 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0f92439..559c3b8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2017-10-06  Pedro Alves  <palves@redhat.com>
+
+	* windows-nat.c: Include <algorithm>.
+
 2017-10-06  Yao Qi  <yao.qi@linaro.org>
 
 	* configure.tgt (i386_tobjs): New variable.
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 1ef38fb..98c32d8 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -42,6 +42,7 @@
 #include <sys/cygwin.h>
 #include <cygwin/version.h>
 #endif
+#include <algorithm>
 
 #include "buildsym.h"
 #include "filenames.h"
-- 
2.5.5


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

* Re: [pushed] Fix more GDB build breakage on mingw32 (Re: [PATCH v5 2/3] Implement "set cwd" command on GDB)
  2017-10-06 11:06                           ` [pushed] Fix more GDB build breakage on mingw32 " Pedro Alves
@ 2017-10-06 11:15                             ` asmwarrior
  2017-10-09 21:58                               ` Sergio Durigan Junior
  0 siblings, 1 reply; 131+ messages in thread
From: asmwarrior @ 2017-10-06 11:15 UTC (permalink / raw)
  To: Pedro Alves, Sergio Durigan Junior; +Cc: gdb-patches

On 10/6/2017 7:06 PM, Pedro Alves wrote:
> On 10/06/2017 11:54 AM, Pedro Alves wrote:
>
>> Pushed as below.  Thanks.
> Pushed this as well.
>
> From a1b85d282f408dfd18a27539874846197f7e4044 Mon Sep 17 00:00:00 2001
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 6 Oct 2017 11:58:56 +0100
> Subject: [PATCH] Fix more GDB build breakage on mingw32
>
> With F23's mingw gcc 5.3.0, I'm seeing:
>
>  i686-w64-mingw32-g++ -x c++ -std=gnu++11 -g3 -O0   -I. -I../../src/gdb -I../../src/gdb/common -I../../src/gdb/config -DLOCALEDIR="\"/usr/local/share/locale\"" -DHAVE_CONFIG_H -I../../src/gdb/../include/opcode -I../../src/gdb/../opcodes/.. -I../../src/gdb/../readline/.. -I../../src/gdb/../zlib -I../bfd -I../../src/gdb/../bfd -I../../src/gdb/../include -I../libdecnumber -I../../src/gdb/../libdecnumber  -I../../src/gdb/gnulib/import -Ibuild-gnulib/import   -I/home/pedro/src/expat/install-win32//include   -Wall -Wpointer-arith -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wempty-body -Wunused-but-set-parameter -Wunused-but-set-variable -Wno-sign-compare -Wno-narrowing -Wno-error=maybe-uninitialized -Wno-format -Werror -c -o windows-nat.o -MT windows-nat.o -MMD -MP -MF ./.deps/windows-nat.o.Tpo ../../src/gdb/windows-nat.c
>  ../../src/gdb/windows-nat.c: In function 'void windows_create_inferior(target_ops*, const char*, const string&, char**, int)':
>  ../../src/gdb/windows-nat.c:2476:7: error: 'replace' is not a member of 'std'
> 	std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
> 	^
>
> gdb/Changelog:
> 2017-10-06  Pedro Alves  <palves@redhat.com>
>
> 	* windows-nat.c: Include <algorithm>.
> ---
>  gdb/ChangeLog     | 4 ++++
>  gdb/windows-nat.c | 1 +
>  2 files changed, 5 insertions(+)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 0f92439..559c3b8 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,7 @@
> +2017-10-06  Pedro Alves  <palves@redhat.com>
> +
> +	* windows-nat.c: Include <algorithm>.
> +
>  2017-10-06  Yao Qi  <yao.qi@linaro.org>
>  
>  	* configure.tgt (i386_tobjs): New variable.
> diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
> index 1ef38fb..98c32d8 100644
> --- a/gdb/windows-nat.c
> +++ b/gdb/windows-nat.c
> @@ -42,6 +42,7 @@
>  #include <sys/cygwin.h>
>  #include <cygwin/version.h>
>  #endif
> +#include <algorithm>
>  
>  #include "buildsym.h"
>  #include "filenames.h"


Hi, Pedro Alves, thanks for verifying the changes.

Aha, I also have this patch fixed in my local git repo, but I just forgot to submit it, because I have locally a lot of other changes. :-)

Thanks.

Yuanhui Zhang

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

* Re: [pushed] Fix more GDB build breakage on mingw32 (Re: [PATCH v5 2/3] Implement "set cwd" command on GDB)
  2017-10-06 11:15                             ` asmwarrior
@ 2017-10-09 21:58                               ` Sergio Durigan Junior
  0 siblings, 0 replies; 131+ messages in thread
From: Sergio Durigan Junior @ 2017-10-09 21:58 UTC (permalink / raw)
  To: asmwarrior; +Cc: Pedro Alves, gdb-patches

On Friday, October 06 2017, asmwarrior@gmail.com wrote:

> On 10/6/2017 7:06 PM, Pedro Alves wrote:
>> On 10/06/2017 11:54 AM, Pedro Alves wrote:
>>
>>> Pushed as below.  Thanks.
>> Pushed this as well.
>>
>> From a1b85d282f408dfd18a27539874846197f7e4044 Mon Sep 17 00:00:00 2001
>> From: Pedro Alves <palves@redhat.com>
>> Date: Fri, 6 Oct 2017 11:58:56 +0100
>> Subject: [PATCH] Fix more GDB build breakage on mingw32
>>
>> With F23's mingw gcc 5.3.0, I'm seeing:
>>
>>  i686-w64-mingw32-g++ -x c++ -std=gnu++11 -g3 -O0   -I. -I../../src/gdb -I../../src/gdb/common -I../../src/gdb/config -DLOCALEDIR="\"/usr/local/share/locale\"" -DHAVE_CONFIG_H -I../../src/gdb/../include/opcode -I../../src/gdb/../opcodes/.. -I../../src/gdb/../readline/.. -I../../src/gdb/../zlib -I../bfd -I../../src/gdb/../bfd -I../../src/gdb/../include -I../libdecnumber -I../../src/gdb/../libdecnumber  -I../../src/gdb/gnulib/import -Ibuild-gnulib/import   -I/home/pedro/src/expat/install-win32//include   -Wall -Wpointer-arith -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wempty-body -Wunused-but-set-parameter -Wunused-but-set-variable -Wno-sign-compare -Wno-narrowing -Wno-error=maybe-uninitialized -Wno-format -Werror -c -o windows-nat.o -MT windows-nat.o -MMD -MP -MF ./.deps/windows-nat.o.Tpo ../../src/gdb/windows-nat.c
>>  ../../src/gdb/windows-nat.c: In function 'void windows_create_inferior(target_ops*, const char*, const string&, char**, int)':
>>  ../../src/gdb/windows-nat.c:2476:7: error: 'replace' is not a member of 'std'
>> 	std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
>> 	^
>>
>> gdb/Changelog:
>> 2017-10-06  Pedro Alves  <palves@redhat.com>
>>
>> 	* windows-nat.c: Include <algorithm>.
>> ---
>>  gdb/ChangeLog     | 4 ++++
>>  gdb/windows-nat.c | 1 +
>>  2 files changed, 5 insertions(+)
>>
>> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
>> index 0f92439..559c3b8 100644
>> --- a/gdb/ChangeLog
>> +++ b/gdb/ChangeLog
>> @@ -1,3 +1,7 @@
>> +2017-10-06  Pedro Alves  <palves@redhat.com>
>> +
>> +	* windows-nat.c: Include <algorithm>.
>> +
>>  2017-10-06  Yao Qi  <yao.qi@linaro.org>
>>  
>>  	* configure.tgt (i386_tobjs): New variable.
>> diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
>> index 1ef38fb..98c32d8 100644
>> --- a/gdb/windows-nat.c
>> +++ b/gdb/windows-nat.c
>> @@ -42,6 +42,7 @@
>>  #include <sys/cygwin.h>
>>  #include <cygwin/version.h>
>>  #endif
>> +#include <algorithm>
>>  
>>  #include "buildsym.h"
>>  #include "filenames.h"
>
>
> Hi, Pedro Alves, thanks for verifying the changes.
>
> Aha, I also have this patch fixed in my local git repo, but I just forgot to submit it, because I have locally a lot of other changes. :-)

Sorry about the breakage.  I guess I forgot to recompile my local tree
with mingw after I implemented some improvements to the Windows support.
This reminds me that it's a good idea to have a mingw builder in our
BuildBot (just building, not testing).  I'll see about implementing
this.

Thank you and Pedro for catching and fixing the issues.

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

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

end of thread, other threads:[~2017-10-09 21:58 UTC | newest]

Thread overview: 131+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-12  4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior
2017-09-12  4:23 ` [PATCH 4/4] Implement " Sergio Durigan Junior
2017-09-12 14:50   ` Eli Zaretskii
2017-09-12  4:23 ` [PATCH 3/4] Introduce gdb_chdir Sergio Durigan Junior
2017-09-12 14:53   ` Eli Zaretskii
2017-09-13 23:00     ` Sergio Durigan Junior
2017-09-13 16:07   ` Pedro Alves
2017-09-14 15:14     ` Sergio Durigan Junior
2017-09-14 15:23       ` Pedro Alves
2017-09-14 15:33         ` Sergio Durigan Junior
2017-09-12  4:23 ` [PATCH 2/4] Import "glob" module from gnulib Sergio Durigan Junior
2017-09-12  4:23 ` [PATCH 1/4] Make gdb_dirbuf local to functions Sergio Durigan Junior
2017-09-13 15:12   ` Pedro Alves
2017-09-13 22:03     ` Sergio Durigan Junior
2017-09-13 22:19       ` Pedro Alves
2017-09-13 22:46         ` Sergio Durigan Junior
2017-09-13 23:47           ` Pedro Alves
2017-09-12 14:55 ` [PATCH 0/4] New "set cwd" command Eli Zaretskii
2017-09-12 16:48   ` Sergio Durigan Junior
2017-09-12 16:57     ` Eli Zaretskii
2017-09-12 17:51       ` Sergio Durigan Junior
2017-09-13 15:00         ` Pedro Alves
2017-09-13 15:06           ` Eli Zaretskii
2017-09-13 21:56             ` Sergio Durigan Junior
2017-09-13 14:54 ` Pedro Alves
2017-09-13 21:54   ` Sergio Durigan Junior
2017-09-19  4:28 ` [PATCH v2 0/5] " Sergio Durigan Junior
2017-09-19  4:28   ` [PATCH v2 4/5] Implement " Sergio Durigan Junior
2017-09-20 14:01     ` Pedro Alves
2017-09-20 23:08       ` Sergio Durigan Junior
2017-09-19  4:28   ` [PATCH v2 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
2017-09-20 12:24     ` Pedro Alves
2017-09-20 17:02       ` Sergio Durigan Junior
2017-09-19  4:28   ` [PATCH v2 3/5] Introduce gdb_chdir Sergio Durigan Junior
2017-09-20 13:14     ` Pedro Alves
2017-09-20 17:25       ` Sergio Durigan Junior
2017-09-19  4:33   ` [PATCH v2 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
2017-09-20 14:34     ` Pedro Alves
2017-09-20 23:49       ` Sergio Durigan Junior
2017-09-21  1:37         ` Sergio Durigan Junior
2017-09-22 10:47         ` Pedro Alves
2017-09-22 18:33           ` Sergio Durigan Junior
2017-09-27 13:28             ` Pedro Alves
2017-09-19  4:37   ` [PATCH v2 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
2017-09-20 12:17     ` Pedro Alves
2017-09-20 17:17       ` Sergio Durigan Junior
2017-09-20 17:33         ` Pedro Alves
2017-09-20 18:31           ` Sergio Durigan Junior
2017-09-20 20:30             ` Sergio Durigan Junior
2017-09-20 22:44               ` Pedro Alves
2017-09-20 23:12                 ` Sergio Durigan Junior
2017-09-20 23:25                   ` Pedro Alves
2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior
2017-09-21 22:59   ` [PATCH v3 2/5] Get rid of "gdb_dirbuf" and use "getcwd (NULL, 0)" Sergio Durigan Junior
2017-09-22 11:19     ` Pedro Alves
2017-09-22 17:30       ` Sergio Durigan Junior
2017-09-21 22:59   ` [PATCH v3 1/5] Import "glob" and "getcwd" modules from gnulib Sergio Durigan Junior
2017-09-22 11:01     ` Pedro Alves
2017-09-22 17:29       ` Sergio Durigan Junior
2017-09-21 22:59   ` [PATCH v3 3/5] Introduce gdb_tilde_expand Sergio Durigan Junior
2017-09-22 11:57     ` Pedro Alves
2017-09-22 17:37       ` Sergio Durigan Junior
2017-09-22 17:41         ` Pedro Alves
2017-09-22 18:07           ` Sergio Durigan Junior
2017-09-22 18:20             ` Pedro Alves
2017-09-22 18:22               ` Sergio Durigan Junior
2017-09-21 22:59   ` [PATCH v3 4/5] Implement "set cwd" command on GDB Sergio Durigan Junior
2017-09-22  8:03     ` Eli Zaretskii
2017-09-22 12:31       ` Pedro Alves
2017-09-22 18:15         ` Sergio Durigan Junior
2017-09-22 18:00       ` Sergio Durigan Junior
2017-09-22 18:56         ` Eli Zaretskii
2017-09-22 19:24           ` Pedro Alves
2017-09-22 19:41             ` Eli Zaretskii
2017-09-22 20:27               ` Sergio Durigan Junior
2017-09-22 20:37                 ` Pedro Alves
2017-09-23  5:55                   ` Eli Zaretskii
2017-09-27 14:02                     ` Pedro Alves
2017-09-29 15:31                       ` Eli Zaretskii
2017-09-29 15:46                         ` Pedro Alves
2017-09-29 17:51                           ` Eli Zaretskii
2017-09-23  5:52                 ` Eli Zaretskii
2017-09-22 20:24           ` Sergio Durigan Junior
2017-09-23  5:51             ` Eli Zaretskii
2017-09-22 20:55           ` Sergio Durigan Junior
2017-09-23  6:05             ` Eli Zaretskii
2017-09-23 17:01               ` Sergio Durigan Junior
2017-09-21 23:06   ` [PATCH v3 5/5] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
2017-09-22  8:12     ` Eli Zaretskii
2017-09-22 18:46       ` Sergio Durigan Junior
2017-09-22 19:09         ` Eli Zaretskii
2017-09-22 20:47           ` Sergio Durigan Junior
2017-09-23  6:00             ` Eli Zaretskii
2017-09-27 14:42     ` Pedro Alves
2017-09-27 21:48       ` Sergio Durigan Junior
2017-09-29 14:03         ` Pedro Alves
2017-09-29 18:33           ` Sergio Durigan Junior
2017-09-28  4:10 ` [PATCH v4 0/3] New "set cwd" command Sergio Durigan Junior
2017-09-28  4:10   ` [PATCH v4 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
2017-09-29 14:08     ` Pedro Alves
2017-09-29 17:48       ` Sergio Durigan Junior
2017-09-28  4:11   ` [PATCH v4 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
2017-09-29 15:21     ` Pedro Alves
2017-09-29 18:48       ` Sergio Durigan Junior
2017-10-03 15:13         ` Pedro Alves
2017-09-28  4:11   ` [PATCH v4 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
2017-09-29 15:20     ` Pedro Alves
2017-09-29 18:31       ` Sergio Durigan Junior
2017-09-29 22:58 ` [PATCH v5 0/3] New "set cwd" command Sergio Durigan Junior
2017-09-29 22:59   ` [PATCH v5 3/3] Extend "set cwd" to work on gdbserver Sergio Durigan Junior
2017-10-03 15:15     ` Pedro Alves
2017-10-03 16:45       ` Sergio Durigan Junior
2017-10-04  6:09         ` Sergio Durigan Junior
2017-09-29 22:59   ` [PATCH v5 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior
2017-10-03 15:15     ` Pedro Alves
2017-10-03 16:39       ` Sergio Durigan Junior
2017-10-03 16:44         ` Pedro Alves
2017-10-03 16:47           ` Sergio Durigan Junior
2017-10-03 16:58             ` Sergio Durigan Junior
2017-10-03 20:09               ` Sergio Durigan Junior
2017-10-03 21:29                 ` Pedro Alves
2017-10-04  5:40                   ` Eli Zaretskii
2017-10-04  6:10                     ` Sergio Durigan Junior
2017-10-06  2:37                       ` asmwarrior
2017-10-06 10:54                         ` [pushed] Fix GDB build under msys+mingw gcc 32bit (Re: [PATCH v5 2/3] Implement "set cwd" command on GDB) Pedro Alves
2017-10-06 11:06                           ` [pushed] Fix more GDB build breakage on mingw32 " Pedro Alves
2017-10-06 11:15                             ` asmwarrior
2017-10-09 21:58                               ` Sergio Durigan Junior
2017-09-29 22:59   ` [PATCH v5 1/3] Introduce gdb_tilde_expand Sergio Durigan Junior
2017-10-03 15:15     ` Pedro Alves
2017-10-04  6:09       ` Sergio Durigan Junior

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