xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/gdb-gdb.py.in (revision 7f2ac4106a41b75cd7b67d794305c00f598853fb)
1# Copyright (C) 2009-2019 Free Software Foundation, Inc.
2#
3# This file is part of GDB.
4#
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.
9#
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.
14#
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/>.
17
18import gdb
19import os.path
20
21
22class TypeFlag:
23    """A class that allows us to store a flag name, its short name,
24    and its value.
25
26    In the GDB sources, struct type has a component called instance_flags
27    in which the value is the addition of various flags.  These flags are
28    defined by the enumerates type_instance_flag_value.  This class helps us
29    recreate a list with all these flags that is easy to manipulate and sort.
30    Because all flag names start with TYPE_INSTANCE_FLAG_, a short_name
31    attribute is provided that strips this prefix.
32
33    ATTRIBUTES
34      name:  The enumeration name (eg: "TYPE_INSTANCE_FLAG_CONST").
35      value: The associated value.
36      short_name: The enumeration name, with the suffix stripped.
37    """
38
39    def __init__(self, name, value):
40        self.name = name
41        self.value = value
42        self.short_name = name.replace("TYPE_INSTANCE_FLAG_", '')
43
44    def __lt__(self, other):
45        """Sort by value order."""
46        return self.value < other.value
47
48
49# A list of all existing TYPE_INSTANCE_FLAGS_* enumerations,
50# stored as TypeFlags objects.  Lazy-initialized.
51TYPE_FLAGS = None
52
53
54class TypeFlagsPrinter:
55    """A class that prints a decoded form of an instance_flags value.
56
57    This class uses a global named TYPE_FLAGS, which is a list of
58    all defined TypeFlag values.  Using a global allows us to compute
59    this list only once.
60
61    This class relies on a couple of enumeration types being defined.
62    If not, then printing of the instance_flag is going to be degraded,
63    but it's not a fatal error.
64    """
65
66    def __init__(self, val):
67        self.val = val
68
69    def __str__(self):
70        global TYPE_FLAGS
71        if TYPE_FLAGS is None:
72            self.init_TYPE_FLAGS()
73        if not self.val:
74            return "0"
75        if TYPE_FLAGS:
76            flag_list = [flag.short_name for flag in TYPE_FLAGS
77                         if self.val & flag.value]
78        else:
79            flag_list = ["???"]
80        return "0x%x [%s]" % (self.val, "|".join(flag_list))
81
82    def init_TYPE_FLAGS(self):
83        """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
84        This operation requires the search of a couple of enumeration types.
85        If not found, a warning is printed on stdout, and TYPE_FLAGS is
86        set to the empty list.
87
88        The resulting list is sorted by increasing value, to facilitate
89        printing of the list of flags used in an instance_flags value.
90        """
91        global TYPE_FLAGS
92        TYPE_FLAGS = []
93        try:
94            iflags = gdb.lookup_type("enum type_instance_flag_value")
95        except:
96            print("Warning: Cannot find enum type_instance_flag_value type.")
97            print("         `struct type' pretty-printer will be degraded")
98            return
99        TYPE_FLAGS = [TypeFlag(field.name, field.enumval)
100                      for field in iflags.fields()]
101        TYPE_FLAGS.sort()
102
103
104class StructTypePrettyPrinter:
105    """Pretty-print an object of type struct type"""
106
107    def __init__(self, val):
108        self.val = val
109
110    def to_string(self):
111        fields = []
112        fields.append("pointer_type = %s" % self.val['pointer_type'])
113        fields.append("reference_type = %s" % self.val['reference_type'])
114        fields.append("chain = %s" % self.val['reference_type'])
115        fields.append("instance_flags = %s"
116                      % TypeFlagsPrinter(self.val['instance_flags']))
117        fields.append("length = %d" % self.val['length'])
118        fields.append("main_type = %s" % self.val['main_type'])
119        return "\n{" + ",\n ".join(fields) + "}"
120
121
122class StructMainTypePrettyPrinter:
123    """Pretty-print an objet of type main_type"""
124
125    def __init__(self, val):
126        self.val = val
127
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".
136        """
137        fields = [field.name.replace("flag_", "")
138                  for field in self.val.type.fields()
139                  if field.name.startswith("flag_") and self.val[field.name]]
140        return "|".join(fields)
141
142    def owner_to_string(self):
143        """Return an image of component "owner".
144        """
145        if self.val['flag_objfile_owned'] != 0:
146            return "%s (objfile)" % self.val['owner']['objfile']
147        else:
148            return "%s (gdbarch)" % self.val['owner']['gdbarch']
149
150    def struct_field_location_img(self, field_val):
151        """Return an image of the loc component inside the given field
152        gdb.Value.
153        """
154        loc_val = field_val['loc']
155        loc_kind = str(field_val['loc_kind'])
156        if loc_kind == "FIELD_LOC_KIND_BITPOS":
157            return 'bitpos = %d' % loc_val['bitpos']
158        elif loc_kind == "FIELD_LOC_KIND_ENUMVAL":
159            return 'enumval = %d' % loc_val['enumval']
160        elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
161            return 'physaddr = 0x%x' % loc_val['physaddr']
162        elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
163            return 'physname = %s' % loc_val['physname']
164        elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
165            return 'dwarf_block = %s' % loc_val['dwarf_block']
166        else:
167            return 'loc = ??? (unsupported loc_kind value)'
168
169    def struct_field_img(self, fieldno):
170        """Return an image of the main_type field number FIELDNO.
171        """
172        f = self.val['flds_bnds']['fields'][fieldno]
173        label = "flds_bnds.fields[%d]:" % fieldno
174        if f['artificial']:
175            label += " (artificial)"
176        fields = []
177        fields.append("name = %s" % f['name'])
178        fields.append("type = %s" % f['type'])
179        fields.append("loc_kind = %s" % f['loc_kind'])
180        fields.append("bitsize = %d" % f['bitsize'])
181        fields.append(self.struct_field_location_img(f))
182        return label + "\n" + "  {" + ",\n   ".join(fields) + "}"
183
184    def bounds_img(self):
185        """Return an image of the main_type bounds.
186        """
187        b = self.val['flds_bnds']['bounds'].dereference()
188        low = str(b['low'])
189        if b['low_undefined'] != 0:
190            low += " (undefined)"
191        high = str(b['high'])
192        if b['high_undefined'] != 0:
193            high += " (undefined)"
194        return "flds_bnds.bounds = {%s, %s}" % (low, high)
195
196    def type_specific_img(self):
197        """Return a string image of the main_type type_specific union.
198        Only the relevant component of that union is printed (based on
199        the value of the type_specific_kind field.
200        """
201        type_specific_kind = str(self.val['type_specific_field'])
202        type_specific = self.val['type_specific']
203        if type_specific_kind == "TYPE_SPECIFIC_NONE":
204            img = 'type_specific_field = %s' % type_specific_kind
205        elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
206            img = "cplus_stuff = %s" % type_specific['cplus_stuff']
207        elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
208            img = ("gnat_stuff = {descriptive_type = %s}"
209                   % type_specific['gnat_stuff']['descriptive_type'])
210        elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
211            img = "floatformat[0..1] = %s" % type_specific['floatformat']
212        elif type_specific_kind == "TYPE_SPECIFIC_FUNC":
213            img = ("calling_convention = %d"
214                   % type_specific['func_stuff']['calling_convention'])
215            # tail_call_list is not printed.
216        elif type_specific_kind == "TYPE_SPECIFIC_SELF_TYPE":
217            img = "self_type = %s" % type_specific['self_type']
218        else:
219            img = ("type_specific = ??? (unknown type_secific_kind: %s)"
220                   % type_specific_kind)
221        return img
222
223    def to_string(self):
224        """Return a pretty-printed image of our main_type.
225        """
226        fields = []
227        fields.append("name = %s" % self.val['name'])
228        fields.append("code = %s" % self.val['code'])
229        fields.append("flags = [%s]" % self.flags_to_string())
230        fields.append("owner = %s" % self.owner_to_string())
231        fields.append("target_type = %s" % self.val['target_type'])
232        if self.val['nfields'] > 0:
233            for fieldno in range(self.val['nfields']):
234                fields.append(self.struct_field_img(fieldno))
235        if self.val['code'] == gdb.TYPE_CODE_RANGE:
236            fields.append(self.bounds_img())
237        fields.append(self.type_specific_img())
238
239        return "\n{" + ",\n ".join(fields) + "}"
240
241
242class CoreAddrPrettyPrinter:
243    """Print CORE_ADDR values as hex."""
244
245    def __init__(self, val):
246        self._val = val
247
248    def to_string(self):
249        return hex(int(self._val))
250
251
252def type_lookup_function(val):
253    """A routine that returns the correct pretty printer for VAL
254    if appropriate.  Returns None otherwise.
255    """
256    if val.type.tag == "type":
257        return StructTypePrettyPrinter(val)
258    elif val.type.tag == "main_type":
259        return StructMainTypePrettyPrinter(val)
260    elif val.type.name == 'CORE_ADDR':
261        return CoreAddrPrettyPrinter(val)
262    return None
263
264
265def register_pretty_printer(objfile):
266    """A routine to register a pretty-printer against the given OBJFILE.
267    """
268    objfile.pretty_printers.append(type_lookup_function)
269
270
271if __name__ == "__main__":
272    if gdb.current_objfile() is not None:
273        # This is the case where this script is being "auto-loaded"
274        # for a given objfile.  Register the pretty-printer for that
275        # objfile.
276        register_pretty_printer(gdb.current_objfile())
277    else:
278        # We need to locate the objfile corresponding to the GDB
279        # executable, and register the pretty-printer for that objfile.
280        # FIXME: The condition used to match the objfile is too simplistic
281        # and will not work on Windows.
282        for objfile in gdb.objfiles():
283            if os.path.basename(objfile.filename) == "gdb":
284                objfile.pretty_printers.append(type_lookup_function)
285