2024-01-12 23:30:44 +08:00
|
|
|
# Copyright 2022-2024 Free Software Foundation, Inc.
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +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/>.
|
|
|
|
|
|
|
|
# The JSON parser.
|
|
|
|
load_lib ton.tcl
|
|
|
|
|
2023-12-12 23:20:31 +08:00
|
|
|
# The sequence number for the currently-executing instance of gdb
|
|
|
|
# launched via dap_gdb_start. This is used for log-file checking
|
|
|
|
# after the run is complete. Zero means gdb hasn't started yet.
|
|
|
|
set dap_gdb_instance 0
|
|
|
|
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
# The sequence number for the next DAP request. This is used by the
|
|
|
|
# automatic sequence-counting code below. It is reset each time GDB
|
|
|
|
# is restarted.
|
|
|
|
set dap_seq 1
|
|
|
|
|
2024-02-21 17:46:08 +08:00
|
|
|
# Return the current DAP log file.
|
|
|
|
proc current_dap_log_file {} {
|
|
|
|
global dap_gdb_instance
|
|
|
|
return [standard_output_file "dap.log.$dap_gdb_instance"]
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return a new DAP log file.
|
|
|
|
proc new_dap_log_file {} {
|
|
|
|
global dap_gdb_instance
|
|
|
|
incr dap_gdb_instance
|
|
|
|
return [current_dap_log_file]
|
|
|
|
}
|
|
|
|
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
# Start gdb using the DAP interpreter.
|
|
|
|
proc dap_gdb_start {} {
|
|
|
|
# Keep track of the number of times GDB has been launched.
|
|
|
|
global gdb_instances
|
|
|
|
incr gdb_instances
|
|
|
|
|
|
|
|
gdb_stdin_log_init
|
|
|
|
|
|
|
|
global GDBFLAGS stty_init
|
|
|
|
save_vars { GDBFLAGS stty_init } {
|
|
|
|
set stty_init "-echo raw"
|
2024-02-21 17:46:08 +08:00
|
|
|
set logfile [new_dap_log_file]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
append GDBFLAGS " -iex \"set debug dap-log-file $logfile\" -q -i=dap"
|
|
|
|
set res [gdb_spawn]
|
|
|
|
if {$res != 0} {
|
|
|
|
return $res
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Reset the counter.
|
|
|
|
set ::dap_seq 1
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
# A helper for dap_to_ton that decides if the list L is a JSON object
|
|
|
|
# or if it is an array.
|
|
|
|
proc _dap_is_obj {l} {
|
|
|
|
if {[llength $l] % 2 != 0} {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
foreach {key value} $l {
|
|
|
|
if {![string is alpha $key]} {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
# The "TON" format is a bit of a pain to write by hand, so this proc
|
|
|
|
# can be used to convert an ordinary Tcl list into TON by guessing at
|
|
|
|
# the correct forms to use. This can't be used in all cases, because
|
|
|
|
# Tcl can't really differentiate between literal forms. For example,
|
|
|
|
# there's no way to decide if "true" should be a string or the literal
|
|
|
|
# true.
|
|
|
|
#
|
|
|
|
# JSON objects must be passed in a particular form here -- as a list
|
|
|
|
# with an even number of elements, alternating keys and values. Each
|
|
|
|
# key must consist only of letters, no digits or other non-letter
|
|
|
|
# characters. Note that this is compatible with the Tcl 'dict'
|
|
|
|
# representation.
|
|
|
|
proc dap_to_ton {obj} {
|
|
|
|
if {[string is list $obj] && [llength $obj] > 1} {
|
|
|
|
if {[_dap_is_obj $obj]} {
|
|
|
|
set result o
|
|
|
|
foreach {key value} $obj {
|
|
|
|
lappend result $key \[[dap_to_ton $value]\]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
set result a
|
|
|
|
foreach val $obj {
|
|
|
|
lappend result \[[dap_to_ton $val]\]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} elseif {[string is entier $obj]} {
|
|
|
|
set result [list i $obj]
|
|
|
|
} elseif {[string is double $obj]} {
|
|
|
|
set result [list d $obj]
|
|
|
|
} elseif {$obj == "true" || $obj == "false" || $obj == "null"} {
|
|
|
|
set result [list l $obj]
|
|
|
|
} else {
|
|
|
|
set result [list s $obj]
|
|
|
|
}
|
|
|
|
return $result
|
|
|
|
}
|
|
|
|
|
|
|
|
# Format the object OBJ, in TON format, as JSON and send it to gdb.
|
2023-01-06 23:35:53 +08:00
|
|
|
proc _dap_send_ton {obj} {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
set json [namespace eval ton::2json $obj]
|
|
|
|
# FIXME this is wrong for non-ASCII characters.
|
|
|
|
set len [string length $json]
|
2023-01-06 23:37:10 +08:00
|
|
|
verbose -log ">>> $json"
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
send_gdb "Content-Length: $len\r\n\r\n$json"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Send a DAP request to gdb. COMMAND is the request's "command"
|
|
|
|
# field, and OBJ is the "arguments" field. If OBJ is empty, it is
|
|
|
|
# omitted. The sequence number of the request is automatically added,
|
|
|
|
# and this is also the return value. OBJ is assumed to already be in
|
|
|
|
# TON form.
|
2023-12-01 04:28:48 +08:00
|
|
|
proc dap_send_request {command {obj {}}} {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
# We can construct this directly as a TON object.
|
|
|
|
set result $::dap_seq
|
|
|
|
incr ::dap_seq
|
|
|
|
set req [format {o seq [i %d] type [s request] command [%s]} \
|
|
|
|
$result [list s $command]]
|
|
|
|
if {$obj != ""} {
|
|
|
|
append req " arguments \[$obj\]"
|
|
|
|
}
|
2023-01-06 23:35:53 +08:00
|
|
|
_dap_send_ton $req
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
return $result
|
|
|
|
}
|
|
|
|
|
2023-01-07 00:15:32 +08:00
|
|
|
# Read a JSON response from gdb. This will return a dict on
|
2023-09-21 22:49:44 +08:00
|
|
|
# success, or throw an exception on error. On success, the global
|
|
|
|
# "last_ton" will be set to the TON form of the result.
|
2023-01-06 23:35:53 +08:00
|
|
|
proc _dap_read_json {} {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
set length ""
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
set seen_timeout 0
|
|
|
|
set seen_eof 0
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
gdb_expect {
|
|
|
|
-re "^Content-Length: (\[0-9\]+)\r\n" {
|
|
|
|
set length $expect_out(1,string)
|
|
|
|
exp_continue
|
|
|
|
}
|
|
|
|
-re "^(\[^\r\n\]+)\r\n" {
|
|
|
|
# Any other header field.
|
|
|
|
exp_continue
|
|
|
|
}
|
|
|
|
-re "^\r\n" {
|
|
|
|
# Done.
|
|
|
|
}
|
|
|
|
timeout {
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
set seen_timeout 1
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
eof {
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
set seen_eof 1
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
if {$seen_timeout} {
|
|
|
|
error "timeout reading json header"
|
|
|
|
}
|
|
|
|
if {$seen_eof} {
|
|
|
|
error "eof reading json header"
|
|
|
|
}
|
|
|
|
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
if {$length == ""} {
|
|
|
|
error "didn't find content-length"
|
|
|
|
}
|
|
|
|
|
|
|
|
set json ""
|
|
|
|
while {$length > 0} {
|
|
|
|
# Tcl only allows up to 255 characters in a {} expression in a
|
|
|
|
# regexp, so we may need to read in chunks.
|
|
|
|
set this_len [expr {min ($length, 255)}]
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
set seen_timeout 0
|
|
|
|
set seen_eof 0
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
gdb_expect {
|
|
|
|
-re "^.{$this_len}" {
|
|
|
|
append json $expect_out(0,string)
|
|
|
|
}
|
|
|
|
timeout {
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
set seen_timeout 1
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
eof {
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
set seen_eof 1
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
[gdb/testsuite] Fix error handling in _dap_read_json
In _dap_read_json we have a gdb_expect with clauses that generate errors:
...
timeout {
error "timeout reading json header"
}
eof {
error "eof reading json header"
}
...
Proc gdb_expect uses dejagnu's remote_expect, which has some peculiar
semantics related to errors:
...
# remote_expect works basically the same as standard expect, but it
# also takes care of getting the file descriptor from the specified
# host and also calling the timeout/eof/default section if there is an
# error on the expect call.
.....
When a timeout triggers, it generates a timeout error, which is reported by
gdb_expect, after which it runs the timeout/eof/default clauses, which
generates an eof error, which is reported by runtest.
I think the intention here is to generate just a one error, a timeout error.
Fix this by postponing generating the error until after gdb_expect.
Tested on x86_64-linux, by:
- running all the DAP test-cases and observing no regressions, and
- modifying the gdb.dap/eof.exp test-case to trigger a timeout error, and
observing only a timeout error.
PR testsuite/31382
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31382
2024-02-21 21:25:31 +08:00
|
|
|
|
|
|
|
if {$seen_timeout} {
|
|
|
|
error "timeout reading json header"
|
|
|
|
}
|
|
|
|
if {$seen_eof} {
|
|
|
|
error "eof reading json header"
|
|
|
|
}
|
|
|
|
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
incr length -$this_len
|
|
|
|
}
|
|
|
|
|
2023-09-21 22:49:44 +08:00
|
|
|
global last_ton
|
|
|
|
set last_ton [ton::json2ton $json]
|
|
|
|
return [namespace eval ton::2dict $last_ton]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Read a sequence of JSON objects from gdb, until a response object is
|
|
|
|
# seen. If the response object has the request sequence number NUM,
|
|
|
|
# and is for command CMD, return a list of two elements: the response
|
|
|
|
# object and a list of any preceding events, in the order they were
|
2023-09-21 22:49:44 +08:00
|
|
|
# emitted. The objects are dicts. If a response object is seen but
|
|
|
|
# has the wrong sequence number or command, throw an exception If a
|
|
|
|
# response is seen, this leaves the global "last_ton" set to the TON
|
|
|
|
# for the response.
|
2023-01-07 00:15:32 +08:00
|
|
|
|
2023-12-01 04:28:48 +08:00
|
|
|
proc dap_read_response {cmd num} {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
set result {}
|
|
|
|
while 1 {
|
2023-01-07 00:15:32 +08:00
|
|
|
set d [_dap_read_json]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
if {[dict get $d type] == "response"} {
|
|
|
|
if {[dict get $d request_seq] != $num} {
|
|
|
|
error "saw wrong request_seq in $obj"
|
|
|
|
} elseif {[dict get $d command] != $cmd} {
|
|
|
|
error "saw wrong command in $obj"
|
|
|
|
} else {
|
2023-01-07 00:15:32 +08:00
|
|
|
return [list $d $result]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
} else {
|
2023-01-07 00:15:32 +08:00
|
|
|
lappend result $d
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-01 04:28:48 +08:00
|
|
|
# A wrapper for dap_send_request and dap_read_response. This sends a
|
2023-01-07 00:09:00 +08:00
|
|
|
# request to gdb and returns the response as a dict.
|
|
|
|
proc dap_request_and_response {command {obj {}}} {
|
2023-12-01 04:28:48 +08:00
|
|
|
set seq [dap_send_request $command $obj]
|
|
|
|
return [dap_read_response $command $seq]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Like dap_request_and_response, but also checks that the response
|
2023-01-07 00:09:00 +08:00
|
|
|
# indicates success. NAME is used to issue a test result.
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
proc dap_check_request_and_response {name command {obj {}}} {
|
2023-01-07 00:15:32 +08:00
|
|
|
set response_and_events [dap_request_and_response $command $obj]
|
|
|
|
set response [lindex $response_and_events 0]
|
|
|
|
if {[dict get $response success] != "true"} {
|
|
|
|
verbose "request failure: $response"
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
fail "$name success"
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
pass "$name success"
|
2023-01-07 00:15:32 +08:00
|
|
|
return $response_and_events
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Start gdb, send a DAP initialization request and return the
|
|
|
|
# response. This approach lets the caller check the feature list, if
|
2024-01-18 22:35:48 +08:00
|
|
|
# desired. Returns the empty string on failure. NAME is used as the
|
|
|
|
# test name.
|
|
|
|
proc dap_initialize {{name "initialize"}} {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
if {[dap_gdb_start]} {
|
|
|
|
return ""
|
|
|
|
}
|
2023-05-16 21:36:08 +08:00
|
|
|
return [dap_check_request_and_response $name initialize \
|
|
|
|
{o clientID [s "gdb testsuite"] \
|
2023-05-27 03:35:52 +08:00
|
|
|
supportsVariableType [l true] \
|
2023-07-28 03:06:38 +08:00
|
|
|
supportsVariablePaging [l true] \
|
|
|
|
supportsMemoryReferences [l true]}]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
|
2024-01-18 22:35:48 +08:00
|
|
|
# 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:
|
|
|
|
#
|
2023-07-25 00:12:17 +08:00
|
|
|
# * arguments - value is a list of strings passed as command-line
|
|
|
|
# arguments to the inferior
|
|
|
|
# * env - value is a list of pairs of the form {VAR VALUE} that is
|
|
|
|
# used to populate the inferior's environment.
|
|
|
|
# * stop_at_main - value is ignored, the presence of this means that
|
|
|
|
# "stopAtBeginningOfMainSubprogram" will be passed to the launch
|
|
|
|
# request.
|
2023-07-24 23:14:20 +08:00
|
|
|
# * cwd - value is the working directory to use.
|
2023-07-25 00:12:17 +08:00
|
|
|
#
|
|
|
|
# After this proc is called, gdb will be ready to accept breakpoint
|
|
|
|
# requests.
|
|
|
|
proc dap_launch {file {args {}}} {
|
2023-05-02 03:59:20 +08:00
|
|
|
set params "o program"
|
|
|
|
append params " [format {[%s]} [list s [standard_output_file $file]]]"
|
|
|
|
|
2023-07-25 00:12:17 +08:00
|
|
|
foreach {key value} $args {
|
|
|
|
switch -exact -- $key {
|
|
|
|
arguments {
|
|
|
|
append params " args"
|
|
|
|
set arglist ""
|
|
|
|
foreach arg $value {
|
|
|
|
append arglist " \[s [list $arg]\]"
|
|
|
|
}
|
|
|
|
append params " \[a $arglist\]"
|
|
|
|
}
|
2023-05-02 03:59:20 +08:00
|
|
|
|
2023-07-25 00:12:17 +08:00
|
|
|
env {
|
|
|
|
append params " env"
|
|
|
|
set envlist ""
|
|
|
|
foreach pair $value {
|
|
|
|
lassign $pair var value
|
|
|
|
append envlist " $var"
|
|
|
|
append envlist " [format {[%s]} [list s $value]]"
|
|
|
|
}
|
|
|
|
append params " \[o $envlist\]"
|
|
|
|
}
|
|
|
|
|
|
|
|
stop_at_main {
|
|
|
|
append params { stopAtBeginningOfMainSubprogram [l true]}
|
|
|
|
}
|
2023-05-02 03:59:20 +08:00
|
|
|
|
2023-07-24 23:14:20 +08:00
|
|
|
cwd {
|
|
|
|
append envlist " cwd [format {[%s]} [list s $value]]"
|
|
|
|
}
|
|
|
|
|
2023-07-25 00:12:17 +08:00
|
|
|
default {
|
|
|
|
error "unrecognized parameter $key"
|
|
|
|
}
|
|
|
|
}
|
2023-05-16 23:51:51 +08:00
|
|
|
}
|
|
|
|
|
2023-05-02 03:59:20 +08:00
|
|
|
return [dap_check_request_and_response "startup - launch" launch $params]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
|
2023-05-10 04:20:31 +08:00
|
|
|
# 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.
|
2023-12-08 00:51:52 +08:00
|
|
|
proc dap_attach {pid {prog ""}} {
|
2024-01-23 01:22:45 +08:00
|
|
|
if {[dap_initialize "startup - initialize"] == ""} {
|
2023-05-10 04:20:31 +08:00
|
|
|
return ""
|
|
|
|
}
|
2023-12-08 00:51:52 +08:00
|
|
|
|
|
|
|
set args [format {o pid [i %s]} $pid]
|
|
|
|
if {$prog != ""} {
|
|
|
|
append args [format { program [s %s]} $prog]
|
|
|
|
}
|
|
|
|
|
|
|
|
return [dap_check_request_and_response "startup - attach" attach $args]
|
2023-05-10 04:20:31 +08:00
|
|
|
}
|
|
|
|
|
2023-05-16 23:34:20 +08:00
|
|
|
# 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.
|
|
|
|
proc dap_target_remote {target} {
|
2024-01-23 01:22:45 +08:00
|
|
|
if {[dap_initialize "startup - initialize"] == ""} {
|
2023-05-16 23:34:20 +08:00
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return [dap_check_request_and_response "startup - target" attach \
|
|
|
|
[format {o target [s %s]} $target]]
|
|
|
|
}
|
|
|
|
|
2023-12-12 23:20:31 +08:00
|
|
|
# Read the most recent DAP log file and check it for exceptions.
|
2024-01-11 03:51:10 +08:00
|
|
|
proc dap_check_log_file {} {
|
2024-02-21 17:46:08 +08:00
|
|
|
set fd [open [current_dap_log_file]]
|
2023-12-12 23:20:31 +08:00
|
|
|
set contents [read $fd]
|
|
|
|
close $fd
|
|
|
|
|
|
|
|
set ok 1
|
|
|
|
foreach line [split $contents "\n"] {
|
|
|
|
if {[regexp "^Traceback" $line]} {
|
|
|
|
set ok 0
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if {$ok} {
|
|
|
|
pass "exceptions in log file"
|
|
|
|
} else {
|
2024-02-26 23:03:45 +08:00
|
|
|
verbose -log -- "--- DAP LOG START ---"
|
|
|
|
verbose -log -- $contents
|
|
|
|
verbose -log -- "--- DAP LOG END ---"
|
2023-12-12 23:20:31 +08:00
|
|
|
fail "exceptions in log file"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-22 18:35:26 +08:00
|
|
|
# Read the most recent DAP log file and check that regexp RE matches.
|
|
|
|
proc dap_check_log_file_re { re } {
|
|
|
|
set fd [open [current_dap_log_file]]
|
|
|
|
set contents [read $fd]
|
|
|
|
close $fd
|
|
|
|
|
|
|
|
set ok [regexp $re $contents]
|
|
|
|
gdb_assert {$ok} "log file matched $re"
|
|
|
|
}
|
|
|
|
|
2023-05-10 04:20:31 +08:00
|
|
|
# Cleanly shut down gdb. TERMINATE is passed as the terminateDebuggee
|
|
|
|
# parameter to the request.
|
|
|
|
proc dap_shutdown {{terminate false}} {
|
|
|
|
dap_check_request_and_response "shutdown" disconnect \
|
|
|
|
[format {o terminateDebuggee [l %s]} $terminate]
|
2024-02-24 04:51:58 +08:00
|
|
|
|
|
|
|
# Check gdb's exit status.
|
|
|
|
global gdb_spawn_id
|
|
|
|
set result [wait -i $gdb_spawn_id]
|
|
|
|
gdb_assert {[lindex $result 2] == 0}
|
|
|
|
gdb_assert {[lindex $result 3] == 0}
|
|
|
|
|
|
|
|
clear_gdb_spawn_id
|
|
|
|
|
2024-01-11 03:51:10 +08:00
|
|
|
dap_check_log_file
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Search the event list EVENTS for an output event matching the regexp
|
|
|
|
# RX. Pass the test NAME if found, fail if not.
|
|
|
|
proc dap_search_output {name rx events} {
|
2023-01-07 00:15:32 +08:00
|
|
|
foreach d $events {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
if {[dict get $d type] != "event"
|
|
|
|
|| [dict get $d event] != "output"} {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if {[regexp $rx [dict get $d body output]]} {
|
|
|
|
pass $name
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fail $name
|
|
|
|
}
|
|
|
|
|
2023-01-07 00:15:32 +08:00
|
|
|
# Check that D (a dict object) has values that match the
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
# key/value pairs given in ARGS. NAME is used as the test name.
|
2023-01-07 00:15:32 +08:00
|
|
|
proc dap_match_values {name d args} {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
foreach {key value} $args {
|
|
|
|
if {[eval dict get [list $d] $key] != $value} {
|
|
|
|
fail "$name (checking $key)"
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pass $name
|
|
|
|
}
|
|
|
|
|
2023-01-07 02:27:14 +08:00
|
|
|
# A helper for dap_wait_for_event_and_check that reads events, looking for one
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
# matching TYPE.
|
2023-01-07 02:27:14 +08:00
|
|
|
#
|
|
|
|
# Return a list of two items:
|
|
|
|
#
|
|
|
|
# - the matched event
|
|
|
|
# - a list of any JSON objects (events or others) seen before the matched
|
|
|
|
# event.
|
|
|
|
proc _dap_wait_for_event { {type ""} } {
|
|
|
|
set preceding [list]
|
|
|
|
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
while 1 {
|
|
|
|
# We don't do any extra error checking here for the time
|
|
|
|
# being; we'll just get a timeout thrown instead.
|
2023-01-07 00:15:32 +08:00
|
|
|
set d [_dap_read_json]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
if {[dict get $d type] == "event"
|
2023-01-07 02:27:14 +08:00
|
|
|
&& ($type == "" || [dict get $d event] == $type)} {
|
|
|
|
return [list $d $preceding]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
2023-01-07 02:27:14 +08:00
|
|
|
|
|
|
|
lappend preceding $d
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Read JSON objects looking for an event whose "event" field is TYPE.
|
2023-01-07 00:15:32 +08:00
|
|
|
#
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
# NAME is used as the test name; it defaults to TYPE. Extra arguments
|
|
|
|
# are used to check fields of the event; the arguments alternate
|
|
|
|
# between a field name (in "dict get" form) and its expected value.
|
2023-01-07 00:15:32 +08:00
|
|
|
#
|
2023-01-07 02:27:14 +08:00
|
|
|
# Return a list of two items:
|
|
|
|
#
|
|
|
|
# - the matched event (regardless of whether it passed the field validation or
|
|
|
|
# not)
|
|
|
|
# - a list of any JSON objects (events or others) seen before the matched
|
|
|
|
# event.
|
2023-01-07 01:09:38 +08:00
|
|
|
proc dap_wait_for_event_and_check {name type args} {
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
if {$name == ""} {
|
|
|
|
set name $type
|
|
|
|
}
|
|
|
|
|
2023-01-07 01:09:38 +08:00
|
|
|
set result [_dap_wait_for_event $type]
|
2023-01-07 02:27:14 +08:00
|
|
|
set event [lindex $result 0]
|
|
|
|
eval dap_match_values [list $name $event] $args
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
|
|
|
|
return $result
|
|
|
|
}
|
|
|
|
|
|
|
|
# A convenience function to extract the breakpoint number when a new
|
|
|
|
# breakpoint is created. OBJ is an object as returned by
|
|
|
|
# dap_check_request_and_response.
|
|
|
|
proc dap_get_breakpoint_number {obj} {
|
2023-01-07 00:15:32 +08:00
|
|
|
set d [lindex $obj 0]
|
Initial implementation of Debugger Adapter Protocol
The Debugger Adapter Protocol is a JSON-RPC protocol that IDEs can use
to communicate with debuggers. You can find more information here:
https://microsoft.github.io/debug-adapter-protocol/
Frequently this is implemented as a shim, but it seemed to me that GDB
could implement it directly, via the Python API. This patch is the
initial implementation.
DAP is implemented as a new "interp". This is slightly weird, because
it doesn't act like an ordinary interpreter -- for example it doesn't
implement a command syntax, and doesn't use GDB's ordinary event loop.
However, this seemed like the best approach overall.
To run GDB in this mode, use:
gdb -i=dap
The DAP code will accept JSON-RPC messages on stdin and print
responses to stdout. GDB redirects the inferior's stdout to a new
pipe so that output can be encapsulated by the protocol.
The Python code uses multiple threads to do its work. Separate
threads are used for reading JSON from the client and for writing JSON
to the client. All GDB work is done in the main thread. (The first
implementation used asyncio, but this had some limitations, and so I
rewrote it to use threads instead.)
This is not a complete implementation of the protocol, but it does
implement enough to demonstrate that the overall approach works.
There is a rudimentary test suite. It uses a JSON parser written in
pure Tcl. This parser is under the same license as Tcl itself, so I
felt it was acceptable to simply import it into the tree.
There is also a bit of documentation -- just documenting the new
interpreter name.
2022-06-24 01:11:36 +08:00
|
|
|
set bplist [dict get $d body breakpoints]
|
|
|
|
return [dict get [lindex $bplist 0] id]
|
|
|
|
}
|