public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFC 0/3] [gdb/dap] Handle DAP command files
@ 2023-03-14 13:05 Tom de Vries
  2023-03-14 13:05 ` [RFC 1/3] [gdb/dap] Add logging of ignored lines Tom de Vries
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Tom de Vries @ 2023-03-14 13:05 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

After reporting a failure in test-case gdb.dap/bt-nodebug.exp, I tried to
reproduce the failure in the usual way, using "-q -batch -x gdb.in":
...
$ gdb -q -batch -iex "set debug dap-log-file dap.log" -i dap -x gdb.in
...
but that didn't work.  It seems that the interpreter reading in gdb.in doesn't
use DAP despite the "-i dap".  I also tried modifying gdb.in to use
interpreter-exec dap, but that didn't work for me, maybe it's possible though,
I don't know.

Then I tried:
...
$ gdb -q -iex "set debug dap-log-file dap.log" -i dap < gdb.in
...
which sort of works, but didn't reproduce the failure due to not waiting for
events, something that is dealt with in the test-case using
dap_wait_for_event_and_check.

So, I've added processing of an input line "WAIT_FOR_EVENTS: <n>" to fix that
problem (patch 3).

With editing gdb.in came the need to make it a bit more readable, so I made
it possible to start Content-Length at a new line (patch 2).

Also I've added a patch to log ignored input, which helps to debug parsing
issues (patch 1).

Using this patch series, and the following gdb.in, I managed to reproduce the
problem:
...
Content-Length: 54
WAIT_FOR_EVENTS: 1
{"seq": 1, "type": "request", "command": "initialize"}
Content-Length: 163
WAIT_FOR_EVENTS: 0
{"seq": 2, "type": "request", "command": "launch", "arguments": {"program": "bt-nodebug"}}
Content-Length: 136
WAIT_FOR_EVENTS: 2
{"seq": 3, "type": "request", "command": "setFunctionBreakpoints", "arguments": {"breakpoints": [{"name": "function_breakpoint_here"}]}}
Content-Length: 61
WAIT_FOR_EVENTS: 1
{"seq": 4, "type": "request", "command": "configurationDone"}
Content-Length: 84

{"seq": 5, "type": "request", "command": "stackTrace", "arguments": {"threadId": 1}}
Content-Length: 54

{"seq": 6, "type": "request", "command": "disconnect"}
...

Sofar, this hasn't actually helped me to investigate, when doing:
...
$ gdb --args gdb -q -iex "set debug dap-log-file dap.log" -i dap
...
followed by:
...
(gdb) run < gdb.in
...
I end up with:
...
(gdb) Undefined command: "Content-Length".  Try "help".
...
which AFAICT means that the input from gdb.in does end up in the inner gdb, but
is not parsed as DAP.

Tom de Vries (3):
  [gdb/dap] Add logging of ignored lines
  [gdb/dap] Allow Content-Length on separate line
  [gdb/dap] Allow WAIT_FOR_EVENTS input

 gdb/python/lib/gdb/dap/io.py     | 17 ++++++++++++++---
 gdb/python/lib/gdb/dap/server.py | 12 +++++++++++-
 2 files changed, 25 insertions(+), 4 deletions(-)


base-commit: c8b3d02c49943d1fef2cc060dd7115a5ae5f7afe
-- 
2.35.3


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC 1/3] [gdb/dap] Add logging of ignored lines
  2023-03-14 13:05 [RFC 0/3] [gdb/dap] Handle DAP command files Tom de Vries
@ 2023-03-14 13:05 ` Tom de Vries
  2023-03-14 14:12   ` Tom Tromey
  2023-03-14 13:05 ` [RFC 2/3] [gdb/dap] Allow Content-Length on separate line Tom de Vries
  2023-03-14 13:05 ` [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input Tom de Vries
  2 siblings, 1 reply; 13+ messages in thread
From: Tom de Vries @ 2023-03-14 13:05 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This input sequence is accepted by DAP:
...
{"seq": 4, "type": "request", "command": "configurationDone"}Content-Length: 84
...

This input sequence has the same effect:
...
{"seq": 4, "type": "request", "command": "configurationDone"}ignorethis
Content-Length: 84
...
but the 'ignorethis' part is silently ignored.

Log the ignored bit, such that we have:
...
READ: <<<{"seq": 4, "type": "request", "command": "configurationDone"}>>>
WROTE: <<<{"request_seq": 4, "type": "response", "command": "configurationDone"
, "success": true}>>>
+++ run
IGNORED: <<<b'ignorethis'>>>
...
---
 gdb/python/lib/gdb/dap/io.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/gdb/python/lib/gdb/dap/io.py b/gdb/python/lib/gdb/dap/io.py
index 74cc82301d7..28f4d93ba46 100644
--- a/gdb/python/lib/gdb/dap/io.py
+++ b/gdb/python/lib/gdb/dap/io.py
@@ -14,8 +14,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import json
+import sys
 
-from .startup import start_thread, send_gdb
+from .startup import start_thread, send_gdb, log
 
 
 def read_json(stream):
@@ -31,6 +32,8 @@ def read_json(stream):
         if line.startswith(b"Content-Length:"):
             line = line[15:].strip()
             content_length = int(line)
+            continue
+        log("IGNORED: <<<%s>>>" % line)
     data = bytes()
     while len(data) < content_length:
         new_data = stream.read(content_length - len(data))
-- 
2.35.3


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC 2/3] [gdb/dap] Allow Content-Length on separate line
  2023-03-14 13:05 [RFC 0/3] [gdb/dap] Handle DAP command files Tom de Vries
  2023-03-14 13:05 ` [RFC 1/3] [gdb/dap] Add logging of ignored lines Tom de Vries
