]> Git Repo - binutils.git/blob - gdb/python/lib/gdb/types.py
26a5027231ef393764bd2c627e6c3f2a7a18a3fb
[binutils.git] / gdb / python / lib / gdb / types.py
1 # Type utilities.
2 # Copyright (C) 2010-2017 Free Software Foundation, Inc.
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
19 import gdb
20
21
22 def 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
33     while (type_.code == gdb.TYPE_CODE_REF or
34            type_.code == gdb.TYPE_CODE_RVALUE_REF or
35            type_.code == gdb.TYPE_CODE_TYPEDEF):
36         if (type_.code == gdb.TYPE_CODE_REF or
37             type_.code == gdb.TYPE_CODE_RVALUE_REF):
38             type_ = type_.target()
39         else:
40             type_ = type_.strip_typedefs()
41     return type_.unqualified()
42
43
44 def has_field(type_, field):
45     """Return True if a type has the specified field.
46
47     Arguments:
48         type_: The type to examine.
49             It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION.
50         field: The name of the field to look up.
51
52     Returns:
53         True if the field is present either in type_ or any baseclass.
54
55     Raises:
56         TypeError: The type is not a struct or union.
57     """
58
59     type_ = get_basic_type(type_)
60     if (type_.code != gdb.TYPE_CODE_STRUCT and
61         type_.code != gdb.TYPE_CODE_UNION):
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
74 def 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():
91         # The enum's value is stored in "enumval".
92         enum_dict[field.name] = field.enumval
93     return enum_dict
94
95
96 def deep_items (type_):
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     """
108     for k, v in type_.iteritems ():
109         if k:
110             yield k, v
111         else:
112             for i in deep_items (v.type):
113                 yield i
114
115 class TypePrinter(object):
116     """The base class for type printers.
117
118     Instances of this type can be used to substitute type names during
119     'ptype'.
120
121     A type printer must have at least 'name' and 'enabled' attributes,
122     and supply an 'instantiate' method.
123
124     The 'instantiate' method must either return None, or return an
125     object which has a 'recognize' method.  This method must accept a
126     gdb.Type argument and either return None, meaning that the type
127     was not recognized, or a string naming the type.
128     """
129
130     def __init__(self, name):
131         self.name = name
132         self.enabled = True
133
134     def instantiate(self):
135         return None
136
137 # Helper function for computing the list of type recognizers.
138 def _get_some_type_recognizers(result, plist):
139     for printer in plist:
140         if printer.enabled:
141             inst = printer.instantiate()
142             if inst is not None:
143                 result.append(inst)
144     return None
145
146 def get_type_recognizers():
147     "Return a list of the enabled type recognizers for the current context."
148     result = []
149
150     # First try the objfiles.
151     for objfile in gdb.objfiles():
152         _get_some_type_recognizers(result, objfile.type_printers)
153     # Now try the program space.
154     _get_some_type_recognizers(result, gdb.current_progspace().type_printers)
155     # Finally, globals.
156     _get_some_type_recognizers(result, gdb.type_printers)
157
158     return result
159
160 def apply_type_recognizers(recognizers, type_obj):
161     """Apply the given list of type recognizers to the type TYPE_OBJ.
162     If any recognizer in the list recognizes TYPE_OBJ, returns the name
163     given by the recognizer.  Otherwise, this returns None."""
164     for r in recognizers:
165         result = r.recognize(type_obj)
166         if result is not None:
167             return result
168     return None
169
170 def register_type_printer(locus, printer):
171     """Register a type printer.
172     PRINTER is the type printer instance.
173     LOCUS is either an objfile, a program space, or None, indicating
174     global registration."""
175
176     if locus is None:
177         locus = gdb
178     locus.type_printers.insert(0, printer)
This page took 0.024388 seconds and 2 git commands to generate.