GDB (xrefs)
types.py
Go to the documentation of this file.
1 # Type utilities.
2 # Copyright (C) 2010-2018 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 
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)
def get_basic_type(type_)
Definition: types.py:22
def __init__(self, name)
Definition: types.py:130
def register_type_printer(locus, printer)
Definition: types.py:170
def deep_items(type_)
Definition: types.py:96
def make_enum_dict(enum_type)
Definition: types.py:74
def has_field(type_, field)
Definition: types.py:44
def _get_some_type_recognizers(result, plist)
Definition: types.py:138
def instantiate(self)
Definition: types.py:134
def apply_type_recognizers(recognizers, type_obj)
Definition: types.py:160
def get_type_recognizers()
Definition: types.py:146