1 # Copyright (C) 2009, 2010, 2011 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/>.
22 """A class that allows us to store a flag name, its short name,
25 In the GDB sources, struct type has a component called instance_flags
26 in which the value is the addition of various flags. These flags are
27 defined by two enumerates: type_flag_value, and type_instance_flag_value.
28 This class helps us recreate a list with all these flags that is
29 easy to manipulate and sort. Because all flag names start with either
30 TYPE_FLAG_ or TYPE_INSTANCE_FLAG_, a short_name attribute is provided
31 that strips this prefix.
34 name: The enumeration name (eg: "TYPE_FLAG_UNSIGNED").
35 value: The associated value.
36 short_name: The enumeration name, with the suffix stripped.
38 def __init__(self, name, value):
41 self.short_name = name.replace("TYPE_FLAG_", '')
42 if self.short_name == name:
43 self.short_name = name.replace("TYPE_INSTANCE_FLAG_", '')
44 def __cmp__(self, other):
45 """Sort by value order."""
46 return self.value.__cmp__(other.value)
48 # A list of all existing TYPE_FLAGS_* and TYPE_INSTANCE_FLAGS_*
49 # enumerations, stored as TypeFlags objects. Lazy-initialized.
52 class TypeFlagsPrinter:
53 """A class that prints a decoded form of an instance_flags value.
55 This class uses a global named TYPE_FLAGS, which is a list of
56 all defined TypeFlag values. Using a global allows us to compute
59 This class relies on a couple of enumeration types being defined.
60 If not, then printing of the instance_flag is going to be degraded,
61 but it's not a fatal error.
63 def __init__(self, val):
67 if TYPE_FLAGS is None:
68 self.init_TYPE_FLAGS()
72 flag_list = [flag.short_name for flag in TYPE_FLAGS
73 if self.val & flag.value]
76 return "0x%x [%s]" % (self.val, "|".join(flag_list))
77 def init_TYPE_FLAGS(self):
78 """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
79 This operation requires the search of a couple of enumeration types.
80 If not found, a warning is printed on stdout, and TYPE_FLAGS is
81 set to the empty list.
83 The resulting list is sorted by increasing value, to facilitate
84 printing of the list of flags used in an instance_flags value.
89 flags = gdb.lookup_type("enum type_flag_value")
91 print "Warning: Cannot find enum type_flag_value type."
92 print " `struct type' pretty-printer will be degraded"
95 iflags = gdb.lookup_type("enum type_instance_flag_value")
97 print "Warning: Cannot find enum type_instance_flag_value type."
98 print " `struct type' pretty-printer will be degraded"
100 # Note: TYPE_FLAG_MIN is a duplicate of TYPE_FLAG_UNSIGNED,
101 # so exclude it from the list we are building.
102 TYPE_FLAGS = [TypeFlag(field.name, field.bitpos)
103 for field in flags.fields()
104 if field.name != 'TYPE_FLAG_MIN']
105 TYPE_FLAGS += [TypeFlag(field.name, field.bitpos)
106 for field in iflags.fields()]
109 class StructTypePrettyPrinter:
110 """Pretty-print an object of type struct type"""
111 def __init__(self, val):
115 fields.append("pointer_type = %s" % self.val['pointer_type'])
116 fields.append("reference_type = %s" % self.val['reference_type'])
117 fields.append("chain = %s" % self.val['reference_type'])
118 fields.append("instance_flags = %s"
119 % TypeFlagsPrinter(self.val['instance_flags']))
120 fields.append("length = %d" % self.val['length'])
121 fields.append("main_type = %s" % self.val['main_type'])
122 return "\n{" + ",\n ".join(fields) + "}"
124 class StructMainTypePrettyPrinter:
125 """Pretty-print an objet of type main_type"""
126 def __init__(self, val):
128 def flags_to_string(self):
129 """struct main_type contains a series of components that
130 are one-bit ints whose name start with "flag_". For instance:
131 flag_unsigned, flag_stub, etc. In essence, these components are
132 really boolean flags, and this method prints a short synthetic
133 version of the value of all these flags. For instance, if
134 flag_unsigned and flag_static are the only components set to 1,
135 this function will return "unsigned|static".
137 fields = [field.name.replace("flag_", "")
138 for field in self.val.type.fields()
139 if field.name.startswith("flag_")
140 and self.val[field.name]]
141 return "|".join(fields)
142 def owner_to_string(self):
143 """Return an image of component "owner".
145 if self.val['flag_objfile_owned'] != 0:
146 return "%s (objfile)" % self.val['owner']['objfile']
148 return "%s (gdbarch)" % self.val['owner']['gdbarch']
149 def struct_field_location_img(self, field_val):
150 """Return an image of the loc component inside the given field
153 loc_val = field_val['loc']
154 loc_kind = str(field_val['loc_kind'])
155 if loc_kind == "FIELD_LOC_KIND_BITPOS":
156 return 'bitpos = %d' % loc_val['bitpos']
157 elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
158 return 'physaddr = 0x%x' % loc_val['physaddr']
159 elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
160 return 'physname = %s' % loc_val['physname']
162 return 'loc = ??? (unsupported loc_kind value)'
163 def struct_field_img(self, fieldno):
164 """Return an image of the main_type field number FIELDNO.
166 f = self.val['flds_bnds']['fields'][fieldno]
167 label = "field[%d]:" % fieldno
169 label += " (artificial)"
171 fields.append("name = %s" % f['name'])
172 fields.append("type = %s" % f['type'])
173 fields.append("loc_kind = %s" % f['loc_kind'])
174 fields.append("bitsize = %d" % f['bitsize'])
175 fields.append(self.struct_field_location_img(f))
176 return label + "\n" + " {" + ",\n ".join(fields) + "}"
177 def bounds_img(self):
178 """Return an image of the main_type bounds.
180 b = self.val['flds_bnds']['bounds'].dereference()
182 if b['low_undefined'] != 0:
183 low += " (undefined)"
184 high = str(b['high'])
185 if b['high_undefined'] != 0:
186 high += " (undefined)"
187 return "bounds = {%s, %s}" % (low, high)
188 def type_specific_img(self):
189 """Return a string image of the main_type type_specific union.
190 Only the relevant component of that union is printed (based on
191 the value of the type_specific_kind field.
193 type_specific_kind = str(self.val['type_specific_field'])
194 type_specific = self.val['type_specific']
195 if type_specific_kind == "TYPE_SPECIFIC_NONE":
196 img = 'type_specific_field = %s' % type_specific_kind
197 elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
198 img = "cplus_stuff = %s" % type_specific['cplus_stuff']
199 elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
200 img = ("gnat_stuff = {descriptive_type = %s}"
201 % type_specific['gnat_stuff']['descriptive_type'])
202 elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
203 img = "floatformat[0..1] = %s" % type_specific['floatformat']
204 elif type_specific_kind == "TYPE_SPECIFIC_CALLING_CONVENTION":
205 img = ("calling_convention = %d"
206 % type_specific['calling_convention'])
208 img = ("type_specific = ??? (unknown type_secific_kind: %s)"
209 % type_specific_kind)
213 """Return a pretty-printed image of our main_type.
216 fields.append("name = %s" % self.val['name'])
217 fields.append("tag_name = %s" % self.val['tag_name'])
218 fields.append("code = %s" % self.val['code'])
219 fields.append("flags = [%s]" % self.flags_to_string())
220 fields.append("owner = %s" % self.owner_to_string())
221 fields.append("target_type = %s" % self.val['target_type'])
222 fields.append("vptr_basetype = %s" % self.val['vptr_basetype'])
223 if self.val['nfields'] > 0:
224 for fieldno in range(self.val['nfields']):
225 fields.append(self.struct_field_img(fieldno))
226 if self.val['code'] == gdb.TYPE_CODE_RANGE:
227 fields.append(self.bounds_img())
228 fields.append(self.type_specific_img())
230 return "\n{" + ",\n ".join(fields) + "}"
232 def type_lookup_function(val):
233 """A routine that returns the correct pretty printer for VAL
234 if appropriate. Returns None otherwise.
236 if val.type.tag == "type":
237 return StructTypePrettyPrinter(val)
238 elif val.type.tag == "main_type":
239 return StructMainTypePrettyPrinter(val)
242 def register_pretty_printer(objfile):
243 """A routine to register a pretty-printer against the given OBJFILE.
245 objfile.pretty_printers.append(type_lookup_function)
247 if __name__ == "__main__":
248 if gdb.current_objfile() is not None:
249 # This is the case where this script is being "auto-loaded"
250 # for a given objfile. Register the pretty-printer for that
252 register_pretty_printer(gdb.current_objfile())
254 # We need to locate the objfile corresponding to the GDB
255 # executable, and register the pretty-printer for that objfile.
256 # FIXME: The condition used to match the objfile is too simplistic
257 # and will not work on Windows.
258 for objfile in gdb.objfiles():
259 if os.path.basename(objfile.filename) == "gdb":
260 objfile.pretty_printers.append(type_lookup_function)