@ 2023-03-14 13:05 ` Tom de Vries
  2023-03-14 14:13   ` Tom Tromey
  2023-03-14 13:05 ` [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input Tom de Vries
  2 siblings, 1 reply; 13+ messages in thread
From: Tom de Vries @ 2023-03-14 13:05 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

Currently this DAP input is accepted:
...
Content-Length: 54

{"seq": 1, ...}Content-Length: 163

{"seq": 2, ...}Content-Length: 136
...

Also allow:
...
Content-Length: 54

{"seq": 1, ...}
Content-Length: 163

{"seq": 2, ...}
Content-Length: 136
...
which makes command files a bit easier to read.
---
 gdb/python/lib/gdb/dap/io.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/gdb/python/lib/gdb/dap/io.py b/gdb/python/lib/gdb/dap/io.py
index 28f4d93ba46..fd9953a7aaa 100644
--- a/gdb/python/lib/gdb/dap/io.py
+++ b/gdb/python/lib/gdb/dap/io.py
@@ -28,7 +28,10 @@ def read_json(stream):
         line = stream.readline()
         line = line.strip()
         if line == b"":
-            break
+            if content_length != None:
+                break
+            else:
+                continue
         if line.startswith(b"Content-Length:"):
             line = line[15:].strip()
             content_length = int(line)
-- 
2.35.3


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input
  2023-03-14 13:05 [RFC 0/3] [gdb/dap] Handle DAP command files Tom de Vries
  2023-03-14 13:05 ` [RFC 1/3] [gdb/dap] Add logging of ignored lines Tom de Vries
  2023-03-14 13:05 ` [RFC 2/3] [gdb/dap] Allow Content-Length on separate line Tom de Vries
@ 2023-03-14 13:05 ` Tom de Vries
  2023-05-05 13:09   ` Tom Tromey
  2023-05-10 16:29   ` Tom Tromey
  2 siblings, 2 replies; 13+ messages in thread
From: Tom de Vries @ 2023-03-14 13:05 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

Modify the dap input format to allow a WAIT_FOR_EVENTS line:
...
Content-Length: 54
WAIT_FOR_EVENTS: 1
{"seq": 1, "type": "request", "command": "initialize"}
Content-Length: 163
...
that ensures that we wait for a specific amount of events before continuing
to process input.
---
 gdb/python/lib/gdb/dap/io.py     |  7 ++++++-
 gdb/python/lib/gdb/dap/server.py | 12 +++++++++++-
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/gdb/python/lib/gdb/dap/io.py b/gdb/python/lib/gdb/dap/io.py
index fd9953a7aaa..27d89e7a175 100644
--- a/gdb/python/lib/gdb/dap/io.py
+++ b/gdb/python/lib/gdb/dap/io.py
@@ -22,6 +22,7 @@ from .startup import start_thread, send_gdb, log
 def read_json(stream):
     """Read a JSON-RPC message from STREAM.
     The decoded object is returned."""
+    wait_for_events = 0
     # First read and parse the header.
     content_length = None
     while True:
