mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
Add returnValue scope to DAP
The DAP spec recently changed to add a new scope for the return value
from a "stepOut" request. This new scope uses the "returnValue"
presentation hint. See:
https://github.com/microsoft/debug-adapter-protocol/issues/458
This patch implements this for gdb.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31945
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This commit is contained in:
4
gdb/NEWS
4
gdb/NEWS
@@ -8,6 +8,10 @@
|
||||
** The "scopes" request will now return a scope holding global
|
||||
variables from the stack frame's compilation unit.
|
||||
|
||||
** The "scopes" request will return a "returnValue" scope holding
|
||||
the return value from the latest "stepOut" command, when
|
||||
appropriate.
|
||||
|
||||
* For ARM targets, the offset of the pc in the jmp_buf has been fixed to match
|
||||
glibc 2.20 and later. This should only matter when not using libc probes.
|
||||
This may cause breakage when using an incompatible libc, like uclibc or
|
||||
|
||||
@@ -111,20 +111,19 @@ class _ScopeReference(BaseReference):
|
||||
return symbol_value(self.var_list[idx], self.frame)
|
||||
|
||||
|
||||
# A _ScopeReference that prepends the most recent return value. Note
|
||||
# that this object is only created if such a value actually exists.
|
||||
# A _ScopeReference that wraps the 'finish' value. Note that this
|
||||
# object is only created if such a value actually exists.
|
||||
class _FinishScopeReference(_ScopeReference):
|
||||
def __init__(self, *args):
|
||||
super().__init__(*args)
|
||||
def __init__(self, frame):
|
||||
super().__init__("Return", "returnValue", frame, ())
|
||||
|
||||
def child_count(self):
|
||||
return super().child_count() + 1
|
||||
return 1
|
||||
|
||||
def fetch_one_child(self, idx):
|
||||
if idx == 0:
|
||||
global _last_return_value
|
||||
return ("(return)", _last_return_value)
|
||||
return super().fetch_one_child(idx - 1)
|
||||
assert idx == 0
|
||||
global _last_return_value
|
||||
return ("(return)", _last_return_value)
|
||||
|
||||
|
||||
class _RegisterReference(_ScopeReference):
|
||||
@@ -159,11 +158,11 @@ def scopes(*, frameId: int, **extra):
|
||||
# Make sure to handle the None case as well as the empty
|
||||
# iterator case.
|
||||
locs = tuple(frame.frame_locals() or ())
|
||||
if has_return_value:
|
||||
scopes.append(_FinishScopeReference("Locals", "locals", frame, locs))
|
||||
elif locs:
|
||||
if locs:
|
||||
scopes.append(_ScopeReference("Locals", "locals", frame, locs))
|
||||
scopes.append(_RegisterReference("Registers", frame))
|
||||
if has_return_value:
|
||||
scopes.append(_FinishScopeReference(frame))
|
||||
frame_to_scope[frameId] = scopes
|
||||
global_scope = get_global_scope(frame)
|
||||
if global_scope is not None:
|
||||
|
||||
@@ -59,15 +59,21 @@ 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] == 2} "two scopes"
|
||||
gdb_assert {[llength $scopes] == 3} "three scopes"
|
||||
|
||||
lassign $scopes scope reg_scope
|
||||
lassign $scopes scope reg_scope return_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] == 2} "two vars in scope"
|
||||
gdb_assert {[dict get $scope namedVariables] == 1} "one var in scope"
|
||||
|
||||
set num [dict get $scope variablesReference]
|
||||
gdb_assert {[dict get $return_scope name] == "Return"} "scope is return"
|
||||
gdb_assert {[dict get $return_scope presentationHint] == "returnValue"} \
|
||||
"returnValue presentation hint"
|
||||
gdb_assert {[dict get $return_scope namedVariables] == 1} \
|
||||
"one var in return scope"
|
||||
|
||||
set num [dict get $return_scope variablesReference]
|
||||
set refs [lindex [dap_check_request_and_response "fetch arguments" \
|
||||
"variables" \
|
||||
[format {o variablesReference [i %d]} $num]] \
|
||||
|
||||
Reference in New Issue
Block a user