87f2ed7547f9569386df678623c372473694e0a0
1 # Copyright 2022-2023 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 from .frames
import frame_for_id
19 from .startup
import send_gdb_with_response
, in_gdb_thread
20 from .server
import request
21 from .varref
import BaseReference
24 # Map DAP frame IDs to scopes. This ensures that scopes are re-used.
28 # When the inferior is re-started, we erase all scope references. See
29 # the section "Lifetime of Objects References" in the spec.
31 def clear_scopes(event
):
36 gdb
.events
.cont
.connect(clear_scopes
)
39 class _ScopeReference(BaseReference
):
40 def __init__(self
, name
, hint
, frame
, var_list
):
41 super().__init
__(name
)
44 self
.inf_frame
= frame
.inferior_frame()
45 self
.func
= frame
.function()
46 self
.line
= frame
.line()
47 # VAR_LIST might be any kind of iterator, but it's convenient
48 # here if it is just a collection.
49 self
.var_list
= tuple(var_list
)
52 result
= super().to_object()
53 result
["presentationHint"] = self
.hint
55 result
["expensive"] = False
56 result
["namedVariables"] = len(self
.var_list
)
57 if self
.line
is not None:
58 result
["line"] = self
.line
59 # FIXME construct a Source object
62 def has_children(self
):
65 def child_count(self
):
66 return len(self
.var_list
)
69 def fetch_one_child(self
, idx
):
70 # Make sure to select the frame first. Ideally this would not
71 # be needed, but this is a way to set the current language
72 # properly so that language-dependent APIs will work.
73 self
.inf_frame
.select()
74 # Here SYM will conform to the SymValueWrapper interface.
75 sym
= self
.var_list
[idx
]
76 name
= str(sym
.symbol())
79 # No synthetic value, so must read the symbol value
81 val
= sym
.symbol().value(self
.inf_frame
)
82 elif not isinstance(val
, gdb
.Value
):
87 class _RegisterReference(_ScopeReference
):
88 def __init__(self
, name
, frame
):
90 name
, "registers", frame
, frame
.inferior_frame().architecture().registers()
94 def fetch_one_child(self
, idx
):
96 self
.var_list
[idx
].name
,
97 self
.inf_frame
.read_register(self
.var_list
[idx
]),
101 # Helper function to create a DAP scopes for a given frame ID.
104 global frame_to_scope
105 if id in frame_to_scope
:
106 scopes
= frame_to_scope
[id]
108 frame
= frame_for_id(id)
110 args
= frame
.frame_args()
112 scopes
.append(_ScopeReference("Arguments", "arguments", frame
, args
))
113 locs
= frame
.frame_locals()
115 scopes
.append(_ScopeReference("Locals", "locals", frame
, locs
))
116 scopes
.append(_RegisterReference("Registers", frame
))
117 frame_to_scope
[id] = scopes
118 return [x
.to_object() for x
in scopes
]
122 def scopes(*, frameId
: int, **extra
):
123 scopes
= send_gdb_with_response(lambda: _get_scope(frameId
))
124 return {"scopes": scopes
}