@@ -36,13 +37,17 @@ def read_json(stream):
             line = line[15:].strip()
             content_length = int(line)
             continue
+        if line.startswith(b"WAIT_FOR_EVENTS:") and content_length != None:
+            line = line[16:].strip()
+            wait_for_events = int(line)
+            break
         log("IGNORED: <<<%s>>>" % line)
     data = bytes()
     while len(data) < content_length:
         new_data = stream.read(content_length - len(data))
         data += new_data
     result = json.loads(data)
-    return result
+    return (result, wait_for_events)
 
 
 def start_json_writer(stream, queue):
diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py
index 92b4eee1c5e..88b41684602 100644
--- a/gdb/python/lib/gdb/dap/server.py
+++ b/gdb/python/lib/gdb/dap/server.py
@@ -16,6 +16,7 @@
 import json
 import queue
 import sys
+import time
 
 from .io import start_json_writer, read_json
 from .startup import (
@@ -45,6 +46,7 @@ class Server:
         self.out_stream = out_stream
         self.child_stream = child_stream
         self.delayed_events = []
+        self.send_event_cnt = 0
         # This queue accepts JSON objects that are then sent to the
         # DAP client.  Writing is done in a separate thread to avoid
         # blocking the read loop.
@@ -110,7 +112,9 @@ class Server:
         start_thread("output reader", self._read_inferior_output)
         start_json_writer(self.out_stream, self.write_queue)
         while not self.done:
-            cmd = read_json(self.in_stream)
+            res = read_json(self.in_stream)
+            cmd = res[0]
+            wait_for_events = res[1]
             log("READ: <<<" + json.dumps(cmd) + ">>>")
             result = self._handle_command(cmd)
             self._send_json(result)
@@ -118,6 +122,11 @@ class Server:
             self.delayed_events = []
             for event, body in events:
                 self.send_event(event, body)
+            while True:
+                if wait_for_events <= self.send_event_cnt:
+                    self.send_event_cnt -= wait_for_events
+                    break
+                time.sleep(1)
         # Got the terminate request.  This is handled by the
         # JSON-writing thread, so that we can ensure that all
         # responses are flushed to the client before exiting.
@@ -143,6 +152,7 @@ class Server:
         if body is not None:
             obj["body"] = body
         self._send_json(obj)
+        self.send_event_cnt += 1
 
     def shutdown(self):
         """Request that the server shut down."""
-- 
2.35.3


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 1/3] [gdb/dap] Add logging of ignored lines
  2023-03-14 13:05 ` [RFC 1/3] [gdb/dap] Add logging of ignored lines Tom de Vries
@ 2023-03-14 14:12   ` Tom Tromey
  2023-03-24  8:10     ` Tom de Vries
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2023-03-14 14:12 UTC (permalink / raw)
  To: Tom de Vries via Gdb-patches; +Cc: Tom de Vries, Tom Tromey

>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:

Tom> This input sequence is accepted by DAP:
Tom> ...
Tom> {"seq": 4, "type": "request", "command": "configurationDone"}Content-Length: 84
Tom> ...

Tom> This input sequence has the same effect:
Tom> ...
Tom> {"seq": 4, "type": "request", "command": "configurationDone"}ignorethis
Tom> Content-Length: 84
Tom> ...
Tom> but the 'ignorethis' part is silently ignored.

This is ok.  Thank you.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 2/3] [gdb/dap] Allow Content-Length on separate line
  2023-03-14 13:05 ` [RFC 2/3] [gdb/dap] Allow Content-Length on separate line Tom de Vries
@ 2023-03-14 14:13   ` Tom Tromey
  2023-03-14 15:35     ` Tom de Vries
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2023-03-14 14:13 UTC (permalink / raw)
  To: Tom de Vries via Gdb-patches; +Cc: Tom de Vries, Tom Tromey

>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:

Tom> Also allow:
Tom> ...
Tom> Content-Length: 54

Tom> {"seq": 1, ...}
Tom> Content-Length: 163

Tom> {"seq": 2, ...}
Tom> Content-Length: 136
Tom> ...
Tom> which makes command files a bit easier to read.

