Implement DAP register scope

I noticed that gdb's DAP code did not provide a way to see register
values.  DAP defines a "register" scope, which this patch implements.
This patch also adds the missing (and optional) "presentationHint" to
scopes.
This commit is contained in:
Tom Tromey 2023-04-13 11:24:02 -06:00
parent 61f9fb1ea4
commit 14e8fded85
2 changed files with 33 additions and 5 deletions

View file

@ -50,14 +50,16 @@ def _block_vars(block):
class ScopeReference(BaseReference):
def __init__(self, name, frame, var_list):
def __init__(self, name, hint, frame, var_list):
super().__init__(name)
self.hint = hint
self.frame = frame
self.func = frame.function()
self.var_list = var_list
def to_object(self):
result = super().to_object()
result["presentationHint"] = self.hint
# How would we know?
result["expensive"] = False
result["namedVariables"] = len(self.var_list)
@ -79,6 +81,17 @@ class ScopeReference(BaseReference):
return (sym.print_name, val)
class RegisterReference(ScopeReference):
def __init__(self, name, frame):
super().__init__(
name, "registers", frame, list(frame.architecture().registers())
)
@in_gdb_thread
def fetch_one_child(self, idx):
return (self.var_list[idx].name, self.frame.read_register(self.var_list[idx]))
# Helper function to create a DAP scopes for a given frame ID.
@in_gdb_thread
def _get_scope(id):
@ -88,9 +101,10 @@ def _get_scope(id):
if block is not None:
(args, locs) = _block_vars(block)
if args:
scopes.append(ScopeReference("Arguments", frame, args))
scopes.append(ScopeReference("Arguments", "arguments", frame, args))
if locs:
scopes.append(ScopeReference("Locals", frame, locs))
scopes.append(ScopeReference("Locals", "locals", frame, locs))
scopes.append(RegisterReference("Registers", frame))
return [x.to_object() for x in scopes]

View file

@ -52,12 +52,20 @@ set scopes [dap_check_request_and_response "get scopes" scopes \
[format {o frameId [i %d]} $frame_id]]
set scopes [dict get [lindex $scopes 0] body scopes]
gdb_assert {[llength $scopes] == 1} "single scope"
gdb_assert {[llength $scopes] == 2} "two scopes"
set scope [lindex $scopes 0]
lassign $scopes scope reg_scope
gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
gdb_assert {[dict get $scope presentationHint] == "locals"} \
"locals presentation hint"
gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope"
gdb_assert {[dict get $reg_scope name] == "Registers"} \
"second scope is registers"
gdb_assert {[dict get $reg_scope presentationHint] == "registers"} \
"registers presentation hint"
gdb_assert {[dict get $reg_scope namedVariables] > 0} "at least one register"
set num [dict get $scope variablesReference]
set refs [lindex [dap_check_request_and_response "fetch variables" \
"variables" \
@ -98,4 +106,10 @@ set refs [lindex [dap_check_request_and_response "fetch contents of dei" \
set deivals [dict get $refs body variables]
gdb_assert {[llength $deivals] == 2} "dei has two members"
set num [dict get $reg_scope variablesReference]
# The request succeeding is sufficient.
dap_check_request_and_response "fetch first register" \
"variables" \
[format {o variablesReference [i %d] count [i 1]} $num]
dap_shutdown