public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] gdb/DAP: Add customRequest
@ 2023-05-07  9:41 Simon Farre
  2023-05-07 10:45 ` Matt Rice
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Simon Farre @ 2023-05-07  9:41 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Farre

First, some preface; as a maintainer on one of the few implementations of a pure GDB-only
debug adapter extension for VSCode (technically, it's designed for GDB+RR)
called "Midas", there is one thing that is crucial for making
the DAP interpreter useful, or rather, to make it be able to fully
utilize all the different super powers that GDB has and that is custom requests.
Midas implements the DA by making GDB feign the DAP in python, but using
CLI and MI, by parsing MI and turning it into JSON. Not great,
but it was the only solution that existed at the time.

The Python interpreter, when in CLI-mode, currently provides something similar to custom requests,
with custom commands from the command line via the base class `gdb.Command`.
But with the current implementation of the DAP-interpreter, no class hierarchies are needed.

This patch introduces the customRequest, which allows for DA's (debug adapters)
that want to use the full extent of GDB's functionality by working a bit
like the extension of `gdb.Command`, But instead of deriving from a base class
and instantiating a command object the DA would source python code
that will be added to the custom requests handler of the DAP-interpreter, for example like:
`-iex "source foo.py"` or `-iex "source debug-adapter-std-lib.py"` or whatever she/he wants
to call it.

Here's an example of what `foo.py` might look like:

> import gdb
> import gdb.dap
> from gdb.dap import server # import logic, possibly should look different
>
> @server.custom_request("foo")
> def fooRequestHandler(argumentBaz):
>  # full Python interpreter access, full access to all of GDB, like we're @ the CLI
>  # say goodbye to MI! Yay! :P
>  return { "bar": gdb.execute("print foo", to_string=True), "someParam": argumentBaz }

Now, the DA would be able to send a request that looks like
> header omitted
> {"seq":6,"type":"request","command":"customRequest","arguments":{"command":"foo","args":["baz"]}}

And in this particular case the response to that request would be:

> {
>  "request_seq":6,
>  "type":"response",
>  "command":"customRequest",
>  "body": {
>   "bar": "resultFromPrintCommand",
>   "someParam": "baz"
>  },
>  "success":true,"seq":19
> }

If the command is unrecognized it will respond with a "success" : false, and an error message.

As a debug adapter maintainer for VSCode, a customRequest like this would be not only useful,
but crucial. VSCode itself in it's debug adapter interface specification,
i.e. not the protocol spec, but the Typescript interface, defines customRequest-functionality,
which can be found here;
https://github.com/microsoft/vscode-debugadapter-node/blob/main/adapter/src/debugSession.ts#L638

Unfortunately, there's nothing about such a request in the DAP-spec, but I'd argue that's really irrelevant;
the largest code editor for debug adapter protocol implementers, has a notion of it,
though it's up to DA-implementers to make sure they understand their own requests.

There are other, (in my opinion) bonuses of the customRequest functionality. The major one
being it can be a driving factor for further development of Python in GDB, by providing
an access point to GDB that returns "real python objects" (instead of the above example
of returning a string from the CLI-command) from commands and make it more
possible for future debug adapters to migrate away from MI (if they so choose),
which is difficult to work with, hard to read and even harder to test. JSON is superior
since there's so much open source code that supports JSON and in
a lot of languages it's even got built in support. "Driving GDB" via the DAP-interpreter
from any modern language is trivial because of this.

Beyond this patch, documentation would be needed also, to document how
to create customRequests, like the one above. I'm hoping Eli can provide me with
some direction here.
---
 gdb/python/lib/gdb/dap/server.py | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py
index ff88282049f..7cd60873319 100644
--- a/gdb/python/lib/gdb/dap/server.py
+++ b/gdb/python/lib/gdb/dap/server.py
@@ -33,6 +33,8 @@ _capabilities = {}
 # Map command names to callables.
 _commands = {}
 
+_custom_requests = {}
+
 # The global server.
 _server = None
 
@@ -171,6 +173,27 @@ def request(name):
     return wrap
 
 
+def custom_request(name):
+    """A decorator that indicates that the wrapper function should be
+    handled by a custom request"""
+
+    def wrap(func):
+        global _custom_requests
+        _custom_requests[name] = func
+        return in_dap_thread(func)
+
+    return wrap
+
+@request("customRequest")
+def custom_request_handler(**args):
+    global _custom_requests
+    cmd = args["command"]
+    if _custom_requests.get(cmd) is not None:
+        return _custom_requests[cmd](args["args"])
+    else:
+        raise Exception(f"Unrecognized customRequest {cmd}")
+
+
 def capability(name):
     """A decorator that indicates that the wrapper function implements
     the DAP capability NAME."""
-- 
2.40.1


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

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

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-07  9:41 [PATCH] gdb/DAP: Add customRequest Simon Farre
2023-05-07 10:45 ` Matt Rice
2023-05-07 21:19 ` Tom Tromey
2023-05-10  9:40 ` Lancelot SIX

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).