Doesn't this violate the XML-RPC protocol?  The issue being that the
header is terminated by a blank line, but now this ignores the blank
line.  Though of course it's also bad to not have a Content-Length.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 2/3] [gdb/dap] Allow Content-Length on separate line
  2023-03-14 14:13   ` Tom Tromey
@ 2023-03-14 15:35     ` Tom de Vries
  2023-05-05 13:09       ` Tom Tromey
  0 siblings, 1 reply; 13+ messages in thread
From: Tom de Vries @ 2023-03-14 15:35 UTC (permalink / raw)
  To: Tom Tromey, Tom de Vries via Gdb-patches

On 3/14/23 15:13, Tom Tromey wrote:
>>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> Tom> Also allow:
> Tom> ...
> Tom> Content-Length: 54
> 
> Tom> {"seq": 1, ...}
> Tom> Content-Length: 163
> 
> Tom> {"seq": 2, ...}
> Tom> Content-Length: 136
> Tom> ...
> Tom> which makes command files a bit easier to read.
> 
> Doesn't this violate the XML-RPC protocol?  The issue being that the
> header is terminated by a blank line, but now this ignores the blank
> line.  Though of course it's also bad to not have a Content-Length.

OK, let's try the example from here ( 
https://microsoft.github.io/debug-adapter-protocol/overview ), two after 
each other, as confirming DAP:
...
Content-Length: 119\r\n
\r\n
{ "seq": <n>, ... }Content-Length: 119\r\n
\r\n
{ "seq": <n>, ... }
...

What I'm proposing with this patch allows in addition:
...
Content-Length: 119\r\n
\r\n
{ "seq": <n>, ... }\r\n
Content-Length: 119\r\n
\r\n
{ "seq": <n>, ... }
...

So the \r\n that terminates the header is still there.

And the blank line (^\r\n) that separates header and content is still there.

Whether this is still confirming DAP, I can't tell from the specification.

I can imagine that it makes sense for GDB to be as strict as possible to 
flush out problems in actual clients.

OTOH, the mock-up client we create by feeding a text file into gdb 
doesn't actually need to conform to DAP, and there's something to win by 
making this text file easy to read and edit, which is what the goal of 
this patch is.

So, perhaps we want to enable this selectively, say with a setting 
dap-parse-strict, and perhaps have some "set dap-cmd-input gdb.in" that 
automatically sets dap-parse-strict to 0.

Alternatively, we could move this into the command-sphere and do 
something like:
...
interpreter-exec dap-wrap { "seq": <n>, ... }
...
and let dap-wrap take care of adding a header with the correct size.

But this all might be overkill, I'm not sure.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 1/3] [gdb/dap] Add logging of ignored lines
  2023-03-14 14:12   ` Tom Tromey
@ 2023-03-24  8:10     ` Tom de Vries
  0 siblings, 0 replies; 13+ messages in thread
From: Tom de Vries @ 2023-03-24  8:10 UTC (permalink / raw)
  To: Tom Tromey, Tom de Vries via Gdb-patches

On 3/14/23 15:12, Tom Tromey wrote:
>>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> Tom> This input sequence is accepted by DAP:
> Tom> ...
> Tom> {"seq": 4, "type": "request", "command": "configurationDone"}Content-Length: 84
> Tom> ...
> 
> Tom> This input sequence has the same effect:
> Tom> ...
> Tom> {"seq": 4, "type": "request", "command": "configurationDone"}ignorethis
> Tom> Content-Length: 84
> Tom> ...
> Tom> but the 'ignorethis' part is silently ignored.
> 
> This is ok.  Thank you.

Thanks for the review.

Committed after dropping the superfluous "import sys".

Thanks,
- Tom


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 2/3] [gdb/dap] Allow Content-Length on separate line
  2023-03-14 15:35     ` Tom de Vries
