[3/6] Add "cwd" parameter to DAP launch request

Message ID 20230725-dap-bt-path-v1-3-bb015b0d8e54@adacore.com
State New
Headers
Series Several DAP fixes for VSCode |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Tom Tromey July 25, 2023, 1:49 p.m. UTC
  This adds the "cwd" parameter to the DAP launch request.

This came up here:
    https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/90
... and seemed like a good idea.
---
 gdb/doc/gdb.texinfo               |  8 ++++++++
 gdb/python/lib/gdb/dap/launch.py  | 34 ++++++++++++++++-----------------
 gdb/testsuite/gdb.dap/cwd.exp     | 40 +++++++++++++++++++++++++++++++++++++++
 gdb/testsuite/lib/dap-support.exp |  5 +++++
 4 files changed, 70 insertions(+), 17 deletions(-)
  

Comments

Eli Zaretskii July 25, 2023, 2:07 p.m. UTC | #1
> Date: Tue, 25 Jul 2023 07:49:40 -0600
> From: Tom Tromey via Gdb-patches <gdb-patches@sourceware.org>
> 
> This adds the "cwd" parameter to the DAP launch request.
> 
> This came up here:
>     https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/90
> ... and seemed like a good idea.
> ---
>  gdb/doc/gdb.texinfo               |  8 ++++++++
>  gdb/python/lib/gdb/dap/launch.py  | 34 ++++++++++++++++-----------------
>  gdb/testsuite/gdb.dap/cwd.exp     | 40 +++++++++++++++++++++++++++++++++++++++
>  gdb/testsuite/lib/dap-support.exp |  5 +++++
>  4 files changed, 70 insertions(+), 17 deletions(-)

OK for the documentation part, thanks.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
  

Patch

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 1463f501768..bd11f0a4475 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -39069,6 +39069,14 @@  If provided, this should be an array of strings.  These strings are
 provided as command-line arguments to the inferior, as if by
 @code{set args}.  @xref{Arguments}.
 
+@item cwd
+If provided, this should be a string.  @value{GDBN} will change its
+working directory to this directory, as if by the @code{cd} command
+(@pxref{Working Directory}).  The launched program will inherit this
+as its working directory.  Note that change of directory happens
+before the @code{program} parameter is processed.  This will affect
+the result if @code{program} is a relative filename.
+
 @item env
 If provided, this should be an object.  Each key of the object will be
 used as the name of an environment variable; each value must be a
diff --git a/gdb/python/lib/gdb/dap/launch.py b/gdb/python/lib/gdb/dap/launch.py
index c3c09bc3dd0..d13037fa476 100644
--- a/gdb/python/lib/gdb/dap/launch.py
+++ b/gdb/python/lib/gdb/dap/launch.py
@@ -23,12 +23,22 @@  from .server import request, capability
 from .startup import send_gdb, send_gdb_with_response, in_gdb_thread, exec_and_log
 
 
+# The program being launched, or None.  This should only be access
+# from the DAP thread.
 _program = None
 
 
 @in_gdb_thread
-def _set_args_env(args, env):
+def _launch_setup(program, cwd, args, env, stopAtBeginningOfMainSubprogram):
+    if cwd is not None:
+        exec_and_log("cd " + cwd)
+    if program is not None:
+        exec_and_log("file " + program)
     inf = gdb.selected_inferior()
+    if stopAtBeginningOfMainSubprogram:
+        main = inf.main_name
+        if main is not None:
+            exec_and_log("tbreak " + main)
     inf.arguments = args
     if env is not None:
         inf.clear_env()
@@ -36,14 +46,6 @@  def _set_args_env(args, env):
             inf.set_env(name, value)
 
 
-@in_gdb_thread
-def _break_at_main():
-    inf = gdb.selected_inferior()
-    main = inf.main_name
-    if main is not None:
-        exec_and_log("tbreak " + main)
-
-
 # Any parameters here are necessarily extensions -- DAP requires this
 # from implementations.  Any additions or changes here should be
 # documented in the gdb manual.
@@ -51,19 +53,17 @@  def _break_at_main():
 def launch(
     *,
     program: Optional[str] = None,
+    cwd: Optional[str] = None,
     args: Sequence[str] = (),
     env: Optional[Mapping[str, str]] = None,
     stopAtBeginningOfMainSubprogram: bool = False,
     **extra,
 ):
-    if program is not None:
-        global _program
-        _program = program
-        send_gdb("file " + _program)
-    if stopAtBeginningOfMainSubprogram:
-        send_gdb(_break_at_main)
-    if len(args) > 0 or env is not None:
-        send_gdb(lambda: _set_args_env(args, env))
+    global _program
+    _program = program
+    send_gdb(
+        lambda: _launch_setup(program, cwd, args, env, stopAtBeginningOfMainSubprogram)
+    )
 
 
 @request("attach")
diff --git a/gdb/testsuite/gdb.dap/cwd.exp b/gdb/testsuite/gdb.dap/cwd.exp
new file mode 100644
index 00000000000..394fe5ada83
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/cwd.exp
@@ -0,0 +1,40 @@ 
+# Copyright 2023 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/>.
+
+# Test the cwd extension.
+
+require allow_dap_tests {!is_remote host}
+
+load_lib dap-support.exp
+
+standard_testfile attach.c
+
+if {[build_executable ${testfile}.exp $testfile $srcfile] == -1} {
+    return
+}
+
+# Starting the inferior will fail if the change of cwd does not work.
+set the_dir [file dirname $testfile]
+set the_file [file tail $testfile]
+if {[dap_launch $the_file cwd $the_dir stop_at_main 1] == ""} {
+    return
+}
+
+dap_check_request_and_response "start inferior" configurationDone
+# We didn't explicitly set a breakpoint, so if we hit one, it worked.
+dap_wait_for_event_and_check "stopped at function breakpoint" stopped \
+    "body reason" breakpoint
+
+dap_shutdown
diff --git a/gdb/testsuite/lib/dap-support.exp b/gdb/testsuite/lib/dap-support.exp
index 4a1a288e7ae..657ad7b29bc 100644
--- a/gdb/testsuite/lib/dap-support.exp
+++ b/gdb/testsuite/lib/dap-support.exp
@@ -248,6 +248,7 @@  proc _dap_initialize {name} {
 # * stop_at_main - value is ignored, the presence of this means that
 #   "stopAtBeginningOfMainSubprogram" will be passed to the launch
 #   request.
+# * cwd - value is the working directory to use.
 #
 # After this proc is called, gdb will be ready to accept breakpoint
 # requests.
@@ -284,6 +285,10 @@  proc dap_launch {file {args {}}} {
 		append params { stopAtBeginningOfMainSubprogram [l true]}
 	    }
 
+	    cwd {
+		append envlist " cwd [format {[%s]} [list s $value]]"
+	    }
+
 	    default {
 		error "unrecognized parameter $key"
 	    }