aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2024-11-20 13:04:27 -0700
committerTom Tromey <tromey@adacore.com>2024-12-09 13:52:54 -0700
commit6b9efd5c1a6ead15845ef5d40b0a4bdc2cb33480 (patch)
tree43e95e441528bc38736555ac8ba48901525dc6fe
parent4baa27895549f06dfad808d70ba0802877021c2b (diff)
downloadfsf-binutils-gdb-6b9efd5c1a6ead15845ef5d40b0a4bdc2cb33480.zip
fsf-binutils-gdb-6b9efd5c1a6ead15845ef5d40b0a4bdc2cb33480.tar.gz
fsf-binutils-gdb-6b9efd5c1a6ead15845ef5d40b0a4bdc2cb33480.tar.bz2
Defer DAP launch command until after configurationDone
PR dap/32090 points out that gdb's DAP "launch" sequencing is incorrect. The current approach (which is itself a 2nd implementation...) was based on a misreading of the spec. The spec has since been clarified here: https://github.com/microsoft/debug-adapter-protocol/issues/497 The clarification here is that a client is free to send the "launch" (or "attach") request at any point after the "initialized" event has been sent by gdb. However, the "launch" does not cause any action to be taken -- and does not send a response -- until after "configurationDone" has been seen. This patch implements this by arranging for the launch and attach commands to return a DeferredRequest object. All the tests needed updates. I've also added a new test that checks that the deferred "launch" request can be cancelled. (Note that the cancellation is lazy -- it also waits until configurationDone is seen. This could be fixed, but I was not sure whether it is important to do so.) Finally, the "launch" command has a somewhat funny sequencing now. Simply sending the command and waiting for a response yielded strange results if the inferior did not stop -- in this case, the repsonse was never sent. So now, the command is split into two parts, with some setup being done synchronously (for better error propagation) and the actual "run" being done async. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32090 Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
-rw-r--r--gdb/NEWS6
-rw-r--r--gdb/python/lib/gdb/dap/launch.py152
-rw-r--r--gdb/testsuite/gdb.dap/ada-arrays.exp7
-rw-r--r--gdb/testsuite/gdb.dap/ada-nested.exp7
-rw-r--r--gdb/testsuite/gdb.dap/ada-scopes.exp7
-rw-r--r--gdb/testsuite/gdb.dap/args-env.exp7
-rw-r--r--gdb/testsuite/gdb.dap/assign.exp7
-rw-r--r--gdb/testsuite/gdb.dap/attach.exp19
-rw-r--r--gdb/testsuite/gdb.dap/basic-dap.exp7
-rw-r--r--gdb/testsuite/gdb.dap/bt-nodebug.exp7
-rw-r--r--gdb/testsuite/gdb.dap/cancel-launch.exp60
-rw-r--r--gdb/testsuite/gdb.dap/catch-exception.exp7
-rw-r--r--gdb/testsuite/gdb.dap/children.exp7
-rw-r--r--gdb/testsuite/gdb.dap/cond-bp.exp7
-rw-r--r--gdb/testsuite/gdb.dap/cwd.exp10
-rw-r--r--gdb/testsuite/gdb.dap/cxx-exception.exp7
-rw-r--r--gdb/testsuite/gdb.dap/disassem.exp7
-rw-r--r--gdb/testsuite/gdb.dap/frameless.exp7
-rw-r--r--gdb/testsuite/gdb.dap/global.exp7
-rw-r--r--gdb/testsuite/gdb.dap/hover.exp7
-rw-r--r--gdb/testsuite/gdb.dap/insn-bp.exp12
-rw-r--r--gdb/testsuite/gdb.dap/lazy-string.exp7
-rw-r--r--gdb/testsuite/gdb.dap/log-message.exp7
-rw-r--r--gdb/testsuite/gdb.dap/memory.exp7
-rw-r--r--gdb/testsuite/gdb.dap/modules.exp7
-rw-r--r--gdb/testsuite/gdb.dap/pause.exp7
-rw-r--r--gdb/testsuite/gdb.dap/ptrref.exp7
-rw-r--r--gdb/testsuite/gdb.dap/remote-dap.exp10
-rw-r--r--gdb/testsuite/gdb.dap/rust-slices.exp7
-rw-r--r--gdb/testsuite/gdb.dap/scopes.exp7
-rw-r--r--gdb/testsuite/gdb.dap/sources.exp14
-rw-r--r--gdb/testsuite/gdb.dap/stack-format.exp7
-rw-r--r--gdb/testsuite/gdb.dap/step-out.exp7
-rw-r--r--gdb/testsuite/gdb.dap/stop-at-main.exp7
-rw-r--r--gdb/testsuite/gdb.dap/terminate.exp7
-rw-r--r--gdb/testsuite/lib/dap-support.exp33
36 files changed, 341 insertions, 164 deletions
diff --git a/gdb/NEWS b/gdb/NEWS
index 361d772..047f8ad 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -98,6 +98,12 @@
the return value from the latest "stepOut" command, when
appropriate.
+ ** The "launch" and "attach" requests were rewritten in accordance
+ with some clarifications to the spec. Now they can be sent at
+ any time after the "initialized" event, but will not take effect
+ (or send a response) until after the "configurationDone" request
+ has been sent.
+
* New commands
show jit-reader-directory
diff --git a/gdb/python/lib/gdb/dap/launch.py b/gdb/python/lib/gdb/dap/launch.py
index 6444c8b..fc1890c 100644
--- a/gdb/python/lib/gdb/dap/launch.py
+++ b/gdb/python/lib/gdb/dap/launch.py
@@ -21,8 +21,42 @@ from typing import Mapping, Optional, Sequence
import gdb
from .events import exec_and_expect_stop, expect_process, expect_stop
-from .server import capability, request
-from .startup import DAPException, exec_and_log, in_gdb_thread
+from .server import (
+ DeferredRequest,
+ call_function_later,
+ capability,
+ request,
+ send_gdb,
+ send_gdb_with_response,
+)
+from .startup import DAPException, exec_and_log, in_dap_thread, in_gdb_thread
+
+# A launch or attach promise that that will be fulfilled after a
+# configurationDone request has been processed.
+_launch_or_attach_promise = None
+
+
+# A DeferredRequest that handles either a "launch" or "attach"
+# request.
+class _LaunchOrAttachDeferredRequest(DeferredRequest):
+ def __init__(self, callback):
+ self._callback = callback
+ global _launch_or_attach_promise
+ if _launch_or_attach_promise is not None:
+ raise DAPException("launch or attach already specified")
+ _launch_or_attach_promise = self
+
+ # Invoke the callback and return the result.
+ @in_dap_thread
+ def invoke(self):
+ return self._callback()
+
+ # Override this so we can clear the global when rescheduling.
+ @in_dap_thread
+ def reschedule(self):
+ global _launch_or_attach_promise
+ _launch_or_attach_promise = None
+ super().reschedule()
# A wrapper for the 'file' command that correctly quotes its argument.
@@ -37,7 +71,7 @@ def file_command(program):
# Any parameters here are necessarily extensions -- DAP requires this
# from implementations. Any additions or changes here should be
# documented in the gdb manual.
-@request("launch", response=False)
+@request("launch", on_dap_thread=True)
def launch(
*,
program: Optional[str] = None,
@@ -48,27 +82,51 @@ def launch(
stopOnEntry: bool = False,
**extra,
):
- if cwd is not None:
- exec_and_log("cd " + cwd)
- if program is not None:
- file_command(program)
- inf = gdb.selected_inferior()
- inf.arguments = args
- if env is not None:
- inf.clear_env()
- for name, value in env.items():
- inf.set_env(name, value)
- expect_process("process")
- if stopAtBeginningOfMainSubprogram:
- cmd = "start"
- elif stopOnEntry:
- cmd = "starti"
- else:
- cmd = "run"
- exec_and_expect_stop(cmd)
-
-
-@request("attach")
+ # Launch setup is handled here. This is done synchronously so
+ # that errors can be reported in a natural way.
+ @in_gdb_thread
+ def _setup_launch():
+ if cwd is not None:
+ exec_and_log("cd " + cwd)
+ if program is not None:
+ file_command(program)
+ inf = gdb.selected_inferior()
+ inf.arguments = args
+ if env is not None:
+ inf.clear_env()
+ for name, value in env.items():
+ inf.set_env(name, value)
+
+ # Actual launching done here. See below for more info.
+ @in_gdb_thread
+ def _do_launch():
+ expect_process("process")
+ if stopAtBeginningOfMainSubprogram:
+ cmd = "start"
+ elif stopOnEntry:
+ cmd = "starti"
+ else:
+ cmd = "run"
+ exec_and_expect_stop(cmd)
+
+ @in_dap_thread
+ def _launch_impl():
+ send_gdb_with_response(_setup_launch)
+ # We do not wait for the result here. It might be a little
+ # nicer if we did -- perhaps the various thread events would
+ # occur in a more logical sequence -- but if the inferior does
+ # not stop, then the launch response will not be seen either,
+ # which seems worse.
+ send_gdb(_do_launch)
+ # Launch response does not have a body.
+ return None
+
+ # The launch itself is deferred until the configurationDone
+ # request.
+ return _LaunchOrAttachDeferredRequest(_launch_impl)
+
+
+@request("attach", on_dap_thread=True)
def attach(
*,
program: Optional[str] = None,
@@ -76,21 +134,39 @@ def attach(
target: Optional[str] = None,
**args,
):
- if program is not None:
- file_command(program)
- if pid is not None:
- cmd = "attach " + str(pid)
- elif target is not None:
- cmd = "target remote " + target
- else:
- raise DAPException("attach requires either 'pid' or 'target'")
- expect_process("attach")
- expect_stop("attach")
- exec_and_log(cmd)
+ # The actual attach is handled by this function.
+ @in_gdb_thread
+ def _do_attach():
+ if program is not None:
+ file_command(program)
+ if pid is not None:
+ cmd = "attach " + str(pid)
+ elif target is not None:
+ cmd = "target remote " + target
+ else:
+ raise DAPException("attach requires either 'pid' or 'target'")
+ expect_process("attach")
+ expect_stop("attach")
+ exec_and_log(cmd)
+ # Attach response does not have a body.
+ return None
+
+ @in_dap_thread
+ def _attach_impl():
+ return send_gdb_with_response(_do_attach)
+
+ # The attach itself is deferred until the configurationDone
+ # request.
+ return _LaunchOrAttachDeferredRequest(_attach_impl)
@capability("supportsConfigurationDoneRequest")
-@request("configurationDone")
+@request("configurationDone", on_dap_thread=True)
def config_done(**args):
- # Nothing to do.
- return None
+ # Handle the launch or attach.
+ global _launch_or_attach_promise
+ if _launch_or_attach_promise is None:
+ raise DAPException("launch or attach not specified")
+ # Resolve the launch or attach, but only after the
+ # configurationDone response has been sent.
+ call_function_later(_launch_or_attach_promise.reschedule)
diff --git a/gdb/testsuite/gdb.dap/ada-arrays.exp b/gdb/testsuite/gdb.dap/ada-arrays.exp
index 0de361f..64c6eb2 100644
--- a/gdb/testsuite/gdb.dap/ada-arrays.exp
+++ b/gdb/testsuite/gdb.dap/ada-arrays.exp
@@ -33,6 +33,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
# Stop in a C frame, but examine values in an Ada frame, to make sure
# cross-language scenarios work correctly.
set line [gdb_get_line_number "STOP" $testdir/cstuff.c]
@@ -44,9 +46,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/ada-nested.exp b/gdb/testsuite/gdb.dap/ada-nested.exp
index 3415da3..7f28d27 100644
--- a/gdb/testsuite/gdb.dap/ada-nested.exp
+++ b/gdb/testsuite/gdb.dap/ada-nested.exp
@@ -31,6 +31,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "STOP"]
set obj [dap_check_request_and_response "set breakpoint" \
setBreakpoints \
@@ -41,9 +43,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $binfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $fn_bpno
diff --git a/gdb/testsuite/gdb.dap/ada-scopes.exp b/gdb/testsuite/gdb.dap/ada-scopes.exp
index 4d895a5..ef1302e 100644
--- a/gdb/testsuite/gdb.dap/ada-scopes.exp
+++ b/gdb/testsuite/gdb.dap/ada-scopes.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "STOP"]
set obj [dap_check_request_and_response "set breakpoint" \
setBreakpoints \
@@ -39,9 +41,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $binfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $fn_bpno
diff --git a/gdb/testsuite/gdb.dap/args-env.exp b/gdb/testsuite/gdb.dap/args-env.exp
index d651173..5f02b00 100644
--- a/gdb/testsuite/gdb.dap/args-env.exp
+++ b/gdb/testsuite/gdb.dap/args-env.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile arguments {a "b c"} env {{DEI something}}]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -38,9 +40,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile arguments {a "b c"} env {{DEI something}}] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/assign.exp b/gdb/testsuite/gdb.dap/assign.exp
index 6703a97..6665b6a 100644
--- a/gdb/testsuite/gdb.dap/assign.exp
+++ b/gdb/testsuite/gdb.dap/assign.exp
@@ -36,6 +36,8 @@ save_vars GDBFLAGS {
}
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "STOP"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -45,9 +47,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $line_bpno
diff --git a/gdb/testsuite/gdb.dap/attach.exp b/gdb/testsuite/gdb.dap/attach.exp
index ce2a16c..e0cd57b 100644
--- a/gdb/testsuite/gdb.dap/attach.exp
+++ b/gdb/testsuite/gdb.dap/attach.exp
@@ -29,17 +29,14 @@ set test_spawn_id [spawn_wait_for_attach $binfile]
set testpid [spawn_id_get_pid $test_spawn_id]
# Test that attaching works at all.
-set result [dap_attach $testpid $binfile]
-
-set found 0
-foreach ev [lindex $result 1] {
- if {[dict get $ev type] == "event"
- && [dict get $ev event] == "stopped"
- && [dict get $ev body reason] == "attach"} {
- set found 1
- }
-}
-gdb_assert {$found} "saw stopped event for attach"
+set attach_id [dap_attach $testpid $binfile]
+
+dap_check_request_and_response "configurationDone" configurationDone
+
+dap_wait_for_event_and_check "stopped" stopped \
+ "body reason" attach
+
+dap_check_response "attach response" attach $attach_id
dap_shutdown true
diff --git a/gdb/testsuite/gdb.dap/basic-dap.exp b/gdb/testsuite/gdb.dap/basic-dap.exp
index 6ef9a5b..dd785ef 100644
--- a/gdb/testsuite/gdb.dap/basic-dap.exp
+++ b/gdb/testsuite/gdb.dap/basic-dap.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set breakpoint on two functions" \
setFunctionBreakpoints \
{o breakpoints [a [o name [s function_breakpoint_here]] \
@@ -86,9 +88,8 @@ gdb_assert {$new_line_bpno == $line_bpno} "re-setting kept same breakpoint numbe
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
# While waiting for the stopped event, we might receive breakpoint changed
diff --git a/gdb/testsuite/gdb.dap/bt-nodebug.exp b/gdb/testsuite/gdb.dap/bt-nodebug.exp
index 550b9c5..319dcf0 100644
--- a/gdb/testsuite/gdb.dap/bt-nodebug.exp
+++ b/gdb/testsuite/gdb.dap/bt-nodebug.exp
@@ -31,6 +31,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set breakpoint on inner" \
setFunctionBreakpoints \
{o breakpoints [a [o name [s function_breakpoint_here]]]}]
@@ -38,9 +40,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
lassign [dap_wait_for_event_and_check "stopped at function breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/cancel-launch.exp b/gdb/testsuite/gdb.dap/cancel-launch.exp
new file mode 100644
index 0000000..7ef18d1
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/cancel-launch.exp
@@ -0,0 +1,60 @@
+# Copyright 2024 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 cancellation of a "launch" command.
+
+require allow_dap_tests
+
+load_lib dap-support.exp
+
+# Anything will work, we aren't going to run it.
+standard_testfile sources.c
+
+if {[build_executable ${testfile}.exp $testfile $srcfile] == -1} {
+ return
+}
+
+if {[dap_initialize] == ""} {
+ return
+}
+
+set launch_id [dap_launch $testfile]
+
+# Set a breakpoint. This is done to ensure that the launch request is
+# definitely in the deferred state when we try to cancel it.
+set line [gdb_get_line_number "Distinguishing comment"]
+dap_check_request_and_response "set breakpoint by line number" \
+ setBreakpoints \
+ [format {o source [o path [%s]] breakpoints [a [o line [i %d]]]} \
+ [list s $srcfile] $line]
+
+set cancel_id [dap_send_request cancel \
+ [format {o requestId [i %d]} $launch_id]]
+
+dap_read_response cancel $cancel_id
+
+# The cancellation isn't actually processed until configurationDone is
+# sent. While this seems fine, it's unclear if gdb should be more
+# eager here and try to cancel a deferred task before it is
+# rescheduled.
+dap_check_request_and_response "configurationDone" configurationDone
+
+set resp [lindex [dap_read_response launch $launch_id] 0]
+gdb_assert {[dict get $resp success] == "false"} \
+ "launch failed"
+gdb_assert {[dict get $resp message] == "cancelled"} \
+ "launch cancelled"
+
+dap_shutdown
diff --git a/gdb/testsuite/gdb.dap/catch-exception.exp b/gdb/testsuite/gdb.dap/catch-exception.exp
index a1ced06..9793746 100644
--- a/gdb/testsuite/gdb.dap/catch-exception.exp
+++ b/gdb/testsuite/gdb.dap/catch-exception.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set exception catchpoints" \
setExceptionBreakpoints \
{o filters [a [s nosuchfilter] [s assert]] \
@@ -69,9 +71,8 @@ foreach spec $bps {
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $binfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at first raise" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" 2
diff --git a/gdb/testsuite/gdb.dap/children.exp b/gdb/testsuite/gdb.dap/children.exp
index f5dfe2c..783fff9 100644
--- a/gdb/testsuite/gdb.dap/children.exp
+++ b/gdb/testsuite/gdb.dap/children.exp
@@ -36,6 +36,8 @@ save_vars GDBFLAGS {
}
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "STOP"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -45,9 +47,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $line_bpno
diff --git a/gdb/testsuite/gdb.dap/cond-bp.exp b/gdb/testsuite/gdb.dap/cond-bp.exp
index 2bd52ba..28d4b8e 100644
--- a/gdb/testsuite/gdb.dap/cond-bp.exp
+++ b/gdb/testsuite/gdb.dap/cond-bp.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "STOP"]
# Test some breakpoint-setting failure modes.
@@ -65,9 +67,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at function breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $fn_bpno
diff --git a/gdb/testsuite/gdb.dap/cwd.exp b/gdb/testsuite/gdb.dap/cwd.exp
index 6b88299..b3c9f9c 100644
--- a/gdb/testsuite/gdb.dap/cwd.exp
+++ b/gdb/testsuite/gdb.dap/cwd.exp
@@ -29,14 +29,14 @@ if {[dap_initialize] == ""} {
return
}
-dap_check_request_and_response "configurationDone" configurationDone
-
# 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
-}
+set launch_id [dap_launch $the_file cwd $the_dir stop_at_main 1]
+
+dap_check_request_and_response "configurationDone" configurationDone
+
+dap_check_response "launch response" launch $launch_id
# 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 \
diff --git a/gdb/testsuite/gdb.dap/cxx-exception.exp b/gdb/testsuite/gdb.dap/cxx-exception.exp
index 1332043..c79c5db 100644
--- a/gdb/testsuite/gdb.dap/cxx-exception.exp
+++ b/gdb/testsuite/gdb.dap/cxx-exception.exp
@@ -28,6 +28,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set exception catchpoints" \
setExceptionBreakpoints \
{o filters [a [s throw] [s rethrow] [s catch]]}]
@@ -49,9 +51,8 @@ foreach bp $bps {
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at throw" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" 1
diff --git a/gdb/testsuite/gdb.dap/disassem.exp b/gdb/testsuite/gdb.dap/disassem.exp
index 87fb516..6fdfc63 100644
--- a/gdb/testsuite/gdb.dap/disassem.exp
+++ b/gdb/testsuite/gdb.dap/disassem.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set breakpoint" \
setFunctionBreakpoints \
{o breakpoints [a [o name [s main]]]}]
@@ -36,9 +38,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/frameless.exp b/gdb/testsuite/gdb.dap/frameless.exp
index 63ee521..6963eed 100644
--- a/gdb/testsuite/gdb.dap/frameless.exp
+++ b/gdb/testsuite/gdb.dap/frameless.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -38,9 +40,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
"body reason" breakpoint \
diff --git a/gdb/testsuite/gdb.dap/global.exp b/gdb/testsuite/gdb.dap/global.exp
index 79f7f2f..2704f46 100644
--- a/gdb/testsuite/gdb.dap/global.exp
+++ b/gdb/testsuite/gdb.dap/global.exp
@@ -27,6 +27,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -36,9 +38,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/hover.exp b/gdb/testsuite/gdb.dap/hover.exp
index 0c80650..f637c4a 100644
--- a/gdb/testsuite/gdb.dap/hover.exp
+++ b/gdb/testsuite/gdb.dap/hover.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -38,9 +40,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/insn-bp.exp b/gdb/testsuite/gdb.dap/insn-bp.exp
index 4a4c144..6542262 100644
--- a/gdb/testsuite/gdb.dap/insn-bp.exp
+++ b/gdb/testsuite/gdb.dap/insn-bp.exp
@@ -39,6 +39,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set breakpoint on main" \
setFunctionBreakpoints \
{o breakpoints [a [o name [s main]]]}]
@@ -56,14 +58,12 @@ gdb_assert {[dict get $bp verified] == "false"} \
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
-
# The event we're looking for should occur during startup, but we want
# to leave open the possibility that it occurs when waiting for the
-# stopped event. So, keep both event lists around and search them
+# stopped event. So, keep all event lists around and search them
# once below.
+lassign [dap_check_response "launch response" launch $launch_id] \
+ unused objs0
lassign [dap_wait_for_event_and_check "inferior started" \
thread "body reason" started] \
unused objs1
@@ -72,7 +72,7 @@ lassign [dap_wait_for_event_and_check "stopped at breakpoint" stopped \
"body hitBreakpointIds" $fn_bpno] unused objs2
set found_bp_event 0
-foreach obj [concat $objs1 $objs2] {
+foreach obj [concat $objs0 $objs1 $objs2] {
if { [dict get $obj "type"] != "event" } {
continue
}
diff --git a/gdb/testsuite/gdb.dap/lazy-string.exp b/gdb/testsuite/gdb.dap/lazy-string.exp
index 5442220..d070347 100644
--- a/gdb/testsuite/gdb.dap/lazy-string.exp
+++ b/gdb/testsuite/gdb.dap/lazy-string.exp
@@ -36,6 +36,8 @@ save_vars GDBFLAGS {
}
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "STOP"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -45,9 +47,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $line_bpno
diff --git a/gdb/testsuite/gdb.dap/log-message.exp b/gdb/testsuite/gdb.dap/log-message.exp
index e966b96..a0070af 100644
--- a/gdb/testsuite/gdb.dap/log-message.exp
+++ b/gdb/testsuite/gdb.dap/log-message.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "HERE"]
set obj [dap_check_request_and_response "set breakpoint" \
setBreakpoints \
@@ -40,9 +42,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "logging output" output \
diff --git a/gdb/testsuite/gdb.dap/memory.exp b/gdb/testsuite/gdb.dap/memory.exp
index c4e4fb3..89ae8bb 100644
--- a/gdb/testsuite/gdb.dap/memory.exp
+++ b/gdb/testsuite/gdb.dap/memory.exp
@@ -37,6 +37,8 @@ save_vars { env(ASAN_OPTIONS) env(TSAN_OPTIONS) } {
}
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -46,9 +48,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/modules.exp b/gdb/testsuite/gdb.dap/modules.exp
index 87cebda..2e41679 100644
--- a/gdb/testsuite/gdb.dap/modules.exp
+++ b/gdb/testsuite/gdb.dap/modules.exp
@@ -42,6 +42,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set breakpoint on stop function" \
setFunctionBreakpoints \
{o breakpoints [a [o name [s stop]]]}]
@@ -49,9 +51,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at function breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $fn_bpno
diff --git a/gdb/testsuite/gdb.dap/pause.exp b/gdb/testsuite/gdb.dap/pause.exp
index 9038d0f..c74fea3 100644
--- a/gdb/testsuite/gdb.dap/pause.exp
+++ b/gdb/testsuite/gdb.dap/pause.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
# Set a conditional breakpoint that will never fire. This is done to
# test the state-tracking in events -- an inferior call from a
# breakpoint condition should not cause any sort of stop or continue
@@ -43,9 +45,8 @@ dap_check_request_and_response "set conditional breakpoint" \
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "process event generated" process \
"body startMethod" process
dap_wait_for_event_and_check "inferior started" thread "body reason" started
diff --git a/gdb/testsuite/gdb.dap/ptrref.exp b/gdb/testsuite/gdb.dap/ptrref.exp
index 236ffae..2a972ac 100644
--- a/gdb/testsuite/gdb.dap/ptrref.exp
+++ b/gdb/testsuite/gdb.dap/ptrref.exp
@@ -27,6 +27,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -36,9 +38,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/remote-dap.exp b/gdb/testsuite/gdb.dap/remote-dap.exp
index 5c28a04..bca66dd 100644
--- a/gdb/testsuite/gdb.dap/remote-dap.exp
+++ b/gdb/testsuite/gdb.dap/remote-dap.exp
@@ -42,8 +42,12 @@ lassign [gdbserver_start "" $target_exec] protocol port
gdb_assert {$protocol == "remote"}
# We just want to test that attaching works at all.
-if {[dap_target_remote $port] != ""} {
- dap_shutdown true
-}
+set attach_id [dap_target_remote $port]
+
+dap_check_request_and_response "configurationDone" configurationDone
+
+dap_check_response "attach response" attach $attach_id
+
+dap_shutdown true
close_gdbserver
diff --git a/gdb/testsuite/gdb.dap/rust-slices.exp b/gdb/testsuite/gdb.dap/rust-slices.exp
index 4af8c11..1ed640a 100644
--- a/gdb/testsuite/gdb.dap/rust-slices.exp
+++ b/gdb/testsuite/gdb.dap/rust-slices.exp
@@ -32,6 +32,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "STOP"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -41,9 +43,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/scopes.exp b/gdb/testsuite/gdb.dap/scopes.exp
index aa3bb68..a8a0c01 100644
--- a/gdb/testsuite/gdb.dap/scopes.exp
+++ b/gdb/testsuite/gdb.dap/scopes.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -38,9 +40,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/sources.exp b/gdb/testsuite/gdb.dap/sources.exp
index ee853cc..305a27c 100644
--- a/gdb/testsuite/gdb.dap/sources.exp
+++ b/gdb/testsuite/gdb.dap/sources.exp
@@ -29,14 +29,16 @@ if {[dap_initialize] == ""} {
return
}
-if {[dap_launch $testfile stop_at_main 1] == ""} {
- return
-}
+set launch_id [dap_launch $testfile stop_at_main 1]
-proc do_tests {} {
- dap_wait_for_event_and_check "stopped at function breakpoint" stopped \
- "body reason" breakpoint
+dap_check_request_and_response "configurationDone" configurationDone
+dap_check_response "launch response" launch $launch_id
+
+dap_wait_for_event_and_check "stopped at function breakpoint" stopped \
+ "body reason" breakpoint
+
+proc do_tests {} {
set obj [dap_check_request_and_response loadedSources loadedSources]
if { $obj == "" } {
return
diff --git a/gdb/testsuite/gdb.dap/stack-format.exp b/gdb/testsuite/gdb.dap/stack-format.exp
index b81183a..4056e1f 100644
--- a/gdb/testsuite/gdb.dap/stack-format.exp
+++ b/gdb/testsuite/gdb.dap/stack-format.exp
@@ -36,6 +36,8 @@ save_vars GDBFLAGS {
}
}
+set launch_id [dap_launch $testfile]
+
set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
setBreakpoints \
@@ -45,9 +47,8 @@ set line_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
"body reason" breakpoint \
"body hitBreakpointIds" $line_bpno
diff --git a/gdb/testsuite/gdb.dap/step-out.exp b/gdb/testsuite/gdb.dap/step-out.exp
index 193264f..cfe730e 100644
--- a/gdb/testsuite/gdb.dap/step-out.exp
+++ b/gdb/testsuite/gdb.dap/step-out.exp
@@ -29,6 +29,8 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
set obj [dap_check_request_and_response "set breakpoint on function" \
setFunctionBreakpoints \
{o breakpoints [a [o name [s function_breakpoint_here]]]}]
@@ -36,9 +38,8 @@ set fn_bpno [dap_get_breakpoint_number $obj]
dap_check_request_and_response "configurationDone" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "stopped at function breakpoint" stopped \
diff --git a/gdb/testsuite/gdb.dap/stop-at-main.exp b/gdb/testsuite/gdb.dap/stop-at-main.exp
index 4c3e57a..52b94f4 100644
--- a/gdb/testsuite/gdb.dap/stop-at-main.exp
+++ b/gdb/testsuite/gdb.dap/stop-at-main.exp
@@ -29,11 +29,12 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile stop_at_main 1]
+
dap_check_request_and_response "start inferior" configurationDone
-if {[dap_launch $testfile stop_at_main 1] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
# 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
diff --git a/gdb/testsuite/gdb.dap/terminate.exp b/gdb/testsuite/gdb.dap/terminate.exp
index 90d0194..9872351 100644
--- a/gdb/testsuite/gdb.dap/terminate.exp
+++ b/gdb/testsuite/gdb.dap/terminate.exp
@@ -31,11 +31,12 @@ if {[dap_initialize] == ""} {
return
}
+set launch_id [dap_launch $testfile]
+
dap_check_request_and_response "start inferior" configurationDone
-if {[dap_launch $testfile] == ""} {
- return
-}
+dap_check_response "launch response" launch $launch_id
+
dap_wait_for_event_and_check "inferior started" thread "body reason" started
dap_wait_for_event_and_check "terminated event" terminated
diff --git a/gdb/testsuite/lib/dap-support.exp b/gdb/testsuite/lib/dap-support.exp
index 61355b5..0e481ac 100644
--- a/gdb/testsuite/lib/dap-support.exp
+++ b/gdb/testsuite/lib/dap-support.exp
@@ -248,10 +248,10 @@ proc dap_request_and_response {command {obj {}}} {
return [dap_read_response $command $seq]
}
-# Like dap_request_and_response, but also checks that the response
-# indicates success. NAME is used to issue a test result.
-proc dap_check_request_and_response {name command {obj {}}} {
- set response_and_events [dap_request_and_response $command $obj]
+# Wait for a response to the given request, and issue a pass/fail.
+# Returns the response and events like dap_request_and_response.
+proc dap_check_response {name cmd request} {
+ set response_and_events [dap_read_response $cmd $request]
set response [lindex $response_and_events 0]
if {[dict get $response success] != "true"} {
verbose "request failure: $response"
@@ -262,6 +262,13 @@ proc dap_check_request_and_response {name command {obj {}}} {
return $response_and_events
}
+# Like dap_request_and_response, but also checks that the response
+# indicates success. NAME is used to issue a test result.
+proc dap_check_request_and_response {name command {obj {}}} {
+ set seq [dap_send_request $command $obj]
+ return [dap_check_response $name $command $seq]
+}
+
# Start gdb, send a DAP initialization request and return the
# response. This approach lets the caller check the feature list, if
# desired. Returns the empty string on failure. NAME is used as the
@@ -278,10 +285,9 @@ proc dap_initialize {{name "initialize"}} {
}
# Send a launch request specifying FILE as the program to use for the
-# inferior. Returns the empty string on failure, or the response
-# object from the launch request. If specified, ARGS is a dictionary
-# of key-value pairs, each passed to the launch request. Valid keys
-# are:
+# inferior. Returns the request ID. If specified, ARGS is a
+# dictionary of key-value pairs, each passed to the launch request.
+# Valid keys are:
#
# * arguments - value is a list of strings passed as command-line
# arguments to the inferior
@@ -334,12 +340,12 @@ proc dap_launch {file {args {}}} {
}
}
- return [dap_check_request_and_response "startup - launch" launch $params]
+ return [dap_send_request launch $params]
}
# Start gdb, send a DAP initialize request, and then an attach request
# specifying PID as the inferior process ID. Returns the empty string
-# on failure, or the response object from the attach request.
+# on failure, or the attach request sequence ID.
proc dap_attach {pid {prog ""}} {
if {[dap_initialize "startup - initialize"] == ""} {
return ""
@@ -350,18 +356,17 @@ proc dap_attach {pid {prog ""}} {
append args [format { program [s %s]} $prog]
}
- return [dap_check_request_and_response "startup - attach" attach $args]
+ return [dap_send_request attach $args]
}
# Start gdb, send a DAP initialize request, and then an attach request
# specifying TARGET as the remote target. Returns the empty string on
-# failure, or the response object from the attach request.
+# failure, or the attach request sequence ID.
proc dap_target_remote {target} {
if {[dap_initialize "startup - initialize"] == ""} {
return ""
}
- return [dap_check_request_and_response "startup - target" attach \
- [format {o target [s %s]} $target]]
+ return [dap_send_request attach [format {o target [s %s]} $target]]
}
# Read the most recent DAP log file and check it for exceptions.