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:
2017-10-04 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:
2017-10-04 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:
2017-10-04 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:
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* gdb.base/set-cwd.c: New file.
* gdb.base/set-cwd.exp: Likewise.
2017-09-11 13:13:50 +08:00
|
|
|
# This testcase is part of GDB, the GNU debugger.
|
|
|
|
|
2020-01-01 14:20:01 +08:00
|
|
|
# Copyright 2017-2020 Free Software Foundation, Inc.
|
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:
2017-10-04 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:
2017-10-04 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:
2017-10-04 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:
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* gdb.base/set-cwd.c: New file.
* gdb.base/set-cwd.exp: Likewise.
2017-09-11 13:13:50 +08:00
|
|
|
|
|
|
|
# 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/>.
|
|
|
|
|
Extend "set cwd" to work on gdbserver
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:
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.
gdb/gdbserver/ChangeLog:
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.
gdb/testsuite/ChangeLog:
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* gdb.base/set-cwd.exp: Make it available on
native-extended-gdbserver.
gdb/doc/ChangeLog:
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-09-21 07:15:40 +08:00
|
|
|
if { [use_gdb_stub] } {
|
|
|
|
untested "skipping tests due to use_gdb_stub"
|
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:
2017-10-04 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:
2017-10-04 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:
2017-10-04 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:
2017-10-04 Sergio Durigan Junior <sergiodj@redhat.com>
* gdb.base/set-cwd.c: New file.
* gdb.base/set-cwd.exp: Likewise.
2017-09-11 13:13:50 +08:00
|
|
|
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
|