* [PATCH 0/4] New "set cwd" command @ 2017-09-12 4:23 Sergio Durigan Junior 2017-09-12 4:23 ` [PATCH 3/4] Introduce gdb_chdir 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 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 ` Sergio Durigan Junior 2017-09-12 14:53 ` Eli Zaretskii 2017-09-13 16:07 ` Pedro Alves 2017-09-12 4:23 ` [PATCH 4/4] Implement "set cwd" command Sergio Durigan Junior ` (8 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
* 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 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 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 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 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 ` [PATCH 3/4] Introduce gdb_chdir Sergio Durigan Junior @ 2017-09-12 4:23 ` Sergio Durigan Junior 2017-09-12 14:50 ` Eli Zaretskii 2017-09-12 4:23 ` [PATCH 1/4] Make gdb_dirbuf local to functions Sergio Durigan Junior ` (7 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 "set cwd" command 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
* [PATCH 1/4] Make gdb_dirbuf local to functions 2017-09-12 4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior 2017-09-12 4:23 ` [PATCH 3/4] Introduce gdb_chdir Sergio Durigan Junior 2017-09-12 4:23 ` [PATCH 4/4] Implement "set cwd" command Sergio Durigan Junior @ 2017-09-12 4:23 ` Sergio Durigan Junior 2017-09-13 15:12 ` Pedro Alves 2017-09-12 4:23 ` [PATCH 2/4] Import "glob" module from gnulib Sergio Durigan Junior ` (6 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
* 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 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 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
* [PATCH 2/4] Import "glob" module from gnulib 2017-09-12 4:23 [PATCH 0/4] New "set cwd" command Sergio Durigan Junior ` (2 preceding siblings ...) 2017-09-12 4:23 ` [PATCH 1/4] Make gdb_dirbuf local to functions Sergio Durigan Junior @ 2017-09-12 4:23 ` Sergio Durigan Junior 2017-09-12 14:55 ` [PATCH 0/4] New "set cwd" command Eli Zaretskii ` (5 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
* 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 2/4] Import "glob" module from gnulib 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 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 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 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-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
* [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 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
* 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 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
* [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
* 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 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
* [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
* 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 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
* [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
* 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 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
* 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 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 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
* [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 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 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 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
* 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 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
* 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 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
* [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 4/5] Implement "set cwd" command on GDB 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
* 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 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
* [PATCH v3 4/5] Implement "set cwd" command on GDB 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 8:03 ` Eli Zaretskii 2017-09-21 22:59 ` [PATCH v3 3/5] Introduce gdb_tilde_expand 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 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
* 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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: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
* [PATCH v3 3/5] Introduce gdb_tilde_expand 2017-09-21 22:59 ` New "set cwd" command Sergio Durigan Junior ` (2 preceding siblings ...) 2017-09-21 22:59 ` [PATCH v3 4/5] Implement "set cwd" command on GDB Sergio Durigan Junior @ 2017-09-21 22:59 ` Sergio Durigan Junior 2017-09-22 11:57 ` Pedro Alves 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
* 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 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 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 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
* [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 3/5] Introduce gdb_tilde_expand 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 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 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 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 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 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 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
* 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 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
* [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 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior 2017-09-28 4:11 ` [PATCH v4 3/3] Extend "set cwd" to work on gdbserver 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
* 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 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
* [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 ` Sergio Durigan Junior 2017-09-29 15:20 ` Pedro Alves 2017-09-28 4:11 ` [PATCH v4 3/3] Extend "set cwd" to work on gdbserver 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 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 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 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
* [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 ` [PATCH v4 2/3] Implement "set cwd" command on GDB Sergio Durigan Junior @ 2017-09-28 4:11 ` Sergio Durigan Junior 2017-09-29 15:21 ` 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 "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
* 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 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
* 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
* [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
* 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 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 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
* [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 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 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 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 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
* [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
* 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 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
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 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 4/4] Implement "set cwd" command Sergio Durigan Junior 2017-09-12 14:50 ` Eli Zaretskii 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 4:23 ` [PATCH 2/4] Import "glob" module from gnulib Sergio Durigan Junior 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 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 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 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 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-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-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).