This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2 5/5] Extend "set cwd" to work on gdbserver


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]