Upgrade GDB from 7.4.1 to 7.6.1 on the vendor branch
[dragonfly.git] / contrib / gdb-7 / gdb / python / lib / gdb / types.py
1 # Type utilities.
2 # Copyright (C) 2010-2013 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_TYPEDEF):
35         if type_.code == gdb.TYPE_CODE_REF:
36             type_ = type_.target()
37         else:
38             type_ = type_.strip_typedefs()
39     return type_.unqualified()
40
41
42 def has_field(type_, field):
43     """Return True if a type has the specified field.
44
45     Arguments:
46         type_: The type to examine.
47             It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION.
48         field: The name of the field to look up.
49
50     Returns:
51         True if the field is present either in type_ or any baseclass.
52
53     Raises:
54         TypeError: The type is not a struct or union.
55     """
56
57     type_ = get_basic_type(type_)
58     if (type_.code != gdb.TYPE_CODE_STRUCT and
59         type_.code != gdb.TYPE_CODE_UNION):
60         raise TypeError("not a struct or union")
61     for f in type_.fields():
62         if f.is_base_class:
63             if has_field(f.type, field):
64                 return True
65         else:
66             # NOTE: f.name could be None
67             if f.name == field:
68                 return True
69     return False
70
71
72 def make_enum_dict(enum_type):
73     """Return a dictionary from a program's enum type.
74
75     Arguments:
76         enum_type: The enum to compute the dictionary for.
77
78     Returns:
79         The dictionary of the enum.
80
81     Raises:
82         TypeError: The type is not an enum.
83     """
84
85     if enum_type.code != gdb.TYPE_CODE_ENUM:
86         raise TypeError("not an enum type")
87     enum_dict = {}
88     for field in enum_type.fields():
89         # The enum's value is stored in "enumval".
90         enum_dict[field.name] = field.enumval
91     return enum_dict
92
93
94 def deep_items (type_):
95     """Return an iterator that recursively traverses anonymous fields.
96
97     Arguments:
98         type_: The type to traverse.  It should be one of
99         gdb.TYPE_CODE_STRUCT or gdb.TYPE_CODE_UNION.
100
101     Returns:
102         an iterator similar to gdb.Type.iteritems(), i.e., it returns
103         pairs of key, value, but for any anonymous struct or union
104         field that field is traversed recursively, depth-first.
105     """
106     for k, v in type_.iteritems ():
107         if k:
108             yield k, v
109         else:
110             for i in deep_items (v.type):
111                 yield i
112
113 class TypePrinter(object):
114     """The base class for type printers.
115
116     Instances of this type can be used to substitute type names during
117     'ptype'.
118
119     A type printer must have at least 'name' and 'enabled' attributes,
120     and supply an 'instantiate' method.
121
122     The 'instantiate' method must either return None, or return an
123     object which has a 'recognize' method.  This method must accept a
124     gdb.Type argument and either return None, meaning that the type
125     was not recognized, or a string naming the type.
126     """
127
128     def __init__(self, name):
129         self.name = name
130         self.enabled = True
131
132     def instantiate(self):
133         return None
134
135 # Helper function for computing the list of type recognizers.
136 def _get_some_type_recognizers(result, plist):
137     for printer in plist:
138         if printer.enabled:
139             inst = printer.instantiate()
140             if inst is not None:
141                 result.append(inst)
142     return None
143
144 def get_type_recognizers():
145     "Return a list of the enabled type recognizers for the current context."
146     result = []
147
148     # First try the objfiles.
149     for objfile in gdb.objfiles():
150         _get_some_type_recognizers(result, objfile.type_printers)
151     # Now try the program space.
152     _get_some_type_recognizers(result, gdb.current_progspace().type_printers)
153     # Finally, globals.
154     _get_some_type_recognizers(result, gdb.type_printers)
155
156     return result
157
158 def apply_type_recognizers(recognizers, type_obj):
159     """Apply the given list of type recognizers to the type TYPE_OBJ.
160     If any recognizer in the list recognizes TYPE_OBJ, returns the name
161     given by the recognizer.  Otherwise, this returns None."""
162     for r in recognizers:
163         result = r.recognize(type_obj)
164         if result is not None:
165             return result
166     return None
167
168 def register_type_printer(locus, printer):
169     """Register a type printer.
170     PRINTER is the type printer instance.
171     LOCUS is either an objfile, a program space, or None, indicating
172     global registration."""
173
174     if locus is None:
175         locus = gdb
176     locus.type_printers.insert(0, printer)