+2017-10-04 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.
+
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* NEWS (New commands): Mention "set/show cwd".
* 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.
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.
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 */
+2017-10-04 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.
+
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* gdb.texinfo (Starting your Program) <The working directory.>:
@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
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.
@table @code
@kindex set cwd
@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}
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
+2017-10-04 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.
+
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* inferiors.c (current_inferior_cwd): New global variable.
{
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;
+}
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;
sprintf (own_buf,
"PacketSize=%x;QPassSignals+;QProgramSignals+;"
"QStartupWithShell+;QEnvironmentHexEncoded+;"
- "QEnvironmentReset+;QEnvironmentUnset+",
+ "QEnvironmentReset+;QEnvironmentUnset+;"
+ "QSetWorkingDir+",
PBUFSIZ - 1);
if (target_supports_catch_syscall ())
#include <tlhelp32.h>
#include <psapi.h>
#include <process.h>
+#include "gdb_tilde_expand.h"
#ifndef USE_WIN32API
#include <sys/cygwin.h>
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));
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 */
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
TRUE, /* inherit handles */
flags, /* start flags */
NULL, /* environment */
- NULL, /* current directory */
+ expanded_infcwd.c_str (), /* current directory */
&si, /* start info */
pi); /* proc info */
#endif
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 ();
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 "
PACKET_QPassSignals,
PACKET_QCatchSyscalls,
PACKET_QProgramSignals,
+ PACKET_QSetWorkingDir,
PACKET_QStartupWithShell,
PACKET_QEnvironmentHexEncoded,
PACKET_QEnvironmentReset,
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,
send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
}
+/* Helper function to set the current working directory for the
+ inferior in the remote target. */
+
+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
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)
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);
+2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
+
+ * gdb.base/set-cwd.exp: Make it available on
+ native-extended-gdbserver.
+
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* gdb.base/set-cwd.c: New file.
# 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
}