Add extra files found in etc/ sub-directory to ETC_SUPPORT in src-release.sh
[binutils-gdb.git] / gdb / gdb-gdb.py.in
blobb5a7fa4f39034dd74fee7ebf349c9a14f827d102
1 # Copyright (C) 2009-2024 Free Software Foundation, Inc.
3 # This file is part of GDB.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 import os.path
20 import gdb
23 class TypeFlag:
24 """A class that allows us to store a flag name, its short name,
25 and its value.
27 In the GDB sources, struct type has a component called instance_flags
28 in which the value is the addition of various flags. These flags are
29 defined by the enumerates type_instance_flag_value. This class helps us
30 recreate a list with all these flags that is easy to manipulate and sort.
31 Because all flag names start with TYPE_INSTANCE_FLAG_, a short_name
32 attribute is provided that strips this prefix.
34 ATTRIBUTES
35 name: The enumeration name (eg: "TYPE_INSTANCE_FLAG_CONST").
36 value: The associated value.
37 short_name: The enumeration name, with the suffix stripped.
38 """
40 def __init__(self, name, value):
41 self.name = name
42 self.value = value
43 self.short_name = name.replace("TYPE_INSTANCE_FLAG_", "")
45 def __lt__(self, other):
46 """Sort by value order."""
47 return self.value < other.value
50 # A list of all existing TYPE_INSTANCE_FLAGS_* enumerations,
51 # stored as TypeFlags objects. Lazy-initialized.
52 TYPE_FLAGS = None
55 class TypeFlagsPrinter:
56 """A class that prints a decoded form of an instance_flags value.
58 This class uses a global named TYPE_FLAGS, which is a list of
59 all defined TypeFlag values. Using a global allows us to compute
60 this list only once.
62 This class relies on a couple of enumeration types being defined.
63 If not, then printing of the instance_flag is going to be degraded,
64 but it's not a fatal error.
65 """
67 def __init__(self, val):
68 self.val = val
70 def __str__(self):
71 global TYPE_FLAGS
72 if TYPE_FLAGS is None:
73 self.init_TYPE_FLAGS()
74 if not self.val:
75 return "0"
76 if TYPE_FLAGS:
77 flag_list = [
78 flag.short_name for flag in TYPE_FLAGS if self.val & flag.value
80 else:
81 flag_list = ["???"]
82 return "0x%x [%s]" % (self.val, "|".join(flag_list))
84 def init_TYPE_FLAGS(self):
85 """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
86 This operation requires the search of a couple of enumeration types.
87 If not found, a warning is printed on stdout, and TYPE_FLAGS is
88 set to the empty list.
90 The resulting list is sorted by increasing value, to facilitate
91 printing of the list of flags used in an instance_flags value.
92 """
93 global TYPE_FLAGS
94 TYPE_FLAGS = []
95 try:
96 iflags = gdb.lookup_type("enum type_instance_flag_value")
97 except:
98 print("Warning: Cannot find enum type_instance_flag_value type.")
99 print(" `struct type' pretty-printer will be degraded")
100 return
101 TYPE_FLAGS = [TypeFlag(field.name, field.enumval) for field in iflags.fields()]
102 TYPE_FLAGS.sort()
105 class StructTypePrettyPrinter:
106 """Pretty-print an object of type struct type"""
108 def __init__(self, val):
109 self.val = val
111 def to_string(self):
112 fields = []
113 fields.append("pointer_type = %s" % self.val["pointer_type"])
114 fields.append("reference_type = %s" % self.val["reference_type"])
115 fields.append("chain = %s" % self.val["reference_type"])
116 fields.append(
117 "instance_flags = %s" % TypeFlagsPrinter(self.val["m_instance_flags"])
119 fields.append("length = %d" % self.val["m_length"])
120 fields.append("main_type = %s" % self.val["main_type"])
121 return "\n{" + ",\n ".join(fields) + "}"
124 class StructMainTypePrettyPrinter:
125 """Pretty-print an objet of type main_type"""
127 def __init__(self, val):
128 self.val = val
130 def flags_to_string(self):
131 """struct main_type contains a series of components that
132 are one-bit ints whose name start with "flag_". For instance:
133 flag_unsigned, flag_stub, etc. In essence, these components are
134 really boolean flags, and this method prints a short synthetic
135 version of the value of all these flags. For instance, if
136 flag_unsigned and flag_static are the only components set to 1,
137 this function will return "unsigned|static".
139 fields = [
140 field.name.replace("flag_", "")
141 for field in self.val.type.fields()
142 if field.name.startswith("flag_") and self.val[field.name]
144 return "|".join(fields)
146 def owner_to_string(self):
147 """Return an image of component "owner"."""
148 if self.val["m_flag_objfile_owned"] != 0:
149 return "%s (objfile)" % self.val["m_owner"]["objfile"]
150 else:
151 return "%s (gdbarch)" % self.val["m_owner"]["gdbarch"]
153 def struct_field_location_img(self, field_val):
154 """Return an image of the loc component inside the given field
155 gdb.Value.
157 loc_val = field_val["m_loc"]
158 loc_kind = str(field_val["m_loc_kind"])
159 if loc_kind == "FIELD_LOC_KIND_BITPOS":
160 return "bitpos = %d" % loc_val["bitpos"]
161 elif loc_kind == "FIELD_LOC_KIND_ENUMVAL":
162 return "enumval = %d" % loc_val["enumval"]
163 elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
164 return "physaddr = 0x%x" % loc_val["physaddr"]
165 elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
166 return "physname = %s" % loc_val["physname"]
167 elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
168 return "dwarf_block = %s" % loc_val["dwarf_block"]
169 else:
170 return "m_loc = ??? (unsupported m_loc_kind value)"
172 def struct_field_img(self, fieldno):
173 """Return an image of the main_type field number FIELDNO."""
174 f = self.val["flds_bnds"]["fields"][fieldno]
175 label = "flds_bnds.fields[%d]:" % fieldno
176 if f["m_artificial"]:
177 label += " (artificial)"
178 fields = []
179 fields.append("m_name = %s" % f["m_name"])
180 fields.append("m_type = %s" % f["m_type"])
181 fields.append("m_loc_kind = %s" % f["m_loc_kind"])
182 fields.append("bitsize = %d" % f["m_bitsize"])
183 fields.append(self.struct_field_location_img(f))
184 return label + "\n" + " {" + ",\n ".join(fields) + "}"
186 def bound_img(self, bound_name):
187 """Return an image of the given main_type's bound."""
188 bounds = self.val["flds_bnds"]["bounds"].dereference()
189 b = bounds[bound_name]
190 bnd_kind = str(b["m_kind"])
191 if bnd_kind == "PROP_CONST":
192 return str(b["m_data"]["const_val"])
193 elif bnd_kind == "PROP_UNDEFINED":
194 return "(undefined)"
195 else:
196 info = [bnd_kind]
197 if bound_name == "high" and bounds["flag_upper_bound_is_count"]:
198 info.append("upper_bound_is_count")
199 return "{} ({})".format(str(b["m_data"]["baton"]), ",".join(info))
201 def bounds_img(self):
202 """Return an image of the main_type bounds."""
203 b = self.val["flds_bnds"]["bounds"].dereference()
204 low = self.bound_img("low")
205 high = self.bound_img("high")
207 img = "flds_bnds.bounds = {%s, %s}" % (low, high)
208 if b["flag_bound_evaluated"]:
209 img += " [evaluated]"
210 return img
212 def type_specific_img(self):
213 """Return a string image of the main_type type_specific union.
214 Only the relevant component of that union is printed (based on
215 the value of the type_specific_kind field.
217 type_specific_kind = str(self.val["type_specific_field"])
218 type_specific = self.val["type_specific"]
219 if type_specific_kind == "TYPE_SPECIFIC_NONE":
220 img = "type_specific_field = %s" % type_specific_kind
221 elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
222 img = "cplus_stuff = %s" % type_specific["cplus_stuff"]
223 elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
224 img = (
225 "gnat_stuff = {descriptive_type = %s}"
226 % type_specific["gnat_stuff"]["descriptive_type"]
228 elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
229 img = "floatformat[0..1] = %s" % type_specific["floatformat"]
230 elif type_specific_kind == "TYPE_SPECIFIC_FUNC":
231 img = (
232 "calling_convention = %d"
233 % type_specific["func_stuff"]["calling_convention"]
235 # tail_call_list is not printed.
236 elif type_specific_kind == "TYPE_SPECIFIC_SELF_TYPE":
237 img = "self_type = %s" % type_specific["self_type"]
238 elif type_specific_kind == "TYPE_SPECIFIC_FIXED_POINT":
239 # The scaling factor is an opaque structure, so we cannot
240 # decode its value from Python (not without insider knowledge).
241 img = (
242 "scaling_factor: <opaque> (call __gmpz_dump with "
243 " _mp_num and _mp_den fields if needed)"
245 elif type_specific_kind == "TYPE_SPECIFIC_INT":
246 img = "int_stuff = { bit_size = %d, bit_offset = %d }" % (
247 type_specific["int_stuff"]["bit_size"],
248 type_specific["int_stuff"]["bit_offset"],
250 else:
251 img = (
252 "type_specific = ??? (unknown type_specific_kind: %s)"
253 % type_specific_kind
255 return img
257 def to_string(self):
258 """Return a pretty-printed image of our main_type."""
259 fields = []
260 fields.append("name = %s" % self.val["name"])
261 fields.append("code = %s" % self.val["code"])
262 fields.append("flags = [%s]" % self.flags_to_string())
263 fields.append("owner = %s" % self.owner_to_string())
264 fields.append("target_type = %s" % self.val["m_target_type"])
265 if self.val["m_nfields"] > 0:
266 for fieldno in range(self.val["m_nfields"]):
267 fields.append(self.struct_field_img(fieldno))
268 if self.val["code"] == gdb.TYPE_CODE_RANGE:
269 fields.append(self.bounds_img())
270 fields.append(self.type_specific_img())
272 return "\n{" + ",\n ".join(fields) + "}"
275 class CoreAddrPrettyPrinter:
276 """Print CORE_ADDR values as hex."""
278 def __init__(self, val):
279 self._val = val
281 def to_string(self):
282 return hex(int(self._val))
285 class IntrusiveListPrinter:
286 """Print a struct intrusive_list."""
288 def __init__(self, val):
289 self._val = val
291 # Type of linked items.
292 self._item_type = self._val.type.template_argument(0)
293 self._node_ptr_type = gdb.lookup_type(
294 "intrusive_list_node<{}>".format(self._item_type.tag)
295 ).pointer()
297 # Type of value -> node converter.
298 self._conv_type = self._val.type.template_argument(1)
300 if self._uses_member_node():
301 # The second template argument of intrusive_member_node is a member
302 # pointer value. Its value is the offset of the node member in the
303 # enclosing type.
304 member_node_ptr = self._conv_type.template_argument(1)
305 member_node_ptr = member_node_ptr.cast(gdb.lookup_type("int"))
306 self._member_node_offset = int(member_node_ptr)
308 # This is only needed in _as_node_ptr if using a member node. Look it
309 # up here so we only do it once.
310 self._char_ptr_type = gdb.lookup_type("char").pointer()
312 def display_hint(self):
313 return "array"
315 def _uses_member_node(self):
316 """Return True if the list items use a node as a member, False if
317 they use a node as a base class.
320 if self._conv_type.name.startswith("intrusive_member_node<"):
321 return True
322 elif self._conv_type.name.startswith("intrusive_base_node<"):
323 return False
324 else:
325 raise RuntimeError(
326 "Unexpected intrusive_list value -> node converter type: {}".format(
327 self._conv_type.name
331 def to_string(self):
332 s = "intrusive list of {}".format(self._item_type)
334 if self._uses_member_node():
335 node_member = self._conv_type.template_argument(1)
336 s += ", linked through {}".format(node_member)
338 return s
340 def _as_node_ptr(self, elem_ptr):
341 """Given ELEM_PTR, a pointer to a list element, return a pointer to the
342 corresponding intrusive_list_node.
345 assert elem_ptr.type.code == gdb.TYPE_CODE_PTR
347 if self._uses_member_node():
348 # Node as a member: add the member node offset from to the element's
349 # address to get the member node's address.
350 elem_char_ptr = elem_ptr.cast(self._char_ptr_type)
351 node_char_ptr = elem_char_ptr + self._member_node_offset
352 return node_char_ptr.cast(self._node_ptr_type)
353 else:
354 # Node as a base: just casting from node pointer to item pointer
355 # will adjust the pointer value.
356 return elem_ptr.cast(self._node_ptr_type)
358 def _children_generator(self):
359 """Generator that yields one tuple per list item."""
361 elem_ptr = self._val["m_front"]
362 idx = 0
363 while elem_ptr != 0:
364 yield (str(idx), elem_ptr.dereference())
365 node_ptr = self._as_node_ptr(elem_ptr)
366 elem_ptr = node_ptr["next"]
367 idx += 1
369 def children(self):
370 return self._children_generator()
373 class HtabPrinter:
374 """Pretty-printer for htab_t hash tables."""
376 def __init__(self, val):
377 self._val = val
379 def display_hint(self):
380 return "array"
382 def to_string(self):
383 n = int(self._val["n_elements"]) - int(self._val["n_deleted"])
384 return "htab_t with {} elements".format(n)
386 def children(self):
387 size = int(self._val["size"])
388 entries = self._val["entries"]
390 child_i = 0
391 for entries_i in range(size):
392 entry = entries[entries_i]
393 # 0 (NULL pointer) means there's nothing, 1 (HTAB_DELETED_ENTRY)
394 # means there was something, but is now deleted.
395 if int(entry) in (0, 1):
396 continue
398 yield (str(child_i), entry)
399 child_i += 1
402 def type_lookup_function(val):
403 """A routine that returns the correct pretty printer for VAL
404 if appropriate. Returns None otherwise.
406 tag = val.type.tag
407 name = val.type.name
408 if tag == "type":
409 return StructTypePrettyPrinter(val)
410 elif tag == "main_type":
411 return StructMainTypePrettyPrinter(val)
412 elif name == "CORE_ADDR":
413 return CoreAddrPrettyPrinter(val)
414 elif tag is not None and tag.startswith("intrusive_list<"):
415 return IntrusiveListPrinter(val)
416 elif name == "htab_t":
417 return HtabPrinter(val)
418 return None
421 def register_pretty_printer(objfile):
422 """A routine to register a pretty-printer against the given OBJFILE."""
423 objfile.pretty_printers.append(type_lookup_function)
426 if __name__ == "__main__":
427 if gdb.current_objfile() is not None:
428 # This is the case where this script is being "auto-loaded"
429 # for a given objfile. Register the pretty-printer for that
430 # objfile.
431 register_pretty_printer(gdb.current_objfile())
432 else:
433 # We need to locate the objfile corresponding to the GDB
434 # executable, and register the pretty-printer for that objfile.
435 # FIXME: The condition used to match the objfile is too simplistic
436 # and will not work on Windows.
437 for objfile in gdb.objfiles():
438 if os.path.basename(objfile.filename) == "gdb":
439 objfile.pretty_printers.append(type_lookup_function)