]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/dap/varref.py
95f00f5fe066fa0ab83bbaeff92a813346a68b6b
1 # Copyright 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/>.
17 from .startup
import in_gdb_thread
18 from .server
import client_bool_capability
19 from abc
import abstractmethod
20 from contextlib
import contextmanager
23 # A list of all the variable references created during this pause.
27 # When the inferior is re-started, we erase all variable references.
28 # See the section "Lifetime of Objects References" in the spec.
30 def clear_vars(event
):
35 gdb
.events
.cont
.connect(clear_vars
)
38 # A null context manager. Python supplies one, starting in 3.7.
45 def apply_format(value_format
):
46 """Temporarily apply the DAP ValueFormat.
48 This returns a new context manager that applies the given DAP
49 ValueFormat object globally, then restores gdb's state when finished."""
50 if value_format
is not None and "hex" in value_format
and value_format
["hex"]:
51 return gdb
.with_parameter("output-radix", 16)
56 """Represent a variable or a scope.
58 This class is just a base class, some methods must be implemented in
61 The 'ref' field can be used as the variablesReference in the protocol.
65 def __init__(self
, name
):
66 """Create a new variable reference with the given name.
68 NAME is a string or None. None means this does not have a
69 name, e.g., the result of expression evaluation."""
72 all_variables
.append(self
)
73 self
.ref
= len(all_variables
)
79 """Return a dictionary that describes this object for DAP.
81 The resulting object is a starting point that can be filled in
82 further. See the Scope or Variable types in the spec"""
84 "variablesReference": self
.ref
,
86 if self
.name
is not None:
87 result
["name"] = str(self
.name
)
90 def no_children(self
):
91 """Call this to declare that this variable or scope has no children."""
95 def fetch_one_child(self
, index
):
96 """Fetch one child of this variable.
98 INDEX is the index of the child to fetch.
99 This should return a tuple of the form (NAME, VALUE), where
100 NAME is the name of the variable, and VALUE is a gdb.Value."""
104 def child_count(self
):
105 """Return the number of children of this variable."""
109 def fetch_children(self
, start
, count
):
110 """Fetch children of this variable.
112 START is the starting index.
113 COUNT is the number to return, with 0 meaning return all."""
115 count
= self
.child_count()
116 if self
.children
is None:
117 self
.children
= [None] * self
.child_count()
119 for idx
in range(start
, start
+ count
):
120 if self
.children
[idx
] is None:
121 (name
, value
) = self
.fetch_one_child(idx
)
122 self
.children
[idx
] = VariableReference(name
, value
)
123 result
.append(self
.children
[idx
])
127 class VariableReference(BaseReference
):
128 """Concrete subclass of BaseReference that handles gdb.Value."""
130 def __init__(self
, name
, value
, result_name
="value"):
133 NAME is the name of this reference, see superclass.
134 VALUE is a gdb.Value that holds the value.
135 RESULT_NAME can be used to change how the simple string result
136 is emitted in the result dictionary."""
137 super().__init
__(name
)
139 self
.printer
= gdb
.printing
.make_visualizer(value
)
140 self
.result_name
= result_name
141 # We cache all the children we create.
142 self
.child_cache
= None
143 if not hasattr(self
.printer
, "children"):
149 def cache_children(self
):
150 if self
.child_cache
is None:
151 # This discards all laziness. This could be improved
152 # slightly by lazily evaluating children, but because this
153 # code also generally needs to know the number of
154 # children, it probably wouldn't help much. Note that
155 # this is only needed with legacy (non-ValuePrinter)
157 self
.child_cache
= list(self
.printer
.children())
158 return self
.child_cache
160 def child_count(self
):
161 if self
.count
is None:
165 if isinstance(self
.printer
, gdb
.ValuePrinter
) and hasattr(
166 self
.printer
, "num_children"
168 num_children
= self
.printer
.num_children()
169 if num_children
is None:
170 num_children
= len(self
.cache_children())
171 self
.count
= num_children
175 result
= super().to_object()
176 result
[self
.result_name
] = str(self
.printer
.to_string())
177 num_children
= self
.child_count()
178 if num_children
is not None:
180 hasattr(self
.printer
, "display_hint")
181 and self
.printer
.display_hint() == "array"
183 result
["indexedVariables"] = num_children
185 result
["namedVariables"] = num_children
186 if client_bool_capability("supportsMemoryReferences"):
187 # https://github.com/microsoft/debug-adapter-protocol/issues/414
188 # changed DAP to allow memory references for any of the
189 # variable response requests, and to lift the restriction
190 # to pointer-to-function from Variable.
191 if self
.value
.type.strip_typedefs().code
== gdb
.TYPE_CODE_PTR
:
192 result
["memoryReference"] = hex(int(self
.value
))
193 if client_bool_capability("supportsVariableType"):
194 result
["type"] = str(self
.value
.type)
198 def fetch_one_child(self
, idx
):
199 if isinstance(self
.printer
, gdb
.ValuePrinter
) and hasattr(
200 self
.printer
, "child"
202 return self
.printer
.child(idx
)
204 return self
.cache_children()[idx
]
208 def find_variable(ref
):
209 """Given a variable reference, return the corresponding variable object."""
211 # Variable references are offset by 1.
213 if ref
< 0 or ref
> len(all_variables
):
214 raise Exception("invalid variablesReference")
215 return all_variables
[ref
]