1 # Copyright (C) 2009-2018 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 the enumerates type_instance_flag_value. This class helps us
28 recreate a list with all these flags that is easy to manipulate and sort.
29 Because all flag names start with TYPE_INSTANCE_FLAG_, a short_name
30 attribute is provided that strips this prefix.
33 name: The enumeration name (eg: "TYPE_INSTANCE_FLAG_CONST").
34 value: The associated value.
35 short_name: The enumeration name, with the suffix stripped.
37 def __init__(self
, name
, value
):
40 self
.short_name
= name
.replace("TYPE_INSTANCE_FLAG_", '')
41 def __cmp__(self
, other
):
42 """Sort by value order."""
43 return self
.value
.__cmp
__(other
.value
)
45 # A list of all existing TYPE_INSTANCE_FLAGS_* enumerations,
46 # stored as TypeFlags objects. Lazy-initialized.
49 class TypeFlagsPrinter
:
50 """A class that prints a decoded form of an instance_flags value.
52 This class uses a global named TYPE_FLAGS, which is a list of
53 all defined TypeFlag values. Using a global allows us to compute
56 This class relies on a couple of enumeration types being defined.
57 If not, then printing of the instance_flag is going to be degraded,
58 but it's not a fatal error.
60 def __init__(self
, val
):
64 if TYPE_FLAGS
is None:
65 self
.init_TYPE_FLAGS()
69 flag_list
= [flag
.short_name
for flag
in TYPE_FLAGS
70 if self
.val
& flag
.value
]
73 return "0x%x [%s]" % (self
.val
, "|".join(flag_list
))
74 def init_TYPE_FLAGS(self
):
75 """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
76 This operation requires the search of a couple of enumeration types.
77 If not found, a warning is printed on stdout, and TYPE_FLAGS is
78 set to the empty list.
80 The resulting list is sorted by increasing value, to facilitate
81 printing of the list of flags used in an instance_flags value.
86 iflags
= gdb
.lookup_type("enum type_instance_flag_value")
88 print("Warning: Cannot find enum type_instance_flag_value type.")
89 print(" `struct type' pretty-printer will be degraded")
91 TYPE_FLAGS
= [TypeFlag(field
.name
, field
.enumval
)
92 for field
in iflags
.fields()]
95 class StructTypePrettyPrinter
:
96 """Pretty-print an object of type struct type"""
97 def __init__(self
, val
):
101 fields
.append("pointer_type = %s" % self
.val
['pointer_type'])
102 fields
.append("reference_type = %s" % self
.val
['reference_type'])
103 fields
.append("chain = %s" % self
.val
['reference_type'])
104 fields
.append("instance_flags = %s"
105 % TypeFlagsPrinter(self
.val
['instance_flags']))
106 fields
.append("length = %d" % self
.val
['length'])
107 fields
.append("main_type = %s" % self
.val
['main_type'])
108 return "\n{" + ",\n ".join(fields
) + "}"
110 class StructMainTypePrettyPrinter
:
111 """Pretty-print an objet of type main_type"""
112 def __init__(self
, val
):
114 def flags_to_string(self
):
115 """struct main_type contains a series of components that
116 are one-bit ints whose name start with "flag_". For instance:
117 flag_unsigned, flag_stub, etc. In essence, these components are
118 really boolean flags, and this method prints a short synthetic
119 version of the value of all these flags. For instance, if
120 flag_unsigned and flag_static are the only components set to 1,
121 this function will return "unsigned|static".
123 fields
= [field
.name
.replace("flag_", "")
124 for field
in self
.val
.type.fields()
125 if field
.name
.startswith("flag_")
126 and self
.val
[field
.name
]]
127 return "|".join(fields
)
128 def owner_to_string(self
):
129 """Return an image of component "owner".
131 if self
.val
['flag_objfile_owned'] != 0:
132 return "%s (objfile)" % self
.val
['owner']['objfile']
134 return "%s (gdbarch)" % self
.val
['owner']['gdbarch']
135 def struct_field_location_img(self
, field_val
):
136 """Return an image of the loc component inside the given field
139 loc_val
= field_val
['loc']
140 loc_kind
= str(field_val
['loc_kind'])
141 if loc_kind
== "FIELD_LOC_KIND_BITPOS":
142 return 'bitpos = %d' % loc_val
['bitpos']
143 elif loc_kind
== "FIELD_LOC_KIND_ENUMVAL":
144 return 'enumval = %d' % loc_val
['enumval']
145 elif loc_kind
== "FIELD_LOC_KIND_PHYSADDR":
146 return 'physaddr = 0x%x' % loc_val
['physaddr']
147 elif loc_kind
== "FIELD_LOC_KIND_PHYSNAME":
148 return 'physname = %s' % loc_val
['physname']
149 elif loc_kind
== "FIELD_LOC_KIND_DWARF_BLOCK":
150 return 'dwarf_block = %s' % loc_val
['dwarf_block']
152 return 'loc = ??? (unsupported loc_kind value)'
153 def struct_field_img(self
, fieldno
):
154 """Return an image of the main_type field number FIELDNO.
156 f
= self
.val
['flds_bnds']['fields'][fieldno
]
157 label
= "flds_bnds.fields[%d]:" % fieldno
159 label
+= " (artificial)"
161 fields
.append("name = %s" % f
['name'])
162 fields
.append("type = %s" % f
['type'])
163 fields
.append("loc_kind = %s" % f
['loc_kind'])
164 fields
.append("bitsize = %d" % f
['bitsize'])
165 fields
.append(self
.struct_field_location_img(f
))
166 return label
+ "\n" + " {" + ",\n ".join(fields
) + "}"
167 def bounds_img(self
):
168 """Return an image of the main_type bounds.
170 b
= self
.val
['flds_bnds']['bounds'].dereference()
172 if b
['low_undefined'] != 0:
173 low
+= " (undefined)"
174 high
= str(b
['high'])
175 if b
['high_undefined'] != 0:
176 high
+= " (undefined)"
177 return "flds_bnds.bounds = {%s, %s}" % (low
, high
)
178 def type_specific_img(self
):
179 """Return a string image of the main_type type_specific union.
180 Only the relevant component of that union is printed (based on
181 the value of the type_specific_kind field.
183 type_specific_kind
= str(self
.val
['type_specific_field'])
184 type_specific
= self
.val
['type_specific']
185 if type_specific_kind
== "TYPE_SPECIFIC_NONE":
186 img
= 'type_specific_field = %s' % type_specific_kind
187 elif type_specific_kind
== "TYPE_SPECIFIC_CPLUS_STUFF":
188 img
= "cplus_stuff = %s" % type_specific
['cplus_stuff']
189 elif type_specific_kind
== "TYPE_SPECIFIC_GNAT_STUFF":
190 img
= ("gnat_stuff = {descriptive_type = %s}"
191 % type_specific
['gnat_stuff']['descriptive_type'])
192 elif type_specific_kind
== "TYPE_SPECIFIC_FLOATFORMAT":
193 img
= "floatformat[0..1] = %s" % type_specific
['floatformat']
194 elif type_specific_kind
== "TYPE_SPECIFIC_FUNC":
195 img
= ("calling_convention = %d"
196 % type_specific
['func_stuff']['calling_convention'])
197 # tail_call_list is not printed.
198 elif type_specific_kind
== "TYPE_SPECIFIC_SELF_TYPE":
199 img
= "self_type = %s" % type_specific
['self_type']
201 img
= ("type_specific = ??? (unknown type_secific_kind: %s)"
202 % type_specific_kind
)
206 """Return a pretty-printed image of our main_type.
209 fields
.append("name = %s" % self
.val
['name'])
210 fields
.append("tag_name = %s" % self
.val
['tag_name'])
211 fields
.append("code = %s" % self
.val
['code'])
212 fields
.append("flags = [%s]" % self
.flags_to_string())
213 fields
.append("owner = %s" % self
.owner_to_string())
214 fields
.append("target_type = %s" % self
.val
['target_type'])
215 if self
.val
['nfields'] > 0:
216 for fieldno
in range(self
.val
['nfields']):
217 fields
.append(self
.struct_field_img(fieldno
))
218 if self
.val
['code'] == gdb
.TYPE_CODE_RANGE
:
219 fields
.append(self
.bounds_img())
220 fields
.append(self
.type_specific_img())
222 return "\n{" + ",\n ".join(fields
) + "}"
224 def type_lookup_function(val
):
225 """A routine that returns the correct pretty printer for VAL
226 if appropriate. Returns None otherwise.
228 if val
.type.tag
== "type":
229 return StructTypePrettyPrinter(val
)
230 elif val
.type.tag
== "main_type":
231 return StructMainTypePrettyPrinter(val
)
234 def register_pretty_printer(objfile
):
235 """A routine to register a pretty-printer against the given OBJFILE.
237 objfile
.pretty_printers
.append(type_lookup_function
)
239 if __name__
== "__main__":
240 if gdb
.current_objfile() is not None:
241 # This is the case where this script is being "auto-loaded"
242 # for a given objfile. Register the pretty-printer for that
244 register_pretty_printer(gdb
.current_objfile())
246 # We need to locate the objfile corresponding to the GDB
247 # executable, and register the pretty-printer for that objfile.
248 # FIXME: The condition used to match the objfile is too simplistic
249 # and will not work on Windows.
250 for objfile
in gdb
.objfiles():
251 if os
.path
.basename(objfile
.filename
) == "gdb":
252 objfile
.pretty_printers
.append(type_lookup_function
)