]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/lib/gdb/types.py
[gdb/testsuite] Fix gdb.arch/amd64-disp-step-self-call.exp on freebsd
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / types.py
CommitLineData
0e3509db 1# Type utilities.
d01e8234 2# Copyright (C) 2010-2025 Free Software Foundation, Inc.
0e3509db
DE
3
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17"""Utilities for working with gdb.Types."""
18
19import gdb
20
21
22def get_basic_type(type_):
23 """Return the "basic" type of a type.
24
25 Arguments:
26 type_: The type to reduce to its basic type.
27
28 Returns:
29 type_ with const/volatile is stripped away,
30 and typedefs/references converted to the underlying type.
31 """
32
13123da8
SM
33 while (
34 type_.code == gdb.TYPE_CODE_REF
35 or type_.code == gdb.TYPE_CODE_RVALUE_REF
36 or type_.code == gdb.TYPE_CODE_TYPEDEF
37 ):
38 if type_.code == gdb.TYPE_CODE_REF or type_.code == gdb.TYPE_CODE_RVALUE_REF:
0e3509db
DE
39 type_ = type_.target()
40 else:
41 type_ = type_.strip_typedefs()
42 return type_.unqualified()
43
44
45def has_field(type_, field):
46 """Return True if a type has the specified field.
47
48 Arguments:
49 type_: The type to examine.
50 It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION.
51 field: The name of the field to look up.
52
53 Returns:
54 True if the field is present either in type_ or any baseclass.
55
56 Raises:
57 TypeError: The type is not a struct or union.
58 """
59
60 type_ = get_basic_type(type_)
13123da8 61 if type_.code != gdb.TYPE_CODE_STRUCT and type_.code != gdb.TYPE_CODE_UNION:
0e3509db
DE
62 raise TypeError("not a struct or union")
63 for f in type_.fields():
64 if f.is_base_class:
65 if has_field(f.type, field):
66 return True
67 else:
68 # NOTE: f.name could be None
69 if f.name == field:
70 return True
71 return False
72
73
74def make_enum_dict(enum_type):
75 """Return a dictionary from a program's enum type.
76
77 Arguments:
78 enum_type: The enum to compute the dictionary for.
79
80 Returns:
81 The dictionary of the enum.
82
83 Raises:
84 TypeError: The type is not an enum.
85 """
86
87 if enum_type.code != gdb.TYPE_CODE_ENUM:
88 raise TypeError("not an enum type")
89 enum_dict = {}
90 for field in enum_type.fields():
14e75d8e
JK
91 # The enum's value is stored in "enumval".
92 enum_dict[field.name] = field.enumval
0e3509db 93 return enum_dict
3eaf3fa2
PK
94
95
13123da8 96def deep_items(type_):
3eaf3fa2
PK
97 """Return an iterator that recursively traverses anonymous fields.
98
99 Arguments:
100 type_: The type to traverse. It should be one of
101 gdb.TYPE_CODE_STRUCT or gdb.TYPE_CODE_UNION.
102
103 Returns:
104 an iterator similar to gdb.Type.iteritems(), i.e., it returns
105 pairs of key, value, but for any anonymous struct or union
106 field that field is traversed recursively, depth-first.
107 """
13123da8 108 for k, v in type_.iteritems():
3eaf3fa2
PK
109 if k:
110 yield k, v
111 else:
13123da8 112 for i in deep_items(v.type):
3eaf3fa2 113 yield i
18a9fc12 114
13123da8 115
18a9fc12
TT
116class TypePrinter(object):
117 """The base class for type printers.
118
119 Instances of this type can be used to substitute type names during
120 'ptype'.
121
122 A type printer must have at least 'name' and 'enabled' attributes,
123 and supply an 'instantiate' method.
124
125 The 'instantiate' method must either return None, or return an
126 object which has a 'recognize' method. This method must accept a
127 gdb.Type argument and either return None, meaning that the type
128 was not recognized, or a string naming the type.
129 """
130
131 def __init__(self, name):
132 self.name = name
133 self.enabled = True
134
135 def instantiate(self):
136 return None
137
13123da8 138
18a9fc12
TT
139# Helper function for computing the list of type recognizers.
140def _get_some_type_recognizers(result, plist):
141 for printer in plist:
142 if printer.enabled:
143 inst = printer.instantiate()
144 if inst is not None:
145 result.append(inst)
146 return None
147
13123da8 148
18a9fc12
TT
149def get_type_recognizers():
150 "Return a list of the enabled type recognizers for the current context."
151 result = []
152
153 # First try the objfiles.
154 for objfile in gdb.objfiles():
155 _get_some_type_recognizers(result, objfile.type_printers)
156 # Now try the program space.
157 _get_some_type_recognizers(result, gdb.current_progspace().type_printers)
158 # Finally, globals.
159 _get_some_type_recognizers(result, gdb.type_printers)
160
161 return result
162
13123da8 163
18a9fc12
TT
164def apply_type_recognizers(recognizers, type_obj):
165 """Apply the given list of type recognizers to the type TYPE_OBJ.
166 If any recognizer in the list recognizes TYPE_OBJ, returns the name
167 given by the recognizer. Otherwise, this returns None."""
168 for r in recognizers:
169 result = r.recognize(type_obj)
170 if result is not None:
171 return result
172 return None
173
13123da8 174
18a9fc12
TT
175def register_type_printer(locus, printer):
176 """Register a type printer.
177 PRINTER is the type printer instance.
178 LOCUS is either an objfile, a program space, or None, indicating
179 global registration."""
180
181 if locus is None:
182 locus = gdb
183 locus.type_printers.insert(0, printer)