@ 2023-05-05 13:09       ` Tom Tromey
  0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2023-05-05 13:09 UTC (permalink / raw)
  To: Tom de Vries via Gdb-patches; +Cc: Tom Tromey, Tom de Vries

>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:

Sorry about the delay in replying to this.

Tom> What I'm proposing with this patch allows in addition:
Tom> ...
Tom> Content-Length: 119\r\n
Tom> \r\n
Tom> { "seq": <n>, ... }\r\n
Tom> Content-Length: 119\r\n
Tom> \r\n
Tom> { "seq": <n>, ... }
Tom> ...

Tom> So the \r\n that terminates the header is still there.

Tom> And the blank line (^\r\n) that separates header and content is still there.

Tom> Whether this is still confirming DAP, I can't tell from the specification.

Yeah, the text says:

    Since both the last header field and the overall header itself are each
    terminated with \r\n, and since the header is mandatory, the content
    part of a message is always preceded (and uniquely identified) by two
    \r\n sequences.

which to me means that they didn't consider the possibility of a blank
line as the first line of the header part.  Oops.

Tom> So, perhaps we want to enable this selectively, say with a setting
Tom> dap-parse-strict, and perhaps have some "set dap-cmd-input gdb.in"
Tom> that automatically sets dap-parse-strict to 0.

I'd be fine with this.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input
  2023-03-14 13:05 ` [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input Tom de Vries
@ 2023-05-05 13:09   ` Tom Tromey
  2023-05-05 14:01     ` Tom de Vries
  2023-05-10 16:29   ` Tom Tromey
  1 sibling, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2023-05-05 13:09 UTC (permalink / raw)
  To: Tom de Vries via Gdb-patches; +Cc: Tom de Vries, Tom Tromey

>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:

Tom> Modify the dap input format to allow a WAIT_FOR_EVENTS line:
Tom> ...
Tom> Content-Length: 54
Tom> WAIT_FOR_EVENTS: 1
Tom> {"seq": 1, "type": "request", "command": "initialize"}
Tom> Content-Length: 163
Tom> ...
Tom> that ensures that we wait for a specific amount of events before continuing
Tom> to process input.

I don't understand the use for this.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input
  2023-05-05 13:09   ` Tom Tromey
@ 2023-05-05 14:01     ` Tom de Vries
  2023-05-10 16:23       ` Tom Tromey
  0 siblings, 1 reply; 13+ messages in thread
From: Tom de Vries @ 2023-05-05 14:01 UTC (permalink / raw)
  To: Tom Tromey, Tom de Vries via Gdb-patches

On 5/5/23 15:09, Tom Tromey wrote:
>>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> Tom> Modify the dap input format to allow a WAIT_FOR_EVENTS line:
> Tom> ...
> Tom> Content-Length: 54
> Tom> WAIT_FOR_EVENTS: 1
> Tom> {"seq": 1, "type": "request", "command": "initialize"}
> Tom> Content-Length: 163
> Tom> ...
> Tom> that ensures that we wait for a specific amount of events before continuing
> Tom> to process input.
> 
> I don't understand the use for this.

The idea is that I'm trying to reproduce gdb.dap test-cases outside the 
test-suite, and I need something to play the role of _dap_wait_for_event.

Otherwise, I sent requests before I have an acknowledgement that 
expected events due to previous requests have occurred.

More concretely, let's run gdb.dap/bt-nodebug.exp.

Now, we copy the gdb.in.1 to use as input:
...
$ cp leap-15-4/build/gdb/testsuite/outputs/gdb.dap/bt-nodebug/gdb.in.1 
gdb.in
...

Let's use it as described in the cover letter:
...
$ gdb -q -iex "set debug dap-log-file dap.log" -i dap < gdb.in
Content-Length: 473

{"request_seq": 1, "type": "response", "command": "initialize", "body": 
{"supportsTerminateRequest": true, "supportTerminateDebuggee": true, 
"supportsFunctionBreakpoints": true, "supportsInstructionBreakpoints": 
true, "supportsDelayedStackTraceLoading": true, 
"supportsDisassembleRequest": true, "supportsConfigurationDoneRequest": 
true, "supportsReadMemoryRequest": true, "supportsWriteMemoryRequest": 
true, "supportsSteppingGranularity": true}, "success": true, "seq": 
1}Content-Length: 51

{"type": "event", "event": "initialized", "seq": 2}Content-Length: 86

{"request_seq": 2, "type": "response", "command": "launch", "success": 
true, "seq": 3}Content-Length: 299

{"type": "event", "event": "breakpoint", "body": {"reason": "new", 
"breakpoint": {"id": 1, "verified": true, "source": {"name": 
"bt-main.c", "path": 
"/data/vries/gdb/binutils-gdb.git/gdb/testsuite/gdb.dap/bt-main.c", 
"sourceReference": 0}, "line": 23, "instructionReference": "0x4004ab"}}, 
"seq": 4}Content-Length: 337

{"request_seq": 3, "type": "response", "command": 
"setFunctionBreakpoints", "body": {"breakpoints": [{"id": 1, "verified": 
true, "source": {"name": "bt-main.c", "path": 
"/data/vries/gdb/binutils-gdb.git/gdb/testsuite/gdb.dap/bt-main.c", 
"sourceReference": 0}, "line": 23, "instructionReference": 
"0x4004ab"}]}, "success": true, "seq": 5}Content-Length: 97

{"request_seq": 4, "type": "response", "command": "configurationDone", 
"success": true, "seq": 6}Content-Length: 186

{"type": "event", "event": "output", "body": {"category": "stdout", 
"output": "Breakpoint 1 at 0x4004ab: file 
/data/vries/gdb/src/gdb/testsuite/gdb.dap/bt-main.c, line 23.\n"}, 
"seq": 7}Content-Length: 92

{"type": "event", "event": "thread", "body": {"reason": "started", 
"threadId": 1}, "seq": 8}Content-Length: 137

{"request_seq": 5, "type": "response", "command": "stackTrace", "body": 
{"stackFrames": [], "totalFrames": 0}, "success": true, "seq": 
9}Content-Length: 91

{"request_seq": 6, "type": "response", "command": "disconnect", 
"success": true, "seq": 10}$
...

As we can see the backtrace is empty.

After playing with this a few times, we get instead:
...
$ gdb -q -iex "set debug dap-log-file dap.log" -i dap < gdb.in
Content-Length: 473

{"request_seq": 1, "type": "response", "command": "initialize", "body": 
{"supportsTerminateRequest": true, "supportTerminateDebuggee": true, 
"supportsFunctionBreakpoints": true, "supportsInstructionBreakpoints": 
true, "supportsDelayedStackTraceLoading": true, 
"supportsDisassembleRequest": true, "supportsConfigurationDoneRequest": 
true, "supportsReadMemoryRequest": true, "supportsWriteMemoryRequest": 
true, "supportsSteppingGranularity": true}, "success": true, "seq": 
1}Content-Length: 51

{"type": "event", "event": "initialized", "seq": 2}Content-Length: 86

{"request_seq": 2, "type": "response", "command": "launch", "success": 
true, "seq": 3}Content-Length: 299

{"type": "event", "event": "breakpoint", "body": {"reason": "new", 
"breakpoint": {"id": 1, "verified": true, "source": {"name": 
"bt-main.c", "path": 
"/data/vries/gdb/binutils-gdb.git/gdb/testsuite/gdb.dap/bt-main.c", 
"sourceReference": 0}, "line": 23, "instructionReference": "0x4004ab"}}, 
"seq": 4}Content-Length: 186

{"type": "event", "event": "output", "body": {"category": "stdout", 
"output": "Breakpoint 1 at 0x4004ab: file 
/data/vries/gdb/src/gdb/testsuite/gdb.dap/bt-main.c, line 23.\n"}, 
"seq": 5}Content-Length: 337

{"request_seq": 3, "type": "response", "command": 
"setFunctionBreakpoints", "body": {"breakpoints": [{"id": 1, "verified": 
true, "source": {"name": "bt-main.c", "path": 
"/data/vries/gdb/binutils-gdb.git/gdb/testsuite/gdb.dap/bt-main.c", 
"sourceReference": 0}, "line": 23, "instructionReference": 
"0x4004ab"}]}, "success": true, "seq": 6}Content-Length: 97

{"request_seq": 4, "type": "response", "command": "configurationDone", 
"success": true, "seq": 7}Content-Length: 92

{"type": "event", "event": "thread", "body": {"reason": "started", 
"threadId": 1}, "seq": 8}Content-Length: 303

{"type": "event", "event": "breakpoint", "body": {"reason": "changed", 
"breakpoint": {"id": 1, "verified": true, "source": {"name": 
"bt-main.c", "path": 
"/data/vries/gdb/binutils-gdb.git/gdb/testsuite/gdb.dap/bt-main.c", 
"sourceReference": 0}, "line": 23, "instructionReference": "0x4004ab"}}, 
"seq": 9}Content-Length: 149

{"type": "event", "event": "stopped", "body": {"threadId": 1, 
"allThreadsStopped": true, "hitBreakpointIds": [1], "reason": 
"breakpoint"}, "seq": 10}Content-Length: 685

{"request_seq": 5, "type": "response", "command": "stackTrace", "body": 
{"stackFrames": [{"id": 0, "name": "function_breakpoint_here", "line": 
23, "column": 0, "instructionPointerReference": "0x4004ab", "source": 
{"name": "bt-main.c", "path": 
"/data/vries/gdb/src/gdb/testsuite/gdb.dap/bt-main.c", 
"sourceReference": 0}}, {"id": 1, "name": "no_debug_info", "line": 0, 
"column": 0, "instructionPointerReference": "0x4004c7"}, {"id": 2, 
"name": "main", "line": 27, "column": 0, "instructionPointerReference": 
"0x4004b7", "source": {"name": "bt-main.c", "path": 
"/data/vries/gdb/src/gdb/testsuite/gdb.dap/bt-main.c", 
"sourceReference": 0}}], "totalFrames": 3}, "success": true, "seq": 
11}Content-Length: 91

{"request_seq": 6, "type": "response", "command": "disconnect", 
"success": true, "seq": 12}$
...

As we can see the backtrace is now not empty.

The WAIT_FOR_EVENTS bit ensures that we get a non-empty backtrace each time.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input
  2023-05-05 14:01     ` Tom de Vries
@ 2023-05-10 16:23       ` Tom Tromey
  0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2023-05-10 16:23 UTC (permalink / raw)
  To: Tom de Vries via Gdb-patches; +Cc: Tom Tromey, Tom de Vries

>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:

>> I don't understand the use for this.

Tom> The idea is that I'm trying to reproduce gdb.dap test-cases outside
Tom> the test-suite, and I need something to play the role of
Tom> _dap_wait_for_event.

Tom> Otherwise, I sent requests before I have an acknowledgement that
Tom> expected events due to previous requests have occurred.

Ok, I understand now.

Tom> {"request_seq": 5, "type": "response", "command": "stackTrace",
Tom> "body": {"stackFrames": [], "totalFrames": 0}, "success": true, "seq":
Tom> 9}Content-Length: 91

...
Tom> As we can see the backtrace is empty.

I wonder if the implementation should reject certain requests when the
inferior (really the specified thread) is running.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input
  2023-03-14 13:05 ` [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input Tom de Vries
  2023-05-05 13:09   ` Tom Tromey
@ 2023-05-10 16:29   ` Tom Tromey
  1 sibling, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2023-05-10 16:29 UTC (permalink / raw)
  To: Tom de Vries via Gdb-patches; +Cc: Tom de Vries, Tom Tromey

>>>>> "Tom" == Tom de Vries via Gdb-patches <gdb-patches@sourceware.org> writes:

Tom> Modify the dap input format to allow a WAIT_FOR_EVENTS line:
Tom> ...
Tom> Content-Length: 54
Tom> WAIT_FOR_EVENTS: 1
Tom> {"seq": 1, "type": "request", "command": "initialize"}
Tom> Content-Length: 163

I think the commit message would benefit from an explanation of the
rationale.

Tom> +        if line.startswith(b"WAIT_FOR_EVENTS:") and content_length != None:
Tom> +            line = line[16:].strip()
Tom> +            wait_for_events = int(line)
Tom> +            break

A comment here explaining why gdb accepts this header and what it's
useful for would also be good.

Tom> +            while True:
Tom> +                if wait_for_events <= self.send_event_cnt:
Tom> +                    self.send_event_cnt -= wait_for_events
Tom> +                    break
Tom> +                time.sleep(1)

Can't this be

   while wait_for_events > self.send_event_cnt:
       time.sleep(1)

Instead of sleep it is probably more efficient to use a queue of some
kind and have the event-generation code write to it when the required
number of events have been sent.  Not sure if we really care in debug
mode though.

Tom

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2023-05-10 16:29 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-14 13:05 [RFC 0/3] [gdb/dap] Handle DAP command files Tom de Vries
2023-03-14 13:05 ` [RFC 1/3] [gdb/dap] Add logging of ignored lines Tom de Vries
2023-03-14 14:12   ` Tom Tromey
2023-03-24  8:10     ` Tom de Vries
2023-03-14 13:05 ` [RFC 2/3] [gdb/dap] Allow Content-Length on separate line Tom de Vries
2023-03-14 14:13   ` Tom Tromey
2023-03-14 15:35     ` Tom de Vries
2023-05-05 13:09       ` Tom Tromey
2023-03-14 13:05 ` [RFC 3/3] [gdb/dap] Allow WAIT_FOR_EVENTS input Tom de Vries
2023-05-05 13:09   ` Tom Tromey
2023-05-05 14:01     ` Tom de Vries
2023-05-10 16:23       ` Tom Tromey
2023-05-10 16:29